summaryrefslogtreecommitdiff
path: root/drivers/staging/rtl8192e
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-08-05 17:04:01 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-08-05 17:04:01 -0300
commit57f0f512b273f60d52568b8c6b77e17f5636edc0 (patch)
tree5e910f0e82173f4ef4f51111366a3f1299037a7b /drivers/staging/rtl8192e
Initial import
Diffstat (limited to 'drivers/staging/rtl8192e')
-rw-r--r--drivers/staging/rtl8192e/Kconfig47
-rw-r--r--drivers/staging/rtl8192e/Makefile21
-rw-r--r--drivers/staging/rtl8192e/TODO2
-rw-r--r--drivers/staging/rtl8192e/dot11d.c216
-rw-r--r--drivers/staging/rtl8192e/dot11d.h103
-rw-r--r--drivers/staging/rtl8192e/license339
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/Kconfig9
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/Makefile20
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_def.h410
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c309
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h31
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c380
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h159
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c2416
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h62
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c319
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h72
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h453
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c565
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.h51
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c1636
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h120
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h852
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h908
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_cam.c277
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_cam.h44
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.c3120
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_core.h1076
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_crypto.h382
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.c2995
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_dm.h316
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c139
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h29
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c53
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pci.c100
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pci.h51
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pm.c119
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_pm.h29
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ps.c316
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_ps.h47
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.c1341
-rw-r--r--drivers/staging/rtl8192e/rtl8192e/rtl_wx.h30
-rw-r--r--drivers/staging/rtl8192e/rtl819x_BA.h77
-rw-r--r--drivers/staging/rtl8192e/rtl819x_BAProc.c571
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HT.h428
-rw-r--r--drivers/staging/rtl8192e/rtl819x_HTProc.c919
-rw-r--r--drivers/staging/rtl8192e/rtl819x_Qos.h389
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TS.h73
-rw-r--r--drivers/staging/rtl8192e/rtl819x_TSProc.c554
-rw-r--r--drivers/staging/rtl8192e/rtllib.h2975
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt.c254
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt.h34
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_ccmp.c457
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_tkip.c779
-rw-r--r--drivers/staging/rtl8192e/rtllib_crypt_wep.c289
-rw-r--r--drivers/staging/rtl8192e/rtllib_debug.h88
-rw-r--r--drivers/staging/rtl8192e/rtllib_module.c268
-rw-r--r--drivers/staging/rtl8192e/rtllib_rx.c2678
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac.c3758
-rw-r--r--drivers/staging/rtl8192e/rtllib_softmac_wx.c661
-rw-r--r--drivers/staging/rtl8192e/rtllib_tx.c988
-rw-r--r--drivers/staging/rtl8192e/rtllib_wx.c881
62 files changed, 37085 insertions, 0 deletions
diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig
new file mode 100644
index 000000000..4602a47cd
--- /dev/null
+++ b/drivers/staging/rtl8192e/Kconfig
@@ -0,0 +1,47 @@
+config RTLLIB
+ tristate "Support for rtllib wireless devices"
+ depends on WLAN && m
+ default n
+ select LIB80211
+ ---help---
+ If you have a wireless card that uses rtllib, say
+ Y. Currently the only card is the rtl8192e.
+
+ If unsure, say N.
+
+if RTLLIB
+
+config RTLLIB_CRYPTO_CCMP
+ tristate "Support for rtllib CCMP crypto"
+ depends on RTLLIB
+ select CRYPTO_AES
+ default y
+ ---help---
+ CCMP crypto driver for rtllib.
+
+ If you enabled RTLLIB, you want this.
+
+config RTLLIB_CRYPTO_TKIP
+ tristate "Support for rtllib TKIP crypto"
+ depends on RTLLIB
+ select CRYPTO_ARC4
+ select CRYPTO_MICHAEL_MIC
+ default y
+ ---help---
+ TKIP crypto driver for rtllib.
+
+ If you enabled RTLLIB, you want this.
+
+config RTLLIB_CRYPTO_WEP
+ tristate "Support for rtllib WEP crypto"
+ select CRYPTO_ARC4
+ depends on RTLLIB
+ default y
+ ---help---
+ TKIP crypto driver for rtllib.
+
+ If you enabled RTLLIB, you want this.
+
+source "drivers/staging/rtl8192e/rtl8192e/Kconfig"
+
+endif
diff --git a/drivers/staging/rtl8192e/Makefile b/drivers/staging/rtl8192e/Makefile
new file mode 100644
index 000000000..cb18db74d
--- /dev/null
+++ b/drivers/staging/rtl8192e/Makefile
@@ -0,0 +1,21 @@
+rtllib-objs := \
+ dot11d.o \
+ rtllib_module.o \
+ rtllib_rx.o \
+ rtllib_tx.o \
+ rtllib_wx.o \
+ rtllib_softmac.o \
+ rtllib_softmac_wx.o \
+ rtl819x_BAProc.o \
+ rtl819x_HTProc.o \
+ rtl819x_TSProc.o
+
+obj-$(CONFIG_RTLLIB) += rtllib.o
+
+obj-$(CONFIG_RTLLIB_CRYPTO_CCMP) += rtllib_crypt_ccmp.o
+obj-$(CONFIG_RTLLIB_CRYPTO_TKIP) += rtllib_crypt_tkip.o
+obj-$(CONFIG_RTLLIB_CRYPTO_WEP) += rtllib_crypt_wep.o
+
+obj-$(CONFIG_RTL8192E) += rtl8192e/
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/staging/rtl8192e/TODO b/drivers/staging/rtl8192e/TODO
new file mode 100644
index 000000000..d51f159d1
--- /dev/null
+++ b/drivers/staging/rtl8192e/TODO
@@ -0,0 +1,2 @@
+* merge into drivers/net/wireless/rtllib/rtl8192e
+* clean up function naming
diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c
new file mode 100644
index 000000000..ef9da863c
--- /dev/null
+++ b/drivers/staging/rtl8192e/dot11d.c
@@ -0,0 +1,216 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "dot11d.h"
+
+struct channel_list {
+ u8 Channel[32];
+ u8 Len;
+};
+
+static struct channel_list ChannelPlan[] = {
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64,
+ 149, 153, 157, 161, 165}, 24},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56,
+ 60, 64}, 21},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52,
+ 56, 60, 64}, 22},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52,
+ 56, 60, 64}, 22},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52,
+ 56, 60, 64}, 22},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52,
+ 56, 60, 64}, 22},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52,
+ 56, 60, 64}, 21}
+};
+
+void dot11d_init(struct rtllib_device *ieee)
+{
+ struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee);
+
+ pDot11dInfo->bEnabled = false;
+
+ pDot11dInfo->State = DOT11D_STATE_NONE;
+ pDot11dInfo->CountryIeLen = 0;
+ memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
+ memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
+ RESET_CIE_WATCHDOG(ieee);
+
+}
+EXPORT_SYMBOL(dot11d_init);
+
+void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee)
+{
+ int i, max_chan = 14, min_chan = 1;
+
+ ieee->bGlobalDomain = false;
+
+ if (ChannelPlan[channel_plan].Len != 0) {
+ memset(GET_DOT11D_INFO(ieee)->channel_map, 0,
+ sizeof(GET_DOT11D_INFO(ieee)->channel_map));
+ for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
+ if (ChannelPlan[channel_plan].Channel[i] < min_chan ||
+ ChannelPlan[channel_plan].Channel[i] > max_chan)
+ break;
+ GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan
+ [channel_plan].Channel[i]] = 1;
+ }
+ }
+
+ switch (channel_plan) {
+ case COUNTRY_CODE_GLOBAL_DOMAIN:
+ ieee->bGlobalDomain = true;
+ for (i = 12; i <= 14; i++)
+ GET_DOT11D_INFO(ieee)->channel_map[i] = 2;
+ ieee->IbssStartChnl = 10;
+ ieee->ibss_maxjoin_chal = 11;
+ break;
+
+ case COUNTRY_CODE_WORLD_WIDE_13:
+ for (i = 12; i <= 13; i++)
+ GET_DOT11D_INFO(ieee)->channel_map[i] = 2;
+ ieee->IbssStartChnl = 10;
+ ieee->ibss_maxjoin_chal = 11;
+ break;
+
+ default:
+ ieee->IbssStartChnl = 1;
+ ieee->ibss_maxjoin_chal = 14;
+ break;
+ }
+}
+EXPORT_SYMBOL(Dot11d_Channelmap);
+
+
+void Dot11d_Reset(struct rtllib_device *ieee)
+{
+ struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee);
+ u32 i;
+
+ memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
+ memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
+ for (i = 1; i <= 11; i++)
+ (pDot11dInfo->channel_map)[i] = 1;
+ for (i = 12; i <= 14; i++)
+ (pDot11dInfo->channel_map)[i] = 2;
+ pDot11dInfo->State = DOT11D_STATE_NONE;
+ pDot11dInfo->CountryIeLen = 0;
+ RESET_CIE_WATCHDOG(ieee);
+}
+
+void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr,
+ u16 CoutryIeLen, u8 *pCoutryIe)
+{
+ struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
+ u8 i, j, NumTriples, MaxChnlNum;
+ struct chnl_txpow_triple *pTriple;
+
+ memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
+ memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
+ MaxChnlNum = 0;
+ NumTriples = (CoutryIeLen - 3) / 3;
+ pTriple = (struct chnl_txpow_triple *)(pCoutryIe + 3);
+ for (i = 0; i < NumTriples; i++) {
+ if (MaxChnlNum >= pTriple->FirstChnl) {
+ netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
+ return;
+ }
+ if (MAX_CHANNEL_NUMBER < (pTriple->FirstChnl +
+ pTriple->NumChnls)) {
+ netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
+ return;
+ }
+
+ for (j = 0; j < pTriple->NumChnls; j++) {
+ pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
+ pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] =
+ pTriple->MaxTxPowerInDbm;
+ MaxChnlNum = pTriple->FirstChnl + j;
+ }
+
+ pTriple = (struct chnl_txpow_triple *)((u8 *)pTriple + 3);
+ }
+
+ UPDATE_CIE_SRC(dev, pTaddr);
+
+ pDot11dInfo->CountryIeLen = CoutryIeLen;
+ memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen);
+ pDot11dInfo->State = DOT11D_STATE_LEARNED;
+}
+
+u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib_device *dev, u8 Channel)
+{
+ struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
+ u8 MaxTxPwrInDbm = 255;
+
+ if (MAX_CHANNEL_NUMBER < Channel) {
+ netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
+ return MaxTxPwrInDbm;
+ }
+ if (pDot11dInfo->channel_map[Channel])
+ MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
+
+ return MaxTxPwrInDbm;
+}
+
+void DOT11D_ScanComplete(struct rtllib_device *dev)
+{
+ struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
+
+ switch (pDot11dInfo->State) {
+ case DOT11D_STATE_LEARNED:
+ pDot11dInfo->State = DOT11D_STATE_DONE;
+ break;
+ case DOT11D_STATE_DONE:
+ Dot11d_Reset(dev);
+ break;
+ case DOT11D_STATE_NONE:
+ break;
+ }
+}
+
+int ToLegalChannel(struct rtllib_device *dev, u8 channel)
+{
+ struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
+ u8 default_chn = 0;
+ u32 i;
+
+ for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
+ if (pDot11dInfo->channel_map[i] > 0) {
+ default_chn = i;
+ break;
+ }
+ }
+
+ if (MAX_CHANNEL_NUMBER < channel) {
+ netdev_err(dev->dev, "%s(): Invalid Channel\n", __func__);
+ return default_chn;
+ }
+
+ if (pDot11dInfo->channel_map[channel] > 0)
+ return channel;
+
+ return default_chn;
+}
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
new file mode 100644
index 000000000..aad339439
--- /dev/null
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -0,0 +1,103 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_DOT11D_H
+#define __INC_DOT11D_H
+
+#include "rtllib.h"
+
+
+
+struct chnl_txpow_triple {
+ u8 FirstChnl;
+ u8 NumChnls;
+ u8 MaxTxPowerInDbm;
+};
+
+enum dot11d_state {
+ DOT11D_STATE_NONE = 0,
+ DOT11D_STATE_LEARNED,
+ DOT11D_STATE_DONE,
+};
+
+/**
+ * struct rt_dot11d_info * @CountryIeLen: value greater than 0 if @CountryIeBuf contains
+ * valid country information element.
+ * @channel_map: holds channel values
+ * 0 - invalid,
+ * 1 - valid (active scan),
+ * 2 - valid (passive scan)
+ * @CountryIeSrcAddr - Source AP of the country IE
+ */
+
+struct rt_dot11d_info {
+
+ bool bEnabled;
+
+ u16 CountryIeLen;
+ u8 CountryIeBuf[MAX_IE_LEN];
+ u8 CountryIeSrcAddr[6];
+ u8 CountryIeWatchdog;
+
+ u8 channel_map[MAX_CHANNEL_NUMBER+1];
+ u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
+
+ enum dot11d_state State;
+};
+
+static inline void cpMacAddr(unsigned char *des, unsigned char *src)
+{
+ memcpy(des, src, 6);
+}
+
+#define GET_DOT11D_INFO(__pIeeeDev) \
+ ((struct rt_dot11d_info *)((__pIeeeDev)->pDot11dInfo))
+
+#define IS_DOT11D_ENABLE(__pIeeeDev) \
+ (GET_DOT11D_INFO(__pIeeeDev)->bEnabled)
+#define IS_COUNTRY_IE_VALID(__pIeeeDev) \
+ (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
+
+#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) \
+ ether_addr_equal_unaligned(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, \
+ __pTa)
+#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) \
+ cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
+
+#define CIE_WATCHDOG_TH 1
+#define GET_CIE_WATCHDOG(__pIeeeDev) \
+ (GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog)
+static inline void RESET_CIE_WATCHDOG(struct rtllib_device *__pIeeeDev)
+{
+ GET_CIE_WATCHDOG(__pIeeeDev) = 0;
+}
+#define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev))
+
+#define IS_DOT11D_STATE_DONE(__pIeeeDev) \
+ (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
+
+void dot11d_init(struct rtllib_device *dev);
+void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee);
+void Dot11d_Reset(struct rtllib_device *dev);
+void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr,
+ u16 CoutryIeLen, u8 *pCoutryIe);
+u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib_device *dev, u8 Channel);
+void DOT11D_ScanComplete(struct rtllib_device *dev);
+int ToLegalChannel(struct rtllib_device *dev, u8 channel);
+
+#endif
diff --git a/drivers/staging/rtl8192e/license b/drivers/staging/rtl8192e/license
new file mode 100644
index 000000000..4bea9fa60
--- /dev/null
+++ b/drivers/staging/rtl8192e/license
@@ -0,0 +1,339 @@
+
+"This software program is licensed subject to the GNU General Public License
+(GPL). Version 2, June 1991, available at
+<http:
+
+GNU General Public License
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies of this license
+document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public License is intended
+to guarantee your freedom to share and change free software--to make sure
+the software is free for all its users. This General Public License applies
+to most of the Free Software Foundation's software and to any other program
+whose authors commit to using it. (Some other Free Software Foundation
+software is covered by the GNU Library General Public License instead.) You
+can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you
+wish), that you receive source code or can get it if you want it, that you
+can change the software or use pieces of it in new free programs; and that
+you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or
+for a fee, you must give the recipients all the rights that you have. You
+must make sure that they, too, receive or can get the source code. And you
+must show them these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2)
+offer you this license which gives you legal permission to copy, distribute
+and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that
+everyone understands that there is no warranty for this free software. If
+the software is modified by someone else and passed on, we want its
+recipients to know that what they have is not the original, so that any
+problems introduced by others will not reflect on the original authors'
+reputations.
+
+Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that redistributors of a free program will
+individually obtain patent licenses, in effect making the program
+proprietary. To prevent this, we have made it clear that any patent must be
+licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification
+follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice
+ placed by the copyright holder saying it may be distributed under the
+ terms of this General Public License. The "Program", below, refers to any
+ such program or work, and a "work based on the Program" means either the
+ Program or any derivative work under copyright law: that is to say, a
+ work containing the Program or a portion of it, either verbatim or with
+ modifications and/or translated into another language. (Hereinafter,
+ translation is included without limitation in the term "modification".)
+ Each licensee is addressed as "you".
+
+ Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of running
+ the Program is not restricted, and the output from the Program is covered
+ only if its contents constitute a work based on the Program (independent
+ of having been made by running the Program). Whether that is true depends
+ on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code
+ as you receive it, in any medium, provided that you conspicuously and
+ appropriately publish on each copy an appropriate copyright notice and
+ disclaimer of warranty; keep intact all the notices that refer to this
+ License and to the absence of any warranty; and give any other recipients
+ of the Program a copy of this License along with the Program.
+
+ You may charge a fee for the physical act of transferring a copy, and you
+ may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it,
+ thus forming a work based on the Program, and copy and distribute such
+ modifications or work under the terms of Section 1 above, provided that
+ you also meet all of these conditions:
+
+ * a) You must cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change.
+
+ * b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any part
+ thereof, to be licensed as a whole at no charge to all third parties
+ under the terms of this License.
+
+ * c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive
+ use in the most ordinary way, to print or display an announcement
+ including an appropriate copyright notice and a notice that there is
+ no warranty (or else, saying that you provide a warranty) and that
+ users may redistribute the program under these conditions, and
+ telling the user how to view a copy of this License. (Exception: if
+ the Program itself is interactive but does not normally print such
+ an announcement, your work based on the Program is not required to
+ print an announcement.)
+
+ These requirements apply to the modified work as a whole. If identifiable
+ sections of that work are not derived from the Program, and can be
+ reasonably considered independent and separate works in themselves, then
+ this License, and its terms, do not apply to those sections when you
+ distribute them as separate works. But when you distribute the same
+ sections as part of a whole which is a work based on the Program, the
+ distribution of the whole must be on the terms of this License, whose
+ permissions for other licensees extend to the entire whole, and thus to
+ each and every part regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.
+
+ In addition, mere aggregation of another work not based on the Program
+ with the Program (or with a work based on the Program) on a volume of a
+ storage or distribution medium does not bring the other work under the
+ scope of this License.
+
+3. You may copy and distribute the Program (or a work based on it, under
+ Section 2) in object code or executable form under the terms of Sections
+ 1 and 2 above provided that you also do one of the following:
+
+ * a) Accompany it with the complete corresponding machine-readable source
+ code, which must be distributed under the terms of Sections 1 and 2
+ above on a medium customarily used for software interchange; or,
+
+ * b) Accompany it with a written offer, valid for at least three years,
+ to give any third party, for a charge no more than your cost of
+ physically performing source distribution, a complete machine-
+ readable copy of the corresponding source code, to be distributed
+ under the terms of Sections 1 and 2 above on a medium customarily
+ used for software interchange; or,
+
+ * c) Accompany it with the information you received as to the offer to
+ distribute corresponding source code. (This alternative is allowed
+ only for noncommercial distribution and only if you received the
+ program in object code or executable form with such an offer, in
+ accord with Subsection b above.)
+
+ The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source code
+ means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to control
+ compilation and installation of the executable. However, as a special
+ exception, the source code distributed need not include anything that is
+ normally distributed (in either source or binary form) with the major
+ components (compiler, kernel, and so on) of the operating system on which
+ the executable runs, unless that component itself accompanies the
+ executable.
+
+ If distribution of executable or object code is made by offering access
+ to copy from a designated place, then offering equivalent access to copy
+ the source code from the same place counts as distribution of the source
+ code, even though third parties are not compelled to copy the source
+ along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as
+ expressly provided under this License. Any attempt otherwise to copy,
+ modify, sublicense or distribute the Program is void, and will
+ automatically terminate your rights under this License. However, parties
+ who have received copies, or rights, from you under this License will not
+ have their licenses terminated so long as such parties remain in full
+ compliance.
+
+5. You are not required to accept this License, since you have not signed
+ it. However, nothing else grants you permission to modify or distribute
+ the Program or its derivative works. These actions are prohibited by law
+ if you do not accept this License. Therefore, by modifying or
+ distributing the Program (or any work based on the Program), you
+ indicate your acceptance of this License to do so, and all its terms and
+ conditions for copying, distributing or modifying the Program or works
+ based on it.
+
+6. Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further restrictions
+ on the recipients' exercise of the rights granted herein. You are not
+ responsible for enforcing compliance by third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot distribute
+ so as to satisfy simultaneously your obligations under this License and
+ any other pertinent obligations, then as a consequence you may not
+ distribute the Program at all. For example, if a patent license would
+ not permit royalty-free redistribution of the Program by all those who
+ receive copies directly or indirectly through you, then the only way you
+ could satisfy both it and this License would be to refrain entirely from
+ distribution of the Program.
+
+ If any portion of this section is held invalid or unenforceable under any
+ particular circumstance, the balance of the section is intended to apply
+ and the section as a whole is intended to apply in other circumstances.
+
+ It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is implemented
+ by public license practices. Many people have made generous contributions
+ to the wide range of software distributed through that system in
+ reliance on consistent application of that system; it is up to the
+ author/donor to decide if he or she is willing to distribute software
+ through any other system and a licensee cannot impose that choice.
+
+ This section is intended to make thoroughly clear what is believed to be
+ a consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain
+ countries either by patents or by copyrighted interfaces, the original
+ copyright holder who places the Program under this License may add an
+ explicit geographical distribution limitation excluding those countries,
+ so that distribution is permitted only in or among countries not thus
+ excluded. In such case, this License incorporates the limitation as if
+ written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of
+ the General Public License from time to time. Such new versions will be
+ similar in spirit to the present version, but may differ in detail to
+ address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and "any
+ later version", you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a version
+ number of this License, you may choose any version ever published by the
+ Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs
+ whose distribution conditions are different, write to the author to ask
+ for permission. For software which is copyrighted by the Free Software
+ Foundation, write to the Free Software Foundation; we sometimes make
+ exceptions for this. Our decision will be guided by the two goals of
+ preserving the free status of all derivatives of our free software and
+ of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+ EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
+ YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+ NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
+ DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+ DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM
+ (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
+ INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
+ THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
+ OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it free
+software which everyone can redistribute and change under these terms.
+
+To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey the
+exclusion of warranty; and each file should have at least the "copyright"
+line and a pointer to where the full notice is found.
+
+one line to give the program's name and an idea of what it does.
+Copyright (C) yyyy name of author
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59
+Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this when
+it starts in an interactive mode:
+
+Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
+with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free
+software, and you are welcome to redistribute it under certain conditions;
+type 'show c' for details.
+
+The hypothetical commands 'show w' and 'show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may be
+called something other than 'show w' and 'show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+'Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+signature of Ty Coon, 1 April 1989
+Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General Public
+License instead of this License.
diff --git a/drivers/staging/rtl8192e/rtl8192e/Kconfig b/drivers/staging/rtl8192e/rtl8192e/Kconfig
new file mode 100644
index 000000000..282e293da
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/Kconfig
@@ -0,0 +1,9 @@
+config RTL8192E
+ tristate "RealTek RTL8192E Wireless LAN NIC driver"
+ depends on PCI && WLAN && RTLLIB
+ depends on m
+ select WIRELESS_EXT
+ select WEXT_PRIV
+ select CRYPTO
+ select FW_LOADER
+ ---help---
diff --git a/drivers/staging/rtl8192e/rtl8192e/Makefile b/drivers/staging/rtl8192e/rtl8192e/Makefile
new file mode 100644
index 000000000..a2c4fb4ba
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/Makefile
@@ -0,0 +1,20 @@
+r8192e_pci-objs := \
+ r8192E_dev.o \
+ r8192E_phy.o \
+ r8192E_firmware.o \
+ r8192E_cmdpkt.o \
+ r8192E_hwimg.o \
+ r8190P_rtl8256.o \
+ rtl_cam.o \
+ rtl_core.o \
+ rtl_dm.o \
+ rtl_eeprom.o \
+ rtl_ethtool.o \
+ rtl_pci.o \
+ rtl_pm.o \
+ rtl_ps.o \
+ rtl_wx.o \
+
+obj-$(CONFIG_RTL8192E) += r8192e_pci.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
new file mode 100644
index 000000000..b7bb71fa9
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
@@ -0,0 +1,410 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+
+#ifndef R8190P_DEF_H
+#define R8190P_DEF_H
+
+#include <linux/types.h>
+
+#define MAX_SILENT_RESET_RX_SLOT_NUM 10
+
+#define RX_MPDU_QUEUE 0
+#define RX_CMD_QUEUE 1
+
+
+enum rtl819x_loopback {
+ RTL819X_NO_LOOPBACK = 0,
+ RTL819X_MAC_LOOPBACK = 1,
+ RTL819X_DMA_LOOPBACK = 2,
+ RTL819X_CCK_LOOPBACK = 3,
+};
+
+
+#define RESET_DELAY_8185 20
+
+#define RT_IBSS_INT_MASKS (IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER)
+
+#define DESC90_RATE1M 0x00
+#define DESC90_RATE2M 0x01
+#define DESC90_RATE5_5M 0x02
+#define DESC90_RATE11M 0x03
+#define DESC90_RATE6M 0x04
+#define DESC90_RATE9M 0x05
+#define DESC90_RATE12M 0x06
+#define DESC90_RATE18M 0x07
+#define DESC90_RATE24M 0x08
+#define DESC90_RATE36M 0x09
+#define DESC90_RATE48M 0x0a
+#define DESC90_RATE54M 0x0b
+#define DESC90_RATEMCS0 0x00
+#define DESC90_RATEMCS1 0x01
+#define DESC90_RATEMCS2 0x02
+#define DESC90_RATEMCS3 0x03
+#define DESC90_RATEMCS4 0x04
+#define DESC90_RATEMCS5 0x05
+#define DESC90_RATEMCS6 0x06
+#define DESC90_RATEMCS7 0x07
+#define DESC90_RATEMCS8 0x08
+#define DESC90_RATEMCS9 0x09
+#define DESC90_RATEMCS10 0x0a
+#define DESC90_RATEMCS11 0x0b
+#define DESC90_RATEMCS12 0x0c
+#define DESC90_RATEMCS13 0x0d
+#define DESC90_RATEMCS14 0x0e
+#define DESC90_RATEMCS15 0x0f
+#define DESC90_RATEMCS32 0x20
+
+#define SHORT_SLOT_TIME 9
+#define NON_SHORT_SLOT_TIME 20
+
+
+#define MAX_LINES_HWCONFIG_TXT 1000
+#define MAX_BYTES_LINE_HWCONFIG_TXT 128
+
+#define SW_THREE_WIRE 0
+#define HW_THREE_WIRE 2
+
+#define BT_DEMO_BOARD 0
+#define BT_QA_BOARD 1
+#define BT_FPGA 2
+
+#define RX_SMOOTH 20
+
+#define QSLT_BK 0x1
+#define QSLT_BE 0x0
+#define QSLT_VI 0x4
+#define QSLT_VO 0x6
+#define QSLT_BEACON 0x10
+#define QSLT_HIGH 0x11
+#define QSLT_MGNT 0x12
+#define QSLT_CMD 0x13
+
+#define NUM_OF_FIRMWARE_QUEUE 10
+#define NUM_OF_PAGES_IN_FW 0x100
+#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x007
+#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x0aa
+#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x024
+#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x007
+#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0
+#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x2
+#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x10
+#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0
+#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x4
+#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xd
+
+#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM 0x026
+#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM 0x048
+#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM 0x048
+#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM 0x026
+#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM 0x00
+
+#define APPLIED_RESERVED_QUEUE_IN_FW 0x80000000
+#define RSVD_FW_QUEUE_PAGE_BK_SHIFT 0x00
+#define RSVD_FW_QUEUE_PAGE_BE_SHIFT 0x08
+#define RSVD_FW_QUEUE_PAGE_VI_SHIFT 0x10
+#define RSVD_FW_QUEUE_PAGE_VO_SHIFT 0x18
+#define RSVD_FW_QUEUE_PAGE_MGNT_SHIFT 0x10
+#define RSVD_FW_QUEUE_PAGE_BCN_SHIFT 0x00
+#define RSVD_FW_QUEUE_PAGE_PUB_SHIFT 0x08
+
+#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0
+#define HAL_PRIME_CHNL_OFFSET_LOWER 1
+#define HAL_PRIME_CHNL_OFFSET_UPPER 2
+
+
+enum version_8190_loopback {
+ VERSION_8190_BD = 0x3,
+ VERSION_8190_BE
+};
+
+#define IC_VersionCut_C 0x2
+#define IC_VersionCut_D 0x3
+#define IC_VersionCut_E 0x4
+
+enum rf_optype {
+ RF_OP_By_SW_3wire = 0,
+ RF_OP_By_FW,
+ RF_OP_MAX
+};
+
+
+enum power_save_mode {
+ POWER_SAVE_MODE_ACTIVE,
+ POWER_SAVE_MODE_SAVE,
+};
+
+enum interface_select_8190pci {
+ INTF_SEL1_MINICARD = 0,
+ INTF_SEL0_PCIE = 1,
+ INTF_SEL2_RSV = 2,
+ INTF_SEL3_RSV = 3,
+};
+
+struct bb_reg_definition {
+ u32 rfintfs;
+ u32 rfintfi;
+ u32 rfintfo;
+ u32 rfintfe;
+ u32 rf3wireOffset;
+ u32 rfLSSI_Select;
+ u32 rfTxGainStage;
+ u32 rfHSSIPara1;
+ u32 rfHSSIPara2;
+ u32 rfSwitchControl;
+ u32 rfAGCControl1;
+ u32 rfAGCControl2;
+ u32 rfRxIQImbalance;
+ u32 rfRxAFE;
+ u32 rfTxIQImbalance;
+ u32 rfTxAFE;
+ u32 rfLSSIReadBack;
+ u32 rfLSSIReadBackPi;
+};
+
+struct tx_fwinfo {
+ u8 TxRate:7;
+ u8 CtsEnable:1;
+ u8 RtsRate:7;
+ u8 RtsEnable:1;
+ u8 TxHT:1;
+ u8 Short:1;
+ u8 TxBandwidth:1;
+ u8 TxSubCarrier:2;
+ u8 STBC:2;
+ u8 AllowAggregation:1;
+ u8 RtsHT:1;
+ u8 RtsShort:1;
+ u8 RtsBandwidth:1;
+ u8 RtsSubcarrier:2;
+ u8 RtsSTBC:2;
+ u8 EnableCPUDur:1;
+
+ u32 RxMF:2;
+ u32 RxAMD:3;
+ u32 Reserved1:3;
+ u32 TxAGCOffset:4;
+ u32 TxAGCSign:1;
+ u32 Tx_INFO_RSVD:6;
+ u32 PacketID:13;
+};
+
+struct tx_fwinfo_8190pci {
+ u8 TxRate:7;
+ u8 CtsEnable:1;
+ u8 RtsRate:7;
+ u8 RtsEnable:1;
+ u8 TxHT:1;
+ u8 Short:1;
+ u8 TxBandwidth:1;
+ u8 TxSubCarrier:2;
+ u8 STBC:2;
+ u8 AllowAggregation:1;
+ u8 RtsHT:1;
+ u8 RtsShort:1;
+ u8 RtsBandwidth:1;
+ u8 RtsSubcarrier:2;
+ u8 RtsSTBC:2;
+ u8 EnableCPUDur:1;
+
+ u32 RxMF:2;
+ u32 RxAMD:3;
+ u32 TxPerPktInfoFeedback:1;
+ u32 Reserved1:2;
+ u32 TxAGCOffset:4;
+ u32 TxAGCSign:1;
+ u32 RAW_TXD:1;
+ u32 Retry_Limit:4;
+ u32 Reserved2:1;
+ u32 PacketID:13;
+
+
+};
+
+
+#define TX_DESC_SIZE 32
+
+#define TX_DESC_CMD_SIZE 32
+
+
+#define TX_STATUS_DESC_SIZE 32
+
+#define TX_FWINFO_SIZE 8
+
+
+#define RX_DESC_SIZE 16
+
+#define RX_STATUS_DESC_SIZE 16
+
+#define RX_DRIVER_INFO_SIZE 8
+
+struct log_int_8190 {
+ u32 nIMR_COMDOK;
+ u32 nIMR_MGNTDOK;
+ u32 nIMR_HIGH;
+ u32 nIMR_VODOK;
+ u32 nIMR_VIDOK;
+ u32 nIMR_BEDOK;
+ u32 nIMR_BKDOK;
+ u32 nIMR_ROK;
+ u32 nIMR_RCOK;
+ u32 nIMR_TBDOK;
+ u32 nIMR_BDOK;
+ u32 nIMR_RXFOVW;
+};
+
+struct phy_ofdm_rx_status_rxsc_sgien_exintfflag {
+ u8 reserved:4;
+ u8 rxsc:2;
+ u8 sgi_en:1;
+ u8 ex_intf_flag:1;
+};
+
+struct phy_sts_ofdm_819xpci {
+ u8 trsw_gain_X[4];
+ u8 pwdb_all;
+ u8 cfosho_X[4];
+ u8 cfotail_X[4];
+ u8 rxevm_X[2];
+ u8 rxsnr_X[4];
+ u8 pdsnr_X[2];
+ u8 csi_current_X[2];
+ u8 csi_target_X[2];
+ u8 sigevm;
+ u8 max_ex_pwr;
+ u8 sgi_en;
+ u8 rxsc_sgien_exflg;
+};
+
+struct phy_sts_cck_819xpci {
+ u8 adc_pwdb_X[4];
+ u8 sq_rpt;
+ u8 cck_agc_rpt;
+};
+
+
+#define PHY_RSSI_SLID_WIN_MAX 100
+#define PHY_Beacon_RSSI_SLID_WIN_MAX 10
+
+struct tx_desc {
+ u16 PktSize;
+ u8 Offset;
+ u8 Reserved1:3;
+ u8 CmdInit:1;
+ u8 LastSeg:1;
+ u8 FirstSeg:1;
+ u8 LINIP:1;
+ u8 OWN:1;
+
+ u8 TxFWInfoSize;
+ u8 RATid:3;
+ u8 DISFB:1;
+ u8 USERATE:1;
+ u8 MOREFRAG:1;
+ u8 NoEnc:1;
+ u8 PIFS:1;
+ u8 QueueSelect:5;
+ u8 NoACM:1;
+ u8 Resv:2;
+ u8 SecCAMID:5;
+ u8 SecDescAssign:1;
+ u8 SecType:2;
+
+ u16 TxBufferSize;
+ u8 PktId:7;
+ u8 Resv1:1;
+ u8 Reserved2;
+
+ u32 TxBuffAddr;
+
+ u32 NextDescAddress;
+
+ u32 Reserved5;
+ u32 Reserved6;
+ u32 Reserved7;
+};
+
+
+struct tx_desc_cmd {
+ u16 PktSize;
+ u8 Reserved1;
+ u8 CmdType:3;
+ u8 CmdInit:1;
+ u8 LastSeg:1;
+ u8 FirstSeg:1;
+ u8 LINIP:1;
+ u8 OWN:1;
+
+ u16 ElementReport;
+ u16 Reserved2;
+
+ u16 TxBufferSize;
+ u16 Reserved3;
+
+ u32 TxBuffAddr;
+ u32 NextDescAddress;
+ u32 Reserved4;
+ u32 Reserved5;
+ u32 Reserved6;
+};
+
+struct rx_desc {
+ u16 Length:14;
+ u16 CRC32:1;
+ u16 ICV:1;
+ u8 RxDrvInfoSize;
+ u8 Shift:2;
+ u8 PHYStatus:1;
+ u8 SWDec:1;
+ u8 LastSeg:1;
+ u8 FirstSeg:1;
+ u8 EOR:1;
+ u8 OWN:1;
+
+ u32 Reserved2;
+
+ u32 Reserved3;
+
+ u32 BufferAddress;
+
+};
+
+
+struct rx_fwinfo {
+ u16 Reserved1:12;
+ u16 PartAggr:1;
+ u16 FirstAGGR:1;
+ u16 Reserved2:2;
+
+ u8 RxRate:7;
+ u8 RxHT:1;
+
+ u8 BW:1;
+ u8 SPLCP:1;
+ u8 Reserved3:2;
+ u8 PAM:1;
+ u8 Mcast:1;
+ u8 Bcast:1;
+ u8 Reserved4:1;
+
+ u32 TSFL;
+
+};
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
new file mode 100644
index 000000000..01d2201af
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
@@ -0,0 +1,309 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#include "rtl_core.h"
+#include "r8192E_phyreg.h"
+#include "r8192E_phy.h"
+#include "r8190P_rtl8256.h"
+
+void PHY_SetRF8256Bandwidth(struct net_device *dev,
+ enum ht_channel_width Bandwidth)
+{
+ u8 eRFPath;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ for (eRFPath = 0; eRFPath < priv->NumTotalRFPath; eRFPath++) {
+ if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+ continue;
+
+ switch (Bandwidth) {
+ case HT_CHANNEL_WIDTH_20:
+ if (priv->card_8192_version == VERSION_8190_BD ||
+ priv->card_8192_version == VERSION_8190_BE) {
+ rtl8192_phy_SetRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ 0x0b, bMask12Bits, 0x100);
+ rtl8192_phy_SetRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ 0x2c, bMask12Bits, 0x3d7);
+ rtl8192_phy_SetRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ 0x0e, bMask12Bits, 0x021);
+
+ } else {
+ RT_TRACE(COMP_ERR,
+ "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
+ }
+
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ if (priv->card_8192_version == VERSION_8190_BD ||
+ priv->card_8192_version == VERSION_8190_BE) {
+ rtl8192_phy_SetRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ 0x0b, bMask12Bits, 0x300);
+ rtl8192_phy_SetRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ 0x2c, bMask12Bits, 0x3ff);
+ rtl8192_phy_SetRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ 0x0e, bMask12Bits, 0x0e1);
+
+ } else {
+ RT_TRACE(COMP_ERR,
+ "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
+ }
+
+
+ break;
+ default:
+ RT_TRACE(COMP_ERR,
+ "PHY_SetRF8256Bandwidth(): unknown Bandwidth: %#X\n",
+ Bandwidth);
+ break;
+
+ }
+ }
+}
+
+bool PHY_RF8256_Config(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
+ return phy_RF8256_Config_ParaFile(dev);
+}
+
+bool phy_RF8256_Config_ParaFile(struct net_device *dev)
+{
+ u32 u4RegValue = 0;
+ u8 eRFPath;
+ bool rtStatus = true;
+ struct bb_reg_definition *pPhyReg;
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 RegOffSetToBeCheck = 0x3;
+ u32 RegValueToBeCheck = 0x7f1;
+ u32 RF3_Final_Value = 0;
+ u8 ConstRetryTimes = 5, RetryTimes = 5;
+ u8 ret = 0;
+
+ for (eRFPath = (enum rf90_radio_path)RF90_PATH_A;
+ eRFPath < priv->NumTotalRFPath; eRFPath++) {
+ if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+ continue;
+
+ pPhyReg = &priv->PHYRegDef[eRFPath];
+
+
+ switch (eRFPath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs,
+ bRFSI_RFENV);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs,
+ bRFSI_RFENV<<16);
+ break;
+ }
+
+ rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
+
+ rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
+
+ rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,
+ b3WireAddressLength, 0x0);
+ rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,
+ b3WireDataLength, 0x0);
+
+ rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path) eRFPath, 0x0,
+ bMask12Bits, 0xbf);
+
+ rtStatus = rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF,
+ (enum rf90_radio_path)eRFPath);
+ if (!rtStatus) {
+ RT_TRACE(COMP_ERR,
+ "PHY_RF8256_Config():Check Radio[%d] Fail!!\n",
+ eRFPath);
+ goto phy_RF8256_Config_ParaFile_Fail;
+ }
+
+ RetryTimes = ConstRetryTimes;
+ RF3_Final_Value = 0;
+ switch (eRFPath) {
+ case RF90_PATH_A:
+ while (RF3_Final_Value != RegValueToBeCheck &&
+ RetryTimes != 0) {
+ ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
+ (enum rf90_radio_path)eRFPath);
+ RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ RegOffSetToBeCheck,
+ bMask12Bits);
+ RT_TRACE(COMP_RF,
+ "RF %d %d register final value: %x\n",
+ eRFPath, RegOffSetToBeCheck,
+ RF3_Final_Value);
+ RetryTimes--;
+ }
+ break;
+ case RF90_PATH_B:
+ while (RF3_Final_Value != RegValueToBeCheck &&
+ RetryTimes != 0) {
+ ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
+ (enum rf90_radio_path)eRFPath);
+ RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ RegOffSetToBeCheck,
+ bMask12Bits);
+ RT_TRACE(COMP_RF,
+ "RF %d %d register final value: %x\n",
+ eRFPath, RegOffSetToBeCheck,
+ RF3_Final_Value);
+ RetryTimes--;
+ }
+ break;
+ case RF90_PATH_C:
+ while (RF3_Final_Value != RegValueToBeCheck &&
+ RetryTimes != 0) {
+ ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
+ (enum rf90_radio_path)eRFPath);
+ RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ RegOffSetToBeCheck,
+ bMask12Bits);
+ RT_TRACE(COMP_RF,
+ "RF %d %d register final value: %x\n",
+ eRFPath, RegOffSetToBeCheck,
+ RF3_Final_Value);
+ RetryTimes--;
+ }
+ break;
+ case RF90_PATH_D:
+ while (RF3_Final_Value != RegValueToBeCheck &&
+ RetryTimes != 0) {
+ ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
+ (enum rf90_radio_path)eRFPath);
+ RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ RegOffSetToBeCheck, bMask12Bits);
+ RT_TRACE(COMP_RF,
+ "RF %d %d register final value: %x\n",
+ eRFPath, RegOffSetToBeCheck,
+ RF3_Final_Value);
+ RetryTimes--;
+ }
+ break;
+ }
+
+ switch (eRFPath) {
+ case RF90_PATH_A:
+ case RF90_PATH_C:
+ rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV,
+ u4RegValue);
+ break;
+ case RF90_PATH_B:
+ case RF90_PATH_D:
+ rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16,
+ u4RegValue);
+ break;
+ }
+
+ if (ret) {
+ RT_TRACE(COMP_ERR,
+ "phy_RF8256_Config_ParaFile():Radio[%d] Fail!!",
+ eRFPath);
+ goto phy_RF8256_Config_ParaFile_Fail;
+ }
+
+ }
+
+ RT_TRACE(COMP_PHY, "PHY Initialization Success\n");
+ return true;
+
+phy_RF8256_Config_ParaFile_Fail:
+ RT_TRACE(COMP_ERR, "PHY Initialization failed\n");
+ return false;
+}
+
+void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel)
+{
+ u32 TxAGC = 0;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ TxAGC = powerlevel;
+ if (priv->bDynamicTxLowPower) {
+ if (priv->CustomerID == RT_CID_819x_Netcore)
+ TxAGC = 0x22;
+ else
+ TxAGC += priv->CckPwEnl;
+ }
+ if (TxAGC > 0x24)
+ TxAGC = 0x24;
+ rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
+}
+
+
+void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 writeVal, powerBase0, powerBase1, writeVal_tmp;
+ u8 index = 0;
+ u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
+ u8 byte0, byte1, byte2, byte3;
+
+ powerBase0 = powerlevel + priv->LegacyHTTxPowerDiff;
+ powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
+ (powerBase0 << 8) | powerBase0;
+ powerBase1 = powerlevel;
+ powerBase1 = (powerBase1 << 24) | (powerBase1 << 16) |
+ (powerBase1 << 8) | powerBase1;
+
+ for (index = 0; index < 6; index++) {
+ writeVal = (u32)(priv->MCSTxPowerLevelOriginalOffset[index] +
+ ((index < 2) ? powerBase0 : powerBase1));
+ byte0 = (u8)(writeVal & 0x7f);
+ byte1 = (u8)((writeVal & 0x7f00)>>8);
+ byte2 = (u8)((writeVal & 0x7f0000)>>16);
+ byte3 = (u8)((writeVal & 0x7f000000)>>24);
+ if (byte0 > 0x24)
+ byte0 = 0x24;
+ if (byte1 > 0x24)
+ byte1 = 0x24;
+ if (byte2 > 0x24)
+ byte2 = 0x24;
+ if (byte3 > 0x24)
+ byte3 = 0x24;
+
+ if (index == 3) {
+ writeVal_tmp = (byte3 << 24) | (byte2 << 16) |
+ (byte1 << 8) | byte0;
+ priv->Pwr_Track = writeVal_tmp;
+ }
+
+ if (priv->bDynamicTxHighPower)
+ writeVal = 0x03030303;
+ else
+ writeVal = (byte3 << 24) | (byte2 << 16) |
+ (byte1 << 8) | byte0;
+ rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
+ }
+
+}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h
new file mode 100644
index 000000000..64e831d2f
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h
@@ -0,0 +1,31 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifndef RTL8225H
+#define RTL8225H
+
+#define RTL819X_TOTAL_RF_PATH 2
+extern void PHY_SetRF8256Bandwidth(struct net_device *dev,
+ enum ht_channel_width Bandwidth);
+extern bool PHY_RF8256_Config(struct net_device *dev);
+extern bool phy_RF8256_Config_ParaFile(struct net_device *dev);
+extern void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel);
+extern void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel);
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
new file mode 100644
index 000000000..ecdd2e5c6
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
@@ -0,0 +1,380 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#include "rtl_core.h"
+#include "r8192E_hw.h"
+#include "r8192E_cmdpkt.h"
+
+bool cmpk_message_handle_tx(
+ struct net_device *dev,
+ u8 *code_virtual_address,
+ u32 packettype,
+ u32 buffer_len)
+{
+
+ bool rt_status = true;
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u16 frag_threshold;
+ u16 frag_length = 0, frag_offset = 0;
+ struct rt_firmware *pfirmware = priv->pFirmware;
+ struct sk_buff *skb;
+ unsigned char *seg_ptr;
+ struct cb_desc *tcb_desc;
+ u8 bLastIniPkt;
+
+ struct tx_fwinfo_8190pci *pTxFwInfo = NULL;
+
+ RT_TRACE(COMP_CMDPKT, "%s(),buffer_len is %d\n", __func__, buffer_len);
+ firmware_init_param(dev);
+ frag_threshold = pfirmware->cmdpacket_frag_thresold;
+
+ do {
+ if ((buffer_len - frag_offset) > frag_threshold) {
+ frag_length = frag_threshold;
+ bLastIniPkt = 0;
+
+ } else {
+ frag_length = (u16)(buffer_len - frag_offset);
+ bLastIniPkt = 1;
+ }
+
+ skb = dev_alloc_skb(frag_length +
+ priv->rtllib->tx_headroom + 4);
+
+ if (skb == NULL) {
+ rt_status = false;
+ goto Failed;
+ }
+
+ memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
+ tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+ tcb_desc->queue_index = TXCMD_QUEUE;
+ tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL;
+ tcb_desc->bLastIniPkt = bLastIniPkt;
+ tcb_desc->pkt_size = frag_length;
+
+ seg_ptr = skb_put(skb, priv->rtllib->tx_headroom);
+ pTxFwInfo = (struct tx_fwinfo_8190pci *)seg_ptr;
+ memset(pTxFwInfo, 0, sizeof(struct tx_fwinfo_8190pci));
+ memset(pTxFwInfo, 0x12, 8);
+
+ seg_ptr = skb_put(skb, frag_length);
+ memcpy(seg_ptr, code_virtual_address, (u32)frag_length);
+
+ priv->rtllib->softmac_hard_start_xmit(skb, dev);
+
+ code_virtual_address += frag_length;
+ frag_offset += frag_length;
+
+ } while (frag_offset < buffer_len);
+
+ write_nic_byte(dev, TPPoll, TPPoll_CQ);
+Failed:
+ return rt_status;
+}
+
+static void
+cmpk_count_txstatistic(
+ struct net_device *dev,
+ struct cmpk_txfb *pstx_fb)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+#ifdef ENABLE_PS
+ enum rt_rf_power_state rtState;
+
+ pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
+ (pu1Byte)(&rtState));
+
+ if (rtState == eRfOff)
+ return;
+#endif
+
+ if (pstx_fb->tok) {
+ priv->stats.txfeedbackok++;
+ priv->stats.txoktotal++;
+ priv->stats.txokbytestotal += pstx_fb->pkt_length;
+ priv->stats.txokinperiod++;
+
+ if (pstx_fb->pkt_type == PACKET_MULTICAST) {
+ priv->stats.txmulticast++;
+ priv->stats.txbytesmulticast += pstx_fb->pkt_length;
+ } else if (pstx_fb->pkt_type == PACKET_BROADCAST) {
+ priv->stats.txbroadcast++;
+ priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
+ } else {
+ priv->stats.txunicast++;
+ priv->stats.txbytesunicast += pstx_fb->pkt_length;
+ }
+ } else {
+ priv->stats.txfeedbackfail++;
+ priv->stats.txerrtotal++;
+ priv->stats.txerrbytestotal += pstx_fb->pkt_length;
+
+ if (pstx_fb->pkt_type == PACKET_MULTICAST)
+ priv->stats.txerrmulticast++;
+ else if (pstx_fb->pkt_type == PACKET_BROADCAST)
+ priv->stats.txerrbroadcast++;
+ else
+ priv->stats.txerrunicast++;
+ }
+
+ priv->stats.txretrycount += pstx_fb->retry_cnt;
+ priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
+}
+
+static void cmpk_handle_tx_feedback(struct net_device *dev, u8 *pmsg)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct cmpk_txfb rx_tx_fb;
+
+ priv->stats.txfeedback++;
+
+
+ memcpy((u8 *)&rx_tx_fb, pmsg, sizeof(struct cmpk_txfb));
+ cmpk_count_txstatistic(dev, &rx_tx_fb);
+}
+
+static void cmdpkt_beacontimerinterrupt_819xusb(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if ((priv->rtllib->current_network.mode == IEEE_A) ||
+ (priv->rtllib->current_network.mode == IEEE_N_5G) ||
+ ((priv->rtllib->current_network.mode == IEEE_N_24G) &&
+ (!priv->rtllib->pHTInfo->bCurSuppCCK)))
+ DMESG("send beacon frame tx rate is 6Mbpm\n");
+ else
+ DMESG("send beacon frame tx rate is 1Mbpm\n");
+}
+
+static void cmpk_handle_interrupt_status(struct net_device *dev, u8 *pmsg)
+{
+ struct cmpk_intr_sta rx_intr_status;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ DMESG("---> cmpk_Handle_Interrupt_Status()\n");
+
+ rx_intr_status.length = pmsg[1];
+ if (rx_intr_status.length != (sizeof(struct cmpk_intr_sta) - 2)) {
+ DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
+ return;
+ }
+
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
+ rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
+
+ DMESG("interrupt status = 0x%x\n",
+ rx_intr_status.interrupt_status);
+
+ if (rx_intr_status.interrupt_status & ISR_TxBcnOk) {
+ priv->rtllib->bibsscoordinator = true;
+ priv->stats.txbeaconokint++;
+ } else if (rx_intr_status.interrupt_status & ISR_TxBcnErr) {
+ priv->rtllib->bibsscoordinator = false;
+ priv->stats.txbeaconerr++;
+ }
+
+ if (rx_intr_status.interrupt_status & ISR_BcnTimerIntr)
+ cmdpkt_beacontimerinterrupt_819xusb(dev);
+ }
+
+ DMESG("<---- cmpk_handle_interrupt_status()\n");
+
+}
+
+static void cmpk_handle_query_config_rx(struct net_device *dev, u8 *pmsg)
+{
+ cmpk_query_cfg_t rx_query_cfg;
+
+
+ rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000)>>31;
+ rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5;
+ rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3;
+ rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0;
+ rx_query_cfg.cfg_offset = pmsg[7];
+ rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) |
+ (pmsg[10] << 8) | (pmsg[11] << 0);
+ rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) |
+ (pmsg[14] << 8) | (pmsg[15] << 0);
+
+}
+
+static void cmpk_count_tx_status(struct net_device *dev,
+ struct cmpk_tx_status *pstx_status)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+#ifdef ENABLE_PS
+
+ enum rt_rf_power_state rtstate;
+
+ pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
+ (pu1Byte)(&rtState));
+
+ if (rtState == eRfOff)
+ return;
+#endif
+
+ priv->stats.txfeedbackok += pstx_status->txok;
+ priv->stats.txoktotal += pstx_status->txok;
+
+ priv->stats.txfeedbackfail += pstx_status->txfail;
+ priv->stats.txerrtotal += pstx_status->txfail;
+
+ priv->stats.txretrycount += pstx_status->txretry;
+ priv->stats.txfeedbackretry += pstx_status->txretry;
+
+
+ priv->stats.txmulticast += pstx_status->txmcok;
+ priv->stats.txbroadcast += pstx_status->txbcok;
+ priv->stats.txunicast += pstx_status->txucok;
+
+ priv->stats.txerrmulticast += pstx_status->txmcfail;
+ priv->stats.txerrbroadcast += pstx_status->txbcfail;
+ priv->stats.txerrunicast += pstx_status->txucfail;
+
+ priv->stats.txbytesmulticast += pstx_status->txmclength;
+ priv->stats.txbytesbroadcast += pstx_status->txbclength;
+ priv->stats.txbytesunicast += pstx_status->txuclength;
+
+ priv->stats.last_packet_rate = pstx_status->rate;
+}
+
+static void cmpk_handle_tx_status(struct net_device *dev, u8 *pmsg)
+{
+ struct cmpk_tx_status rx_tx_sts;
+
+ memcpy((void *)&rx_tx_sts, (void *)pmsg, sizeof(struct cmpk_tx_status));
+ cmpk_count_tx_status(dev, &rx_tx_sts);
+}
+
+static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg)
+{
+ struct cmpk_tx_rahis *ptxrate;
+ u8 i, j;
+ u16 length = sizeof(struct cmpk_tx_rahis);
+ u32 *ptemp;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+#ifdef ENABLE_PS
+ pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE,
+ (pu1Byte)(&rtState));
+
+ if (rtState == eRfOff)
+ return;
+#endif
+
+ ptemp = (u32 *)pmsg;
+
+ for (i = 0; i < (length / 4); i++) {
+ u16 temp1, temp2;
+
+ temp1 = ptemp[i] & 0x0000FFFF;
+ temp2 = ptemp[i] >> 16;
+ ptemp[i] = (temp1 << 16) | temp2;
+ }
+
+ ptxrate = (struct cmpk_tx_rahis *)pmsg;
+
+ if (ptxrate == NULL)
+ return;
+
+ for (i = 0; i < 16; i++) {
+ if (i < 4)
+ priv->stats.txrate.cck[i] += ptxrate->cck[i];
+
+ if (i < 8)
+ priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
+
+ for (j = 0; j < 4; j++)
+ priv->stats.txrate.ht_mcs[j][i] +=
+ ptxrate->ht_mcs[j][i];
+ }
+}
+
+u32 cmpk_message_handle_rx(struct net_device *dev,
+ struct rtllib_rx_stats *pstats)
+{
+ int total_length;
+ u8 cmd_length, exe_cnt = 0;
+ u8 element_id;
+ u8 *pcmd_buff;
+
+ RT_TRACE(COMP_CMDPKT, "---->cmpk_message_handle_rx()\n");
+
+ if (pstats == NULL)
+ return 0;
+
+ total_length = pstats->Length;
+
+ pcmd_buff = pstats->virtual_address;
+
+ element_id = pcmd_buff[0];
+
+ while (total_length > 0 || exe_cnt++ > 100) {
+ element_id = pcmd_buff[0];
+
+ switch (element_id) {
+ case RX_TX_FEEDBACK:
+ RT_TRACE(COMP_CMDPKT,
+ "---->cmpk_message_handle_rx():RX_TX_FEEDBACK\n");
+ cmpk_handle_tx_feedback(dev, pcmd_buff);
+ cmd_length = CMPK_RX_TX_FB_SIZE;
+ break;
+ case RX_INTERRUPT_STATUS:
+ RT_TRACE(COMP_CMDPKT,
+ "---->cmpk_message_handle_rx():RX_INTERRUPT_STATUS\n");
+ cmpk_handle_interrupt_status(dev, pcmd_buff);
+ cmd_length = sizeof(struct cmpk_intr_sta);
+ break;
+ case BOTH_QUERY_CONFIG:
+ RT_TRACE(COMP_CMDPKT,
+ "---->cmpk_message_handle_rx():BOTH_QUERY_CONFIG\n");
+ cmpk_handle_query_config_rx(dev, pcmd_buff);
+ cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
+ break;
+ case RX_TX_STATUS:
+ RT_TRACE(COMP_CMDPKT,
+ "---->cmpk_message_handle_rx():RX_TX_STATUS\n");
+ cmpk_handle_tx_status(dev, pcmd_buff);
+ cmd_length = CMPK_RX_TX_STS_SIZE;
+ break;
+ case RX_TX_PER_PKT_FEEDBACK:
+ RT_TRACE(COMP_CMDPKT,
+ "---->cmpk_message_handle_rx():RX_TX_PER_PKT_FEEDBACK\n");
+ cmd_length = CMPK_RX_TX_FB_SIZE;
+ break;
+ case RX_TX_RATE_HISTORY:
+ RT_TRACE(COMP_CMDPKT,
+ "---->cmpk_message_handle_rx():RX_TX_HISTORY\n");
+ cmpk_handle_tx_rate_history(dev, pcmd_buff);
+ cmd_length = CMPK_TX_RAHIS_SIZE;
+ break;
+ default:
+
+ RT_TRACE(COMP_CMDPKT,
+ "---->cmpk_message_handle_rx():unknown CMD Element\n");
+ return 1;
+ }
+
+ total_length -= cmd_length;
+ pcmd_buff += cmd_length;
+ }
+ return 1;
+}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
new file mode 100644
index 000000000..269368264
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
@@ -0,0 +1,159 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef R819XUSB_CMDPKT_H
+#define R819XUSB_CMDPKT_H
+#define CMPK_RX_TX_FB_SIZE sizeof(struct cmpk_txfb)
+#define CMPK_TX_SET_CONFIG_SIZE sizeof(struct cmpk_set_cfg)
+#define CMPK_BOTH_QUERY_CONFIG_SIZE sizeof(struct cmpk_set_cfg)
+#define CMPK_RX_TX_STS_SIZE sizeof(struct cmpk_tx_status)
+#define CMPK_RX_DBG_MSG_SIZE sizeof(struct cmpk_rx_dbginfo)
+#define CMPK_TX_RAHIS_SIZE sizeof(struct cmpk_tx_rahis)
+
+#define ISR_TxBcnOk BIT27
+#define ISR_TxBcnErr BIT26
+#define ISR_BcnTimerIntr BIT13
+
+
+struct cmpk_txfb {
+ u8 element_id;
+ u8 length;
+ u8 TID:4;
+ u8 fail_reason:3;
+ u8 tok:1;
+ u8 reserve1:4;
+ u8 pkt_type:2;
+ u8 bandwidth:1;
+ u8 qos_pkt:1;
+
+ u8 reserve2;
+ u8 retry_cnt;
+ u16 pkt_id;
+
+ u16 seq_num;
+ u8 s_rate;
+ u8 f_rate;
+
+ u8 s_rts_rate;
+ u8 f_rts_rate;
+ u16 pkt_length;
+
+ u16 reserve3;
+ u16 duration;
+};
+
+struct cmpk_intr_sta {
+ u8 element_id;
+ u8 length;
+ u16 reserve;
+ u32 interrupt_status;
+};
+
+
+struct cmpk_set_cfg {
+ u8 element_id;
+ u8 length;
+ u16 reserve1;
+ u8 cfg_reserve1:3;
+ u8 cfg_size:2;
+ u8 cfg_type:2;
+ u8 cfg_action:1;
+ u8 cfg_reserve2;
+ u8 cfg_page:4;
+ u8 cfg_reserve3:4;
+ u8 cfg_offset;
+ u32 value;
+ u32 mask;
+};
+
+#define cmpk_query_cfg_t struct cmpk_set_cfg
+
+struct cmpk_tx_status {
+ u16 reserve1;
+ u8 length;
+ u8 element_id;
+
+ u16 txfail;
+ u16 txok;
+
+ u16 txmcok;
+ u16 txretry;
+
+ u16 txucok;
+ u16 txbcok;
+
+ u16 txbcfail;
+ u16 txmcfail;
+
+ u16 reserve2;
+ u16 txucfail;
+
+ u32 txmclength;
+ u32 txbclength;
+ u32 txuclength;
+
+ u16 reserve3_23;
+ u8 reserve3_1;
+ u8 rate;
+} __packed;
+
+struct cmpk_rx_dbginfo {
+ u16 reserve1;
+ u8 length;
+ u8 element_id;
+
+
+};
+
+struct cmpk_tx_rahis {
+ u8 element_id;
+ u8 length;
+ u16 reserved1;
+
+ u16 cck[4];
+
+ u16 ofdm[8];
+
+
+
+
+
+ u16 ht_mcs[4][16];
+
+} __packed;
+
+enum cmpk_element {
+ RX_TX_FEEDBACK = 0,
+ RX_INTERRUPT_STATUS = 1,
+ TX_SET_CONFIG = 2,
+ BOTH_QUERY_CONFIG = 3,
+ RX_TX_STATUS = 4,
+ RX_DBGINFO_FEEDBACK = 5,
+ RX_TX_PER_PKT_FEEDBACK = 6,
+ RX_TX_RATE_HISTORY = 7,
+ RX_CMD_ELE_MAX
+};
+
+extern u32 cmpk_message_handle_rx(struct net_device *dev,
+ struct rtllib_rx_stats *pstats);
+extern bool cmpk_message_handle_tx(struct net_device *dev,
+ u8 *codevirtualaddress, u32 packettype,
+ u32 buffer_len);
+
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
new file mode 100644
index 000000000..286960243
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -0,0 +1,2416 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtl_core.h"
+#include "r8192E_phy.h"
+#include "r8192E_phyreg.h"
+#include "r8190P_rtl8256.h"
+#include "r8192E_cmdpkt.h"
+#include "rtl_dm.h"
+#include "rtl_wx.h"
+
+static int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI, EDCAPARA_VO};
+
+void rtl8192e_start_beacon(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ struct rtllib_network *net = &priv->rtllib->current_network;
+ u16 BcnTimeCfg = 0;
+ u16 BcnCW = 6;
+ u16 BcnIFS = 0xf;
+
+ DMESG("Enabling beacon TX");
+ rtl8192_irq_disable(dev);
+
+ write_nic_word(dev, ATIMWND, 2);
+
+ write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
+ write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
+ write_nic_word(dev, BCN_DMATIME, 256);
+
+ write_nic_byte(dev, BCN_ERR_THRESH, 100);
+
+ BcnTimeCfg |= BcnCW<<BCN_TCFG_CW_SHIFT;
+ BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
+ write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
+ rtl8192_irq_enable(dev);
+}
+
+static void rtl8192e_update_msr(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 msr;
+ enum led_ctl_mode LedAction = LED_CTL_NO_LINK;
+
+ msr = read_nic_byte(dev, MSR);
+ msr &= ~MSR_LINK_MASK;
+
+ switch (priv->rtllib->iw_mode) {
+ case IW_MODE_INFRA:
+ if (priv->rtllib->state == RTLLIB_LINKED)
+ msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT);
+ else
+ msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
+ LedAction = LED_CTL_LINK;
+ break;
+ case IW_MODE_ADHOC:
+ if (priv->rtllib->state == RTLLIB_LINKED)
+ msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT);
+ else
+ msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
+ break;
+ case IW_MODE_MASTER:
+ if (priv->rtllib->state == RTLLIB_LINKED)
+ msr |= (MSR_LINK_MASTER << MSR_LINK_SHIFT);
+ else
+ msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
+ break;
+ default:
+ break;
+ }
+
+ write_nic_byte(dev, MSR, msr);
+ if (priv->rtllib->LedControlHandler)
+ priv->rtllib->LedControlHandler(dev, LedAction);
+}
+
+void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ switch (variable) {
+ case HW_VAR_BSSID:
+ write_nic_dword(dev, BSSIDR, ((u32 *)(val))[0]);
+ write_nic_word(dev, BSSIDR+2, ((u16 *)(val+2))[0]);
+ break;
+
+ case HW_VAR_MEDIA_STATUS:
+ {
+ enum rt_op_mode OpMode = *((enum rt_op_mode *)(val));
+ enum led_ctl_mode LedAction = LED_CTL_NO_LINK;
+ u8 btMsr = read_nic_byte(dev, MSR);
+
+ btMsr &= 0xfc;
+
+ switch (OpMode) {
+ case RT_OP_MODE_INFRASTRUCTURE:
+ btMsr |= MSR_INFRA;
+ LedAction = LED_CTL_LINK;
+ break;
+
+ case RT_OP_MODE_IBSS:
+ btMsr |= MSR_ADHOC;
+ break;
+
+ case RT_OP_MODE_AP:
+ btMsr |= MSR_AP;
+ LedAction = LED_CTL_LINK;
+ break;
+
+ default:
+ btMsr |= MSR_NOLINK;
+ break;
+ }
+
+ write_nic_byte(dev, MSR, btMsr);
+
+ }
+ break;
+
+ case HW_VAR_CECHK_BSSID:
+ {
+ u32 RegRCR, Type;
+
+ Type = ((u8 *)(val))[0];
+ RegRCR = read_nic_dword(dev, RCR);
+ priv->ReceiveConfig = RegRCR;
+
+ if (Type == true)
+ RegRCR |= (RCR_CBSSID);
+ else if (Type == false)
+ RegRCR &= (~RCR_CBSSID);
+
+ write_nic_dword(dev, RCR, RegRCR);
+ priv->ReceiveConfig = RegRCR;
+
+ }
+ break;
+
+ case HW_VAR_SLOT_TIME:
+
+ priv->slot_time = val[0];
+ write_nic_byte(dev, SLOT_TIME, val[0]);
+
+ break;
+
+ case HW_VAR_ACK_PREAMBLE:
+ {
+ u32 regTmp;
+
+ priv->short_preamble = (bool)(*(u8 *)val);
+ regTmp = priv->basic_rate;
+ if (priv->short_preamble)
+ regTmp |= BRSR_AckShortPmb;
+ write_nic_dword(dev, RRSR, regTmp);
+ break;
+ }
+
+ case HW_VAR_CPU_RST:
+ write_nic_dword(dev, CPU_GEN, ((u32 *)(val))[0]);
+ break;
+
+ case HW_VAR_AC_PARAM:
+ {
+ u8 pAcParam = *((u8 *)val);
+ u32 eACI = pAcParam;
+ u8 u1bAIFS;
+ u32 u4bAcParam;
+ u8 mode = priv->rtllib->mode;
+ struct rtllib_qos_parameters *qos_parameters =
+ &priv->rtllib->current_network.qos_data.parameters;
+
+ u1bAIFS = qos_parameters->aifs[pAcParam] *
+ ((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
+
+ dm_init_edca_turbo(dev);
+
+ u4bAcParam = (((le16_to_cpu(
+ qos_parameters->tx_op_limit[pAcParam])) <<
+ AC_PARAM_TXOP_LIMIT_OFFSET) |
+ ((le16_to_cpu(qos_parameters->cw_max[pAcParam])) <<
+ AC_PARAM_ECW_MAX_OFFSET) |
+ ((le16_to_cpu(qos_parameters->cw_min[pAcParam])) <<
+ AC_PARAM_ECW_MIN_OFFSET) |
+ (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET));
+
+ RT_TRACE(COMP_DBG, "%s():HW_VAR_AC_PARAM eACI:%x:%x\n",
+ __func__, eACI, u4bAcParam);
+ switch (eACI) {
+ case AC1_BK:
+ write_nic_dword(dev, EDCAPARA_BK, u4bAcParam);
+ break;
+
+ case AC0_BE:
+ write_nic_dword(dev, EDCAPARA_BE, u4bAcParam);
+ break;
+
+ case AC2_VI:
+ write_nic_dword(dev, EDCAPARA_VI, u4bAcParam);
+ break;
+
+ case AC3_VO:
+ write_nic_dword(dev, EDCAPARA_VO, u4bAcParam);
+ break;
+
+ default:
+ netdev_info(dev, "SetHwReg8185(): invalid ACI: %d !\n",
+ eACI);
+ break;
+ }
+ priv->rtllib->SetHwRegHandler(dev, HW_VAR_ACM_CTRL,
+ (u8 *)(&pAcParam));
+ break;
+ }
+
+ case HW_VAR_ACM_CTRL:
+ {
+ struct rtllib_qos_parameters *qos_parameters =
+ &priv->rtllib->current_network.qos_data.parameters;
+ u8 pAcParam = *((u8 *)val);
+ u32 eACI = pAcParam;
+ union aci_aifsn *pAciAifsn = (union aci_aifsn *) &
+ (qos_parameters->aifs[0]);
+ u8 acm = pAciAifsn->f.acm;
+ u8 AcmCtrl = read_nic_byte(dev, AcmHwCtrl);
+
+ RT_TRACE(COMP_DBG, "===========>%s():HW_VAR_ACM_CTRL:%x\n",
+ __func__, eACI);
+ AcmCtrl = AcmCtrl | ((priv->AcmMethod == 2) ? 0x0 : 0x1);
+
+ if (acm) {
+ switch (eACI) {
+ case AC0_BE:
+ AcmCtrl |= AcmHw_BeqEn;
+ break;
+
+ case AC2_VI:
+ AcmCtrl |= AcmHw_ViqEn;
+ break;
+
+ case AC3_VO:
+ AcmCtrl |= AcmHw_VoqEn;
+ break;
+
+ default:
+ RT_TRACE(COMP_QOS,
+ "SetHwReg8185(): [HW_VAR_ACM_CTRL] acm set failed: eACI is %d\n",
+ eACI);
+ break;
+ }
+ } else {
+ switch (eACI) {
+ case AC0_BE:
+ AcmCtrl &= (~AcmHw_BeqEn);
+ break;
+
+ case AC2_VI:
+ AcmCtrl &= (~AcmHw_ViqEn);
+ break;
+
+ case AC3_VO:
+ AcmCtrl &= (~AcmHw_BeqEn);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ RT_TRACE(COMP_QOS,
+ "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n",
+ AcmCtrl);
+ write_nic_byte(dev, AcmHwCtrl, AcmCtrl);
+ break;
+ }
+
+ case HW_VAR_SIFS:
+ write_nic_byte(dev, SIFS, val[0]);
+ write_nic_byte(dev, SIFS+1, val[0]);
+ break;
+
+ case HW_VAR_RF_TIMING:
+ {
+ u8 Rf_Timing = *((u8 *)val);
+
+ write_nic_byte(dev, rFPGA0_RFTiming1, Rf_Timing);
+ break;
+ }
+
+ default:
+ break;
+ }
+
+}
+
+static void rtl8192_read_eeprom_info(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ u8 tempval;
+ u8 ICVer8192, ICVer8256;
+ u16 i, usValue, IC_Version;
+ u16 EEPROMId;
+ u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x01};
+
+ RT_TRACE(COMP_INIT, "====> rtl8192_read_eeprom_info\n");
+
+ EEPROMId = eprom_read(dev, 0);
+ if (EEPROMId != RTL8190_EEPROM_ID) {
+ RT_TRACE(COMP_ERR, "EEPROM ID is invalid:%x, %x\n",
+ EEPROMId, RTL8190_EEPROM_ID);
+ priv->AutoloadFailFlag = true;
+ } else {
+ priv->AutoloadFailFlag = false;
+ }
+
+ if (!priv->AutoloadFailFlag) {
+ priv->eeprom_vid = eprom_read(dev, EEPROM_VID >> 1);
+ priv->eeprom_did = eprom_read(dev, EEPROM_DID >> 1);
+
+ usValue = eprom_read(dev, (u16)(EEPROM_Customer_ID>>1)) >> 8;
+ priv->eeprom_CustomerID = (u8)(usValue & 0xff);
+ usValue = eprom_read(dev, EEPROM_ICVersion_ChannelPlan>>1);
+ priv->eeprom_ChannelPlan = usValue&0xff;
+ IC_Version = (usValue & 0xff00)>>8;
+
+ ICVer8192 = (IC_Version&0xf);
+ ICVer8256 = (IC_Version & 0xf0)>>4;
+ RT_TRACE(COMP_INIT, "\nICVer8192 = 0x%x\n", ICVer8192);
+ RT_TRACE(COMP_INIT, "\nICVer8256 = 0x%x\n", ICVer8256);
+ if (ICVer8192 == 0x2) {
+ if (ICVer8256 == 0x5)
+ priv->card_8192_version = VERSION_8190_BE;
+ }
+ switch (priv->card_8192_version) {
+ case VERSION_8190_BD:
+ case VERSION_8190_BE:
+ break;
+ default:
+ priv->card_8192_version = VERSION_8190_BD;
+ break;
+ }
+ RT_TRACE(COMP_INIT, "\nIC Version = 0x%x\n",
+ priv->card_8192_version);
+ } else {
+ priv->card_8192_version = VERSION_8190_BD;
+ priv->eeprom_vid = 0;
+ priv->eeprom_did = 0;
+ priv->eeprom_CustomerID = 0;
+ priv->eeprom_ChannelPlan = 0;
+ RT_TRACE(COMP_INIT, "\nIC Version = 0x%x\n", 0xff);
+ }
+
+ RT_TRACE(COMP_INIT, "EEPROM VID = 0x%4x\n", priv->eeprom_vid);
+ RT_TRACE(COMP_INIT, "EEPROM DID = 0x%4x\n", priv->eeprom_did);
+ RT_TRACE(COMP_INIT, "EEPROM Customer ID: 0x%2x\n",
+ priv->eeprom_CustomerID);
+
+ if (!priv->AutoloadFailFlag) {
+ for (i = 0; i < 6; i += 2) {
+ usValue = eprom_read(dev,
+ (u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i) >> 1));
+ *(u16 *)(&dev->dev_addr[i]) = usValue;
+ }
+ } else {
+ memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
+ }
+
+ RT_TRACE(COMP_INIT, "Permanent Address = %pM\n",
+ dev->dev_addr);
+
+ if (priv->card_8192_version > VERSION_8190_BD)
+ priv->bTXPowerDataReadFromEEPORM = true;
+ else
+ priv->bTXPowerDataReadFromEEPORM = false;
+
+ priv->rf_type = RTL819X_DEFAULT_RF_TYPE;
+
+ if (priv->card_8192_version > VERSION_8190_BD) {
+ if (!priv->AutoloadFailFlag) {
+ tempval = (eprom_read(dev, (EEPROM_RFInd_PowerDiff >>
+ 1))) & 0xff;
+ priv->EEPROMLegacyHTTxPowerDiff = tempval & 0xf;
+
+ if (tempval&0x80)
+ priv->rf_type = RF_1T2R;
+ else
+ priv->rf_type = RF_2T4R;
+ } else {
+ priv->EEPROMLegacyHTTxPowerDiff = 0x04;
+ }
+ RT_TRACE(COMP_INIT, "EEPROMLegacyHTTxPowerDiff = %d\n",
+ priv->EEPROMLegacyHTTxPowerDiff);
+
+ if (!priv->AutoloadFailFlag)
+ priv->EEPROMThermalMeter = (u8)(((eprom_read(dev,
+ (EEPROM_ThermalMeter>>1))) &
+ 0xff00)>>8);
+ else
+ priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
+ RT_TRACE(COMP_INIT, "ThermalMeter = %d\n",
+ priv->EEPROMThermalMeter);
+ priv->TSSI_13dBm = priv->EEPROMThermalMeter * 100;
+
+ if (priv->epromtype == EEPROM_93C46) {
+ if (!priv->AutoloadFailFlag) {
+ usValue = eprom_read(dev,
+ EEPROM_TxPwDiff_CrystalCap >> 1);
+ priv->EEPROMAntPwDiff = (usValue&0x0fff);
+ priv->EEPROMCrystalCap = (u8)((usValue & 0xf000)
+ >> 12);
+ } else {
+ priv->EEPROMAntPwDiff =
+ EEPROM_Default_AntTxPowerDiff;
+ priv->EEPROMCrystalCap =
+ EEPROM_Default_TxPwDiff_CrystalCap;
+ }
+ RT_TRACE(COMP_INIT, "EEPROMAntPwDiff = %d\n",
+ priv->EEPROMAntPwDiff);
+ RT_TRACE(COMP_INIT, "EEPROMCrystalCap = %d\n",
+ priv->EEPROMCrystalCap);
+
+ for (i = 0; i < 14; i += 2) {
+ if (!priv->AutoloadFailFlag)
+ usValue = eprom_read(dev,
+ (u16)((EEPROM_TxPwIndex_CCK +
+ i) >> 1));
+ else
+ usValue = EEPROM_Default_TxPower;
+ *((u16 *)(&priv->EEPROMTxPowerLevelCCK[i])) =
+ usValue;
+ RT_TRACE(COMP_INIT,
+ "CCK Tx Power Level, Index %d = 0x%02x\n",
+ i, priv->EEPROMTxPowerLevelCCK[i]);
+ RT_TRACE(COMP_INIT,
+ "CCK Tx Power Level, Index %d = 0x%02x\n",
+ i+1, priv->EEPROMTxPowerLevelCCK[i+1]);
+ }
+ for (i = 0; i < 14; i += 2) {
+ if (!priv->AutoloadFailFlag)
+ usValue = eprom_read(dev,
+ (u16)((EEPROM_TxPwIndex_OFDM_24G
+ + i) >> 1));
+ else
+ usValue = EEPROM_Default_TxPower;
+ *((u16 *)(&priv->EEPROMTxPowerLevelOFDM24G[i]))
+ = usValue;
+ RT_TRACE(COMP_INIT,
+ "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n",
+ i, priv->EEPROMTxPowerLevelOFDM24G[i]);
+ RT_TRACE(COMP_INIT,
+ "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n",
+ i + 1,
+ priv->EEPROMTxPowerLevelOFDM24G[i+1]);
+ }
+ }
+ if (priv->epromtype == EEPROM_93C46) {
+ for (i = 0; i < 14; i++) {
+ priv->TxPowerLevelCCK[i] =
+ priv->EEPROMTxPowerLevelCCK[i];
+ priv->TxPowerLevelOFDM24G[i] =
+ priv->EEPROMTxPowerLevelOFDM24G[i];
+ }
+ priv->LegacyHTTxPowerDiff =
+ priv->EEPROMLegacyHTTxPowerDiff;
+ priv->AntennaTxPwDiff[0] = (priv->EEPROMAntPwDiff &
+ 0xf);
+ priv->AntennaTxPwDiff[1] = (priv->EEPROMAntPwDiff &
+ 0xf0) >> 4;
+ priv->AntennaTxPwDiff[2] = (priv->EEPROMAntPwDiff &
+ 0xf00) >> 8;
+ priv->CrystalCap = priv->EEPROMCrystalCap;
+ priv->ThermalMeter[0] = (priv->EEPROMThermalMeter &
+ 0xf);
+ priv->ThermalMeter[1] = (priv->EEPROMThermalMeter &
+ 0xf0) >> 4;
+ } else if (priv->epromtype == EEPROM_93C56) {
+
+ for (i = 0; i < 3; i++) {
+ priv->TxPowerLevelCCK_A[i] =
+ priv->EEPROMRfACCKChnl1TxPwLevel[0];
+ priv->TxPowerLevelOFDM24G_A[i] =
+ priv->EEPROMRfAOfdmChnlTxPwLevel[0];
+ priv->TxPowerLevelCCK_C[i] =
+ priv->EEPROMRfCCCKChnl1TxPwLevel[0];
+ priv->TxPowerLevelOFDM24G_C[i] =
+ priv->EEPROMRfCOfdmChnlTxPwLevel[0];
+ }
+ for (i = 3; i < 9; i++) {
+ priv->TxPowerLevelCCK_A[i] =
+ priv->EEPROMRfACCKChnl1TxPwLevel[1];
+ priv->TxPowerLevelOFDM24G_A[i] =
+ priv->EEPROMRfAOfdmChnlTxPwLevel[1];
+ priv->TxPowerLevelCCK_C[i] =
+ priv->EEPROMRfCCCKChnl1TxPwLevel[1];
+ priv->TxPowerLevelOFDM24G_C[i] =
+ priv->EEPROMRfCOfdmChnlTxPwLevel[1];
+ }
+ for (i = 9; i < 14; i++) {
+ priv->TxPowerLevelCCK_A[i] =
+ priv->EEPROMRfACCKChnl1TxPwLevel[2];
+ priv->TxPowerLevelOFDM24G_A[i] =
+ priv->EEPROMRfAOfdmChnlTxPwLevel[2];
+ priv->TxPowerLevelCCK_C[i] =
+ priv->EEPROMRfCCCKChnl1TxPwLevel[2];
+ priv->TxPowerLevelOFDM24G_C[i] =
+ priv->EEPROMRfCOfdmChnlTxPwLevel[2];
+ }
+ for (i = 0; i < 14; i++)
+ RT_TRACE(COMP_INIT,
+ "priv->TxPowerLevelCCK_A[%d] = 0x%x\n",
+ i, priv->TxPowerLevelCCK_A[i]);
+ for (i = 0; i < 14; i++)
+ RT_TRACE(COMP_INIT,
+ "priv->TxPowerLevelOFDM24G_A[%d] = 0x%x\n",
+ i, priv->TxPowerLevelOFDM24G_A[i]);
+ for (i = 0; i < 14; i++)
+ RT_TRACE(COMP_INIT,
+ "priv->TxPowerLevelCCK_C[%d] = 0x%x\n",
+ i, priv->TxPowerLevelCCK_C[i]);
+ for (i = 0; i < 14; i++)
+ RT_TRACE(COMP_INIT,
+ "priv->TxPowerLevelOFDM24G_C[%d] = 0x%x\n",
+ i, priv->TxPowerLevelOFDM24G_C[i]);
+ priv->LegacyHTTxPowerDiff =
+ priv->EEPROMLegacyHTTxPowerDiff;
+ priv->AntennaTxPwDiff[0] = 0;
+ priv->AntennaTxPwDiff[1] = 0;
+ priv->AntennaTxPwDiff[2] = 0;
+ priv->CrystalCap = priv->EEPROMCrystalCap;
+ priv->ThermalMeter[0] = (priv->EEPROMThermalMeter &
+ 0xf);
+ priv->ThermalMeter[1] = (priv->EEPROMThermalMeter &
+ 0xf0) >> 4;
+ }
+ }
+
+ if (priv->rf_type == RF_1T2R) {
+ /* no matter what checkpatch says, the braces are needed */
+ RT_TRACE(COMP_INIT, "\n1T2R config\n");
+ } else if (priv->rf_type == RF_2T4R) {
+ RT_TRACE(COMP_INIT, "\n2T4R config\n");
+ }
+
+ init_rate_adaptive(dev);
+
+ priv->rf_chip = RF_8256;
+
+ if (priv->RegChannelPlan == 0xf)
+ priv->ChannelPlan = priv->eeprom_ChannelPlan;
+ else
+ priv->ChannelPlan = priv->RegChannelPlan;
+
+ if (priv->eeprom_vid == 0x1186 && priv->eeprom_did == 0x3304)
+ priv->CustomerID = RT_CID_DLINK;
+
+ switch (priv->eeprom_CustomerID) {
+ case EEPROM_CID_DEFAULT:
+ priv->CustomerID = RT_CID_DEFAULT;
+ break;
+ case EEPROM_CID_CAMEO:
+ priv->CustomerID = RT_CID_819x_CAMEO;
+ break;
+ case EEPROM_CID_RUNTOP:
+ priv->CustomerID = RT_CID_819x_RUNTOP;
+ break;
+ case EEPROM_CID_NetCore:
+ priv->CustomerID = RT_CID_819x_Netcore;
+ break;
+ case EEPROM_CID_TOSHIBA:
+ priv->CustomerID = RT_CID_TOSHIBA;
+ if (priv->eeprom_ChannelPlan&0x80)
+ priv->ChannelPlan = priv->eeprom_ChannelPlan&0x7f;
+ else
+ priv->ChannelPlan = 0x0;
+ RT_TRACE(COMP_INIT, "Toshiba ChannelPlan = 0x%x\n",
+ priv->ChannelPlan);
+ break;
+ case EEPROM_CID_Nettronix:
+ priv->ScanDelay = 100;
+ priv->CustomerID = RT_CID_Nettronix;
+ break;
+ case EEPROM_CID_Pronet:
+ priv->CustomerID = RT_CID_PRONET;
+ break;
+ case EEPROM_CID_DLINK:
+ priv->CustomerID = RT_CID_DLINK;
+ break;
+
+ case EEPROM_CID_WHQL:
+ break;
+ default:
+ break;
+ }
+
+ if (priv->ChannelPlan > CHANNEL_PLAN_LEN - 1)
+ priv->ChannelPlan = 0;
+ priv->ChannelPlan = COUNTRY_CODE_WORLD_WIDE_13;
+
+ if (priv->eeprom_vid == 0x1186 && priv->eeprom_did == 0x3304)
+ priv->rtllib->bSupportRemoteWakeUp = true;
+ else
+ priv->rtllib->bSupportRemoteWakeUp = false;
+
+ RT_TRACE(COMP_INIT, "RegChannelPlan(%d)\n", priv->RegChannelPlan);
+ RT_TRACE(COMP_INIT, "ChannelPlan = %d\n", priv->ChannelPlan);
+ RT_TRACE(COMP_TRACE, "<==== ReadAdapterInfo\n");
+}
+
+void rtl8192_get_eeprom_size(struct net_device *dev)
+{
+ u16 curCR;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ RT_TRACE(COMP_INIT, "===========>%s()\n", __func__);
+ curCR = read_nic_dword(dev, EPROM_CMD);
+ RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD,
+ curCR);
+ priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 :
+ EEPROM_93C46;
+ RT_TRACE(COMP_INIT, "<===========%s(), epromtype:%d\n", __func__,
+ priv->epromtype);
+ rtl8192_read_eeprom_info(dev);
+}
+
+static void rtl8192_hwconfig(struct net_device *dev)
+{
+ u32 regRATR = 0, regRRSR = 0;
+ u8 regBwOpMode = 0, regTmp = 0;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ switch (priv->rtllib->mode) {
+ case WIRELESS_MODE_B:
+ regBwOpMode = BW_OPMODE_20MHZ;
+ regRATR = RATE_ALL_CCK;
+ regRRSR = RATE_ALL_CCK;
+ break;
+ case WIRELESS_MODE_A:
+ regBwOpMode = BW_OPMODE_5G | BW_OPMODE_20MHZ;
+ regRATR = RATE_ALL_OFDM_AG;
+ regRRSR = RATE_ALL_OFDM_AG;
+ break;
+ case WIRELESS_MODE_G:
+ regBwOpMode = BW_OPMODE_20MHZ;
+ regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+ regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+ break;
+ case WIRELESS_MODE_AUTO:
+ case WIRELESS_MODE_N_24G:
+ regBwOpMode = BW_OPMODE_20MHZ;
+ regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG |
+ RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
+ regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+ break;
+ case WIRELESS_MODE_N_5G:
+ regBwOpMode = BW_OPMODE_5G;
+ regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS |
+ RATE_ALL_OFDM_2SS;
+ regRRSR = RATE_ALL_OFDM_AG;
+ break;
+ default:
+ regBwOpMode = BW_OPMODE_20MHZ;
+ regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+ regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
+ break;
+ }
+
+ write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+ {
+ u32 ratr_value = 0;
+
+ ratr_value = regRATR;
+ if (priv->rf_type == RF_1T2R)
+ ratr_value &= ~(RATE_ALL_OFDM_2SS);
+ write_nic_dword(dev, RATR0, ratr_value);
+ write_nic_byte(dev, UFWP, 1);
+ }
+ regTmp = read_nic_byte(dev, 0x313);
+ regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
+ write_nic_dword(dev, RRSR, regRRSR);
+
+ write_nic_word(dev, RETRY_LIMIT,
+ priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
+ priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
+}
+
+bool rtl8192_adapter_start(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 ulRegRead;
+ bool rtStatus = true;
+ u8 tmpvalue;
+ u8 ICVersion, SwitchingRegulatorOutput;
+ bool bfirmwareok = true;
+ u32 tmpRegA, tmpRegC, TempCCk;
+ int i = 0;
+ u32 retry_times = 0;
+
+ RT_TRACE(COMP_INIT, "====>%s()\n", __func__);
+ priv->being_init_adapter = true;
+
+start:
+ rtl8192_pci_resetdescring(dev);
+ priv->Rf_Mode = RF_OP_By_SW_3wire;
+ if (priv->ResetProgress == RESET_TYPE_NORESET) {
+ write_nic_byte(dev, ANAPAR, 0x37);
+ mdelay(500);
+ }
+ priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
+
+ if (priv->RegRfOff)
+ priv->rtllib->eRFPowerState = eRfOff;
+
+ ulRegRead = read_nic_dword(dev, CPU_GEN);
+ if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
+ ulRegRead |= CPU_GEN_SYSTEM_RESET;
+ else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
+ ulRegRead |= CPU_GEN_FIRMWARE_RESET;
+ else
+ RT_TRACE(COMP_ERR,
+ "ERROR in %s(): undefined firmware state(%d)\n",
+ __func__, priv->pFirmware->firmware_status);
+
+ write_nic_dword(dev, CPU_GEN, ulRegRead);
+
+ ICVersion = read_nic_byte(dev, IC_VERRSION);
+ if (ICVersion >= 0x4) {
+ SwitchingRegulatorOutput = read_nic_byte(dev, SWREGULATOR);
+ if (SwitchingRegulatorOutput != 0xb8) {
+ write_nic_byte(dev, SWREGULATOR, 0xa8);
+ mdelay(1);
+ write_nic_byte(dev, SWREGULATOR, 0xb8);
+ }
+ }
+ RT_TRACE(COMP_INIT, "BB Config Start!\n");
+ rtStatus = rtl8192_BBConfig(dev);
+ if (!rtStatus) {
+ RT_TRACE(COMP_ERR, "BB Config failed\n");
+ return rtStatus;
+ }
+ RT_TRACE(COMP_INIT, "BB Config Finished!\n");
+
+ priv->LoopbackMode = RTL819X_NO_LOOPBACK;
+ if (priv->ResetProgress == RESET_TYPE_NORESET) {
+ ulRegRead = read_nic_dword(dev, CPU_GEN);
+ if (priv->LoopbackMode == RTL819X_NO_LOOPBACK)
+ ulRegRead = ((ulRegRead & CPU_GEN_NO_LOOPBACK_MSK) |
+ CPU_GEN_NO_LOOPBACK_SET);
+ else if (priv->LoopbackMode == RTL819X_MAC_LOOPBACK)
+ ulRegRead |= CPU_CCK_LOOPBACK;
+ else
+ RT_TRACE(COMP_ERR,
+ "Serious error: wrong loopback mode setting\n");
+
+ write_nic_dword(dev, CPU_GEN, ulRegRead);
+
+ udelay(500);
+ }
+ rtl8192_hwconfig(dev);
+ write_nic_byte(dev, CMDR, CR_RE | CR_TE);
+
+ write_nic_byte(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) |
+ (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT)));
+ write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
+ write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
+ write_nic_dword(dev, RCR, priv->ReceiveConfig);
+
+ write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK <<
+ RSVD_FW_QUEUE_PAGE_BK_SHIFT |
+ NUM_OF_PAGE_IN_FW_QUEUE_BE <<
+ RSVD_FW_QUEUE_PAGE_BE_SHIFT |
+ NUM_OF_PAGE_IN_FW_QUEUE_VI <<
+ RSVD_FW_QUEUE_PAGE_VI_SHIFT |
+ NUM_OF_PAGE_IN_FW_QUEUE_VO <<
+ RSVD_FW_QUEUE_PAGE_VO_SHIFT);
+ write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT <<
+ RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
+ write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW |
+ NUM_OF_PAGE_IN_FW_QUEUE_BCN <<
+ RSVD_FW_QUEUE_PAGE_BCN_SHIFT|
+ NUM_OF_PAGE_IN_FW_QUEUE_PUB <<
+ RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
+
+ rtl8192_tx_enable(dev);
+ rtl8192_rx_enable(dev);
+ ulRegRead = (0xFFF00000 & read_nic_dword(dev, RRSR)) |
+ RATE_ALL_OFDM_AG | RATE_ALL_CCK;
+ write_nic_dword(dev, RRSR, ulRegRead);
+ write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
+
+ write_nic_byte(dev, ACK_TIMEOUT, 0x30);
+
+ if (priv->ResetProgress == RESET_TYPE_NORESET)
+ rtl8192_SetWirelessMode(dev, priv->rtllib->mode);
+ CamResetAllEntry(dev);
+ {
+ u8 SECR_value = 0x0;
+
+ SECR_value |= SCR_TxEncEnable;
+ SECR_value |= SCR_RxDecEnable;
+ SECR_value |= SCR_NoSKMC;
+ write_nic_byte(dev, SECR, SECR_value);
+ }
+ write_nic_word(dev, ATIMWND, 2);
+ write_nic_word(dev, BCN_INTERVAL, 100);
+ {
+ int i;
+
+ for (i = 0; i < QOS_QUEUE_NUM; i++)
+ write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
+ }
+ write_nic_byte(dev, 0xbe, 0xc0);
+
+ rtl8192_phy_configmac(dev);
+
+ if (priv->card_8192_version > (u8) VERSION_8190_BD) {
+ rtl8192_phy_getTxPower(dev);
+ rtl8192_phy_setTxPower(dev, priv->chan);
+ }
+
+ tmpvalue = read_nic_byte(dev, IC_VERRSION);
+ priv->IC_Cut = tmpvalue;
+ RT_TRACE(COMP_INIT, "priv->IC_Cut= 0x%x\n", priv->IC_Cut);
+ if (priv->IC_Cut >= IC_VersionCut_D) {
+ if (priv->IC_Cut == IC_VersionCut_D) {
+ /* no matter what checkpatch says, braces are needed */
+ RT_TRACE(COMP_INIT, "D-cut\n");
+ } else if (priv->IC_Cut == IC_VersionCut_E) {
+ RT_TRACE(COMP_INIT, "E-cut\n");
+ }
+ } else {
+ RT_TRACE(COMP_INIT, "Before C-cut\n");
+ }
+
+ RT_TRACE(COMP_INIT, "Load Firmware!\n");
+ bfirmwareok = init_firmware(dev);
+ if (!bfirmwareok) {
+ if (retry_times < 10) {
+ retry_times++;
+ goto start;
+ } else {
+ rtStatus = false;
+ goto end;
+ }
+ }
+ RT_TRACE(COMP_INIT, "Load Firmware finished!\n");
+ if (priv->ResetProgress == RESET_TYPE_NORESET) {
+ RT_TRACE(COMP_INIT, "RF Config Started!\n");
+ rtStatus = rtl8192_phy_RFConfig(dev);
+ if (!rtStatus) {
+ RT_TRACE(COMP_ERR, "RF Config failed\n");
+ return rtStatus;
+ }
+ RT_TRACE(COMP_INIT, "RF Config Finished!\n");
+ }
+ rtl8192_phy_updateInitGain(dev);
+
+ rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
+ rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
+
+ write_nic_byte(dev, 0x87, 0x0);
+
+ if (priv->RegRfOff) {
+ RT_TRACE((COMP_INIT | COMP_RF | COMP_POWER),
+ "%s(): Turn off RF for RegRfOff ----------\n",
+ __func__);
+ MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW, true);
+ } else if (priv->rtllib->RfOffReason > RF_CHANGE_BY_PS) {
+ RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER),
+ "%s(): Turn off RF for RfOffReason(%d) ----------\n",
+ __func__, priv->rtllib->RfOffReason);
+ MgntActSet_RF_State(dev, eRfOff, priv->rtllib->RfOffReason,
+ true);
+ } else if (priv->rtllib->RfOffReason >= RF_CHANGE_BY_IPS) {
+ RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER),
+ "%s(): Turn off RF for RfOffReason(%d) ----------\n",
+ __func__, priv->rtllib->RfOffReason);
+ MgntActSet_RF_State(dev, eRfOff, priv->rtllib->RfOffReason,
+ true);
+ } else {
+ RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): RF-ON\n",
+ __func__);
+ priv->rtllib->eRFPowerState = eRfOn;
+ priv->rtllib->RfOffReason = 0;
+ }
+
+ if (priv->rtllib->FwRWRF)
+ priv->Rf_Mode = RF_OP_By_FW;
+ else
+ priv->Rf_Mode = RF_OP_By_SW_3wire;
+
+ if (priv->ResetProgress == RESET_TYPE_NORESET) {
+ dm_initialize_txpower_tracking(dev);
+
+ if (priv->IC_Cut >= IC_VersionCut_D) {
+ tmpRegA = rtl8192_QueryBBReg(dev,
+ rOFDM0_XATxIQImbalance, bMaskDWord);
+ tmpRegC = rtl8192_QueryBBReg(dev,
+ rOFDM0_XCTxIQImbalance, bMaskDWord);
+ for (i = 0; i < TxBBGainTableLength; i++) {
+ if (tmpRegA ==
+ priv->txbbgain_table[i].txbbgain_value) {
+ priv->rfa_txpowertrackingindex = (u8)i;
+ priv->rfa_txpowertrackingindex_real =
+ (u8)i;
+ priv->rfa_txpowertracking_default =
+ priv->rfa_txpowertrackingindex;
+ break;
+ }
+ }
+
+ TempCCk = rtl8192_QueryBBReg(dev,
+ rCCK0_TxFilter1, bMaskByte2);
+
+ for (i = 0; i < CCKTxBBGainTableLength; i++) {
+ if (TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0]) {
+ priv->CCKPresentAttentuation_20Mdefault = (u8)i;
+ break;
+ }
+ }
+ priv->CCKPresentAttentuation_40Mdefault = 0;
+ priv->CCKPresentAttentuation_difference = 0;
+ priv->CCKPresentAttentuation =
+ priv->CCKPresentAttentuation_20Mdefault;
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->rfa_txpowertrackingindex_initial = %d\n",
+ priv->rfa_txpowertrackingindex);
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->rfa_txpowertrackingindex_real__initial = %d\n",
+ priv->rfa_txpowertrackingindex_real);
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->CCKPresentAttentuation_difference_initial = %d\n",
+ priv->CCKPresentAttentuation_difference);
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->CCKPresentAttentuation_initial = %d\n",
+ priv->CCKPresentAttentuation);
+ priv->btxpower_tracking = false;
+ }
+ }
+ rtl8192_irq_enable(dev);
+end:
+ priv->being_init_adapter = false;
+ return rtStatus;
+}
+
+static void rtl8192_net_update(struct net_device *dev)
+{
+
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_network *net;
+ u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
+ u16 rate_config = 0;
+
+ net = &priv->rtllib->current_network;
+ rtl8192_config_rate(dev, &rate_config);
+ priv->dot11CurrentPreambleMode = PREAMBLE_AUTO;
+ priv->basic_rate = rate_config &= 0x15f;
+ write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]);
+ write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
+
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
+ write_nic_word(dev, ATIMWND, 2);
+ write_nic_word(dev, BCN_DMATIME, 256);
+ write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
+ write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
+ write_nic_byte(dev, BCN_ERR_THRESH, 100);
+
+ BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
+ BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
+
+ write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
+ }
+}
+
+void rtl8192_link_change(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ if (!priv->up)
+ return;
+
+ if (ieee->state == RTLLIB_LINKED) {
+ rtl8192_net_update(dev);
+ priv->ops->update_ratr_table(dev);
+ if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) ||
+ (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
+ EnableHWSecurityConfig8192(dev);
+ } else {
+ write_nic_byte(dev, 0x173, 0);
+ }
+ rtl8192e_update_msr(dev);
+
+ if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
+ u32 reg = 0;
+
+ reg = read_nic_dword(dev, RCR);
+ if (priv->rtllib->state == RTLLIB_LINKED) {
+ if (ieee->IntelPromiscuousModeInfo.bPromiscuousOn)
+ ;
+ else
+ priv->ReceiveConfig = reg |= RCR_CBSSID;
+ } else
+ priv->ReceiveConfig = reg &= ~RCR_CBSSID;
+
+ write_nic_dword(dev, RCR, reg);
+ }
+}
+
+void rtl8192_AllowAllDestAddr(struct net_device *dev,
+ bool bAllowAllDA, bool WriteIntoReg)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (bAllowAllDA)
+ priv->ReceiveConfig |= RCR_AAP;
+ else
+ priv->ReceiveConfig &= ~RCR_AAP;
+
+ if (WriteIntoReg)
+ write_nic_dword(dev, RCR, priv->ReceiveConfig);
+}
+
+static u8 MRateToHwRate8190Pci(u8 rate)
+{
+ u8 ret = DESC90_RATE1M;
+
+ switch (rate) {
+ case MGN_1M:
+ ret = DESC90_RATE1M;
+ break;
+ case MGN_2M:
+ ret = DESC90_RATE2M;
+ break;
+ case MGN_5_5M:
+ ret = DESC90_RATE5_5M;
+ break;
+ case MGN_11M:
+ ret = DESC90_RATE11M;
+ break;
+ case MGN_6M:
+ ret = DESC90_RATE6M;
+ break;
+ case MGN_9M:
+ ret = DESC90_RATE9M;
+ break;
+ case MGN_12M:
+ ret = DESC90_RATE12M;
+ break;
+ case MGN_18M:
+ ret = DESC90_RATE18M;
+ break;
+ case MGN_24M:
+ ret = DESC90_RATE24M;
+ break;
+ case MGN_36M:
+ ret = DESC90_RATE36M;
+ break;
+ case MGN_48M:
+ ret = DESC90_RATE48M;
+ break;
+ case MGN_54M:
+ ret = DESC90_RATE54M;
+ break;
+ case MGN_MCS0:
+ ret = DESC90_RATEMCS0;
+ break;
+ case MGN_MCS1:
+ ret = DESC90_RATEMCS1;
+ break;
+ case MGN_MCS2:
+ ret = DESC90_RATEMCS2;
+ break;
+ case MGN_MCS3:
+ ret = DESC90_RATEMCS3;
+ break;
+ case MGN_MCS4:
+ ret = DESC90_RATEMCS4;
+ break;
+ case MGN_MCS5:
+ ret = DESC90_RATEMCS5;
+ break;
+ case MGN_MCS6:
+ ret = DESC90_RATEMCS6;
+ break;
+ case MGN_MCS7:
+ ret = DESC90_RATEMCS7;
+ break;
+ case MGN_MCS8:
+ ret = DESC90_RATEMCS8;
+ break;
+ case MGN_MCS9:
+ ret = DESC90_RATEMCS9;
+ break;
+ case MGN_MCS10:
+ ret = DESC90_RATEMCS10;
+ break;
+ case MGN_MCS11:
+ ret = DESC90_RATEMCS11;
+ break;
+ case MGN_MCS12:
+ ret = DESC90_RATEMCS12;
+ break;
+ case MGN_MCS13:
+ ret = DESC90_RATEMCS13;
+ break;
+ case MGN_MCS14:
+ ret = DESC90_RATEMCS14;
+ break;
+ case MGN_MCS15:
+ ret = DESC90_RATEMCS15;
+ break;
+ case (0x80|0x20):
+ ret = DESC90_RATEMCS32;
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static u8 rtl8192_MapHwQueueToFirmwareQueue(u8 QueueID, u8 priority)
+{
+ u8 QueueSelect = 0x0;
+
+ switch (QueueID) {
+ case BE_QUEUE:
+ QueueSelect = QSLT_BE;
+ break;
+
+ case BK_QUEUE:
+ QueueSelect = QSLT_BK;
+ break;
+
+ case VO_QUEUE:
+ QueueSelect = QSLT_VO;
+ break;
+
+ case VI_QUEUE:
+ QueueSelect = QSLT_VI;
+ break;
+ case MGNT_QUEUE:
+ QueueSelect = QSLT_MGNT;
+ break;
+ case BEACON_QUEUE:
+ QueueSelect = QSLT_BEACON;
+ break;
+ case TXCMD_QUEUE:
+ QueueSelect = QSLT_CMD;
+ break;
+ case HIGH_QUEUE:
+ QueueSelect = QSLT_HIGH;
+ break;
+ default:
+ RT_TRACE(COMP_ERR,
+ "TransmitTCB(): Impossible Queue Selection: %d\n",
+ QueueID);
+ break;
+ }
+ return QueueSelect;
+}
+
+void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc,
+ struct cb_desc *cb_desc, struct sk_buff *skb)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ struct tx_fwinfo_8190pci *pTxFwInfo = NULL;
+
+ pTxFwInfo = (struct tx_fwinfo_8190pci *)skb->data;
+ memset(pTxFwInfo, 0, sizeof(struct tx_fwinfo_8190pci));
+ pTxFwInfo->TxHT = (cb_desc->data_rate & 0x80) ? 1 : 0;
+ pTxFwInfo->TxRate = MRateToHwRate8190Pci((u8)cb_desc->data_rate);
+ pTxFwInfo->EnableCPUDur = cb_desc->bTxEnableFwCalcDur;
+ pTxFwInfo->Short = rtl8192_QueryIsShort(pTxFwInfo->TxHT,
+ pTxFwInfo->TxRate,
+ cb_desc);
+
+ if (pci_dma_mapping_error(priv->pdev, mapping))
+ RT_TRACE(COMP_ERR, "DMA Mapping error\n");
+ if (cb_desc->bAMPDUEnable) {
+ pTxFwInfo->AllowAggregation = 1;
+ pTxFwInfo->RxMF = cb_desc->ampdu_factor;
+ pTxFwInfo->RxAMD = cb_desc->ampdu_density;
+ } else {
+ pTxFwInfo->AllowAggregation = 0;
+ pTxFwInfo->RxMF = 0;
+ pTxFwInfo->RxAMD = 0;
+ }
+
+ pTxFwInfo->RtsEnable = (cb_desc->bRTSEnable) ? 1 : 0;
+ pTxFwInfo->CtsEnable = (cb_desc->bCTSEnable) ? 1 : 0;
+ pTxFwInfo->RtsSTBC = (cb_desc->bRTSSTBC) ? 1 : 0;
+ pTxFwInfo->RtsHT = (cb_desc->rts_rate&0x80) ? 1 : 0;
+ pTxFwInfo->RtsRate = MRateToHwRate8190Pci((u8)cb_desc->rts_rate);
+ pTxFwInfo->RtsBandwidth = 0;
+ pTxFwInfo->RtsSubcarrier = cb_desc->RTSSC;
+ pTxFwInfo->RtsShort = (pTxFwInfo->RtsHT == 0) ?
+ (cb_desc->bRTSUseShortPreamble ? 1 : 0) :
+ (cb_desc->bRTSUseShortGI ? 1 : 0);
+ if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
+ if (cb_desc->bPacketBW) {
+ pTxFwInfo->TxBandwidth = 1;
+ pTxFwInfo->TxSubCarrier = 0;
+ } else {
+ pTxFwInfo->TxBandwidth = 0;
+ pTxFwInfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
+ }
+ } else {
+ pTxFwInfo->TxBandwidth = 0;
+ pTxFwInfo->TxSubCarrier = 0;
+ }
+
+ memset((u8 *)pdesc, 0, 12);
+ pdesc->LINIP = 0;
+ pdesc->CmdInit = 1;
+ pdesc->Offset = sizeof(struct tx_fwinfo_8190pci) + 8;
+ pdesc->PktSize = (u16)skb->len-sizeof(struct tx_fwinfo_8190pci);
+
+ pdesc->SecCAMID = 0;
+ pdesc->RATid = cb_desc->RATRIndex;
+
+
+ pdesc->NoEnc = 1;
+ pdesc->SecType = 0x0;
+ if (cb_desc->bHwSec) {
+ static u8 tmp;
+
+ if (!tmp) {
+ RT_TRACE(COMP_DBG, "==>================hw sec\n");
+ tmp = 1;
+ }
+ switch (priv->rtllib->pairwise_key_type) {
+ case KEY_TYPE_WEP40:
+ case KEY_TYPE_WEP104:
+ pdesc->SecType = 0x1;
+ pdesc->NoEnc = 0;
+ break;
+ case KEY_TYPE_TKIP:
+ pdesc->SecType = 0x2;
+ pdesc->NoEnc = 0;
+ break;
+ case KEY_TYPE_CCMP:
+ pdesc->SecType = 0x3;
+ pdesc->NoEnc = 0;
+ break;
+ case KEY_TYPE_NA:
+ pdesc->SecType = 0x0;
+ pdesc->NoEnc = 1;
+ break;
+ }
+ }
+
+ pdesc->PktId = 0x0;
+
+ pdesc->QueueSelect = rtl8192_MapHwQueueToFirmwareQueue(
+ cb_desc->queue_index,
+ cb_desc->priority);
+ pdesc->TxFWInfoSize = sizeof(struct tx_fwinfo_8190pci);
+
+ pdesc->DISFB = cb_desc->bTxDisableRateFallBack;
+ pdesc->USERATE = cb_desc->bTxUseDriverAssingedRate;
+
+ pdesc->FirstSeg = 1;
+ pdesc->LastSeg = 1;
+ pdesc->TxBufferSize = skb->len;
+
+ pdesc->TxBuffAddr = mapping;
+}
+
+void rtl8192_tx_fill_cmd_desc(struct net_device *dev,
+ struct tx_desc_cmd *entry,
+ struct cb_desc *cb_desc, struct sk_buff *skb)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+
+ if (pci_dma_mapping_error(priv->pdev, mapping))
+ RT_TRACE(COMP_ERR, "DMA Mapping error\n");
+ memset(entry, 0, 12);
+ entry->LINIP = cb_desc->bLastIniPkt;
+ entry->FirstSeg = 1;
+ entry->LastSeg = 1;
+ if (cb_desc->bCmdOrInit == DESC_PACKET_TYPE_INIT) {
+ entry->CmdInit = DESC_PACKET_TYPE_INIT;
+ } else {
+ struct tx_desc *entry_tmp = (struct tx_desc *)entry;
+
+ entry_tmp->CmdInit = DESC_PACKET_TYPE_NORMAL;
+ entry_tmp->Offset = sizeof(struct tx_fwinfo_8190pci) + 8;
+ entry_tmp->PktSize = (u16)(cb_desc->pkt_size +
+ entry_tmp->Offset);
+ entry_tmp->QueueSelect = QSLT_CMD;
+ entry_tmp->TxFWInfoSize = 0x08;
+ entry_tmp->RATid = (u8)DESC_PACKET_TYPE_INIT;
+ }
+ entry->TxBufferSize = skb->len;
+ entry->TxBuffAddr = mapping;
+ entry->OWN = 1;
+}
+
+static u8 HwRateToMRate90(bool bIsHT, u8 rate)
+{
+ u8 ret_rate = 0x02;
+
+ if (!bIsHT) {
+ switch (rate) {
+ case DESC90_RATE1M:
+ ret_rate = MGN_1M;
+ break;
+ case DESC90_RATE2M:
+ ret_rate = MGN_2M;
+ break;
+ case DESC90_RATE5_5M:
+ ret_rate = MGN_5_5M;
+ break;
+ case DESC90_RATE11M:
+ ret_rate = MGN_11M;
+ break;
+ case DESC90_RATE6M:
+ ret_rate = MGN_6M;
+ break;
+ case DESC90_RATE9M:
+ ret_rate = MGN_9M;
+ break;
+ case DESC90_RATE12M:
+ ret_rate = MGN_12M;
+ break;
+ case DESC90_RATE18M:
+ ret_rate = MGN_18M;
+ break;
+ case DESC90_RATE24M:
+ ret_rate = MGN_24M;
+ break;
+ case DESC90_RATE36M:
+ ret_rate = MGN_36M;
+ break;
+ case DESC90_RATE48M:
+ ret_rate = MGN_48M;
+ break;
+ case DESC90_RATE54M:
+ ret_rate = MGN_54M;
+ break;
+
+ default:
+ RT_TRACE(COMP_RECV,
+ "HwRateToMRate90(): Non supportedRate [%x], bIsHT = %d!!!\n",
+ rate, bIsHT);
+ break;
+ }
+
+ } else {
+ switch (rate) {
+ case DESC90_RATEMCS0:
+ ret_rate = MGN_MCS0;
+ break;
+ case DESC90_RATEMCS1:
+ ret_rate = MGN_MCS1;
+ break;
+ case DESC90_RATEMCS2:
+ ret_rate = MGN_MCS2;
+ break;
+ case DESC90_RATEMCS3:
+ ret_rate = MGN_MCS3;
+ break;
+ case DESC90_RATEMCS4:
+ ret_rate = MGN_MCS4;
+ break;
+ case DESC90_RATEMCS5:
+ ret_rate = MGN_MCS5;
+ break;
+ case DESC90_RATEMCS6:
+ ret_rate = MGN_MCS6;
+ break;
+ case DESC90_RATEMCS7:
+ ret_rate = MGN_MCS7;
+ break;
+ case DESC90_RATEMCS8:
+ ret_rate = MGN_MCS8;
+ break;
+ case DESC90_RATEMCS9:
+ ret_rate = MGN_MCS9;
+ break;
+ case DESC90_RATEMCS10:
+ ret_rate = MGN_MCS10;
+ break;
+ case DESC90_RATEMCS11:
+ ret_rate = MGN_MCS11;
+ break;
+ case DESC90_RATEMCS12:
+ ret_rate = MGN_MCS12;
+ break;
+ case DESC90_RATEMCS13:
+ ret_rate = MGN_MCS13;
+ break;
+ case DESC90_RATEMCS14:
+ ret_rate = MGN_MCS14;
+ break;
+ case DESC90_RATEMCS15:
+ ret_rate = MGN_MCS15;
+ break;
+ case DESC90_RATEMCS32:
+ ret_rate = (0x80|0x20);
+ break;
+
+ default:
+ RT_TRACE(COMP_RECV,
+ "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n",
+ rate, bIsHT);
+ break;
+ }
+ }
+
+ return ret_rate;
+}
+
+static long rtl8192_signal_scale_mapping(struct r8192_priv *priv, long currsig)
+{
+ long retsig;
+
+ if (currsig >= 61 && currsig <= 100)
+ retsig = 90 + ((currsig - 60) / 4);
+ else if (currsig >= 41 && currsig <= 60)
+ retsig = 78 + ((currsig - 40) / 2);
+ else if (currsig >= 31 && currsig <= 40)
+ retsig = 66 + (currsig - 30);
+ else if (currsig >= 21 && currsig <= 30)
+ retsig = 54 + (currsig - 20);
+ else if (currsig >= 5 && currsig <= 20)
+ retsig = 42 + (((currsig - 5) * 2) / 3);
+ else if (currsig == 4)
+ retsig = 36;
+ else if (currsig == 3)
+ retsig = 27;
+ else if (currsig == 2)
+ retsig = 18;
+ else if (currsig == 1)
+ retsig = 9;
+ else
+ retsig = currsig;
+
+ return retsig;
+}
+
+
+#define rx_hal_is_cck_rate(_pdrvinfo)\
+ ((_pdrvinfo->RxRate == DESC90_RATE1M ||\
+ _pdrvinfo->RxRate == DESC90_RATE2M ||\
+ _pdrvinfo->RxRate == DESC90_RATE5_5M ||\
+ _pdrvinfo->RxRate == DESC90_RATE11M) &&\
+ !_pdrvinfo->RxHT)
+
+static void rtl8192_query_rxphystatus(
+ struct r8192_priv *priv,
+ struct rtllib_rx_stats *pstats,
+ struct rx_desc *pdesc,
+ struct rx_fwinfo *pdrvinfo,
+ struct rtllib_rx_stats *precord_stats,
+ bool bpacket_match_bssid,
+ bool bpacket_toself,
+ bool bPacketBeacon,
+ bool bToSelfBA
+ )
+{
+ struct phy_sts_ofdm_819xpci *pofdm_buf;
+ struct phy_sts_cck_819xpci *pcck_buf;
+ struct phy_ofdm_rx_status_rxsc_sgien_exintfflag *prxsc;
+ u8 *prxpkt;
+ u8 i, max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
+ char rx_pwr[4], rx_pwr_all = 0;
+ char rx_snrX, rx_evmX;
+ u8 evm, pwdb_all;
+ u32 RSSI, total_rssi = 0;
+ u8 is_cck_rate = 0;
+ u8 rf_rx_num = 0;
+ static u8 check_reg824;
+ static u32 reg824_bit9;
+
+ priv->stats.numqry_phystatus++;
+
+ is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
+ memset(precord_stats, 0, sizeof(struct rtllib_rx_stats));
+ pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID =
+ bpacket_match_bssid;
+ pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
+ pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;
+ pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
+ pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
+ if (check_reg824 == 0) {
+ reg824_bit9 = rtl8192_QueryBBReg(priv->rtllib->dev,
+ rFPGA0_XA_HSSIParameter2, 0x200);
+ check_reg824 = 1;
+ }
+
+
+ prxpkt = (u8 *)pdrvinfo;
+
+ prxpkt += sizeof(struct rx_fwinfo);
+
+ pcck_buf = (struct phy_sts_cck_819xpci *)prxpkt;
+ pofdm_buf = (struct phy_sts_ofdm_819xpci *)prxpkt;
+
+ pstats->RxMIMOSignalQuality[0] = -1;
+ pstats->RxMIMOSignalQuality[1] = -1;
+ precord_stats->RxMIMOSignalQuality[0] = -1;
+ precord_stats->RxMIMOSignalQuality[1] = -1;
+
+ if (is_cck_rate) {
+ u8 report;
+
+ priv->stats.numqry_phystatusCCK++;
+ if (!reg824_bit9) {
+ report = pcck_buf->cck_agc_rpt & 0xc0;
+ report >>= 6;
+ switch (report) {
+ case 0x3:
+ rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt &
+ 0x3e);
+ break;
+ case 0x2:
+ rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt &
+ 0x3e);
+ break;
+ case 0x1:
+ rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt &
+ 0x3e);
+ break;
+ case 0x0:
+ rx_pwr_all = 8 - (pcck_buf->cck_agc_rpt & 0x3e);
+ break;
+ }
+ } else {
+ report = pcck_buf->cck_agc_rpt & 0x60;
+ report >>= 5;
+ switch (report) {
+ case 0x3:
+ rx_pwr_all = -35 -
+ ((pcck_buf->cck_agc_rpt &
+ 0x1f) << 1);
+ break;
+ case 0x2:
+ rx_pwr_all = -23 -
+ ((pcck_buf->cck_agc_rpt &
+ 0x1f) << 1);
+ break;
+ case 0x1:
+ rx_pwr_all = -11 -
+ ((pcck_buf->cck_agc_rpt &
+ 0x1f) << 1);
+ break;
+ case 0x0:
+ rx_pwr_all = -8 -
+ ((pcck_buf->cck_agc_rpt &
+ 0x1f) << 1);
+ break;
+ }
+ }
+
+ pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
+ pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
+ pstats->RecvSignalPower = rx_pwr_all;
+
+ if (bpacket_match_bssid) {
+ u8 sq;
+
+ if (pstats->RxPWDBAll > 40) {
+ sq = 100;
+ } else {
+ sq = pcck_buf->sq_rpt;
+
+ if (pcck_buf->sq_rpt > 64)
+ sq = 0;
+ else if (pcck_buf->sq_rpt < 20)
+ sq = 100;
+ else
+ sq = ((64-sq) * 100) / 44;
+ }
+ pstats->SignalQuality = sq;
+ precord_stats->SignalQuality = sq;
+ pstats->RxMIMOSignalQuality[0] = sq;
+ precord_stats->RxMIMOSignalQuality[0] = sq;
+ pstats->RxMIMOSignalQuality[1] = -1;
+ precord_stats->RxMIMOSignalQuality[1] = -1;
+ }
+ } else {
+ priv->stats.numqry_phystatusHT++;
+ for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
+ if (priv->brfpath_rxenable[i])
+ rf_rx_num++;
+
+ rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i] & 0x3F) *
+ 2) - 110;
+
+ tmp_rxsnr = pofdm_buf->rxsnr_X[i];
+ rx_snrX = (char)(tmp_rxsnr);
+ rx_snrX /= 2;
+ priv->stats.rxSNRdB[i] = (long)rx_snrX;
+
+ RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
+ if (priv->brfpath_rxenable[i])
+ total_rssi += RSSI;
+
+ if (bpacket_match_bssid) {
+ pstats->RxMIMOSignalStrength[i] = (u8) RSSI;
+ precord_stats->RxMIMOSignalStrength[i] =
+ (u8) RSSI;
+ }
+ }
+
+
+ rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1) & 0x7f) - 106;
+ pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
+
+ pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
+ pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
+ pstats->RecvSignalPower = rx_pwr_all;
+ if (pdrvinfo->RxHT && pdrvinfo->RxRate >= DESC90_RATEMCS8 &&
+ pdrvinfo->RxRate <= DESC90_RATEMCS15)
+ max_spatial_stream = 2;
+ else
+ max_spatial_stream = 1;
+
+ for (i = 0; i < max_spatial_stream; i++) {
+ tmp_rxevm = pofdm_buf->rxevm_X[i];
+ rx_evmX = (char)(tmp_rxevm);
+
+ rx_evmX /= 2;
+
+ evm = rtl819x_evm_dbtopercentage(rx_evmX);
+ if (bpacket_match_bssid) {
+ if (i == 0) {
+ pstats->SignalQuality = (u8)(evm &
+ 0xff);
+ precord_stats->SignalQuality = (u8)(evm
+ & 0xff);
+ }
+ pstats->RxMIMOSignalQuality[i] = (u8)(evm &
+ 0xff);
+ precord_stats->RxMIMOSignalQuality[i] = (u8)(evm
+ & 0xff);
+ }
+ }
+
+
+ rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
+ prxsc = (struct phy_ofdm_rx_status_rxsc_sgien_exintfflag *)
+ &rxsc_sgien_exflg;
+ if (pdrvinfo->BW)
+ priv->stats.received_bwtype[1+prxsc->rxsc]++;
+ else
+ priv->stats.received_bwtype[0]++;
+ }
+
+ if (is_cck_rate) {
+ pstats->SignalStrength = precord_stats->SignalStrength =
+ (u8)(rtl8192_signal_scale_mapping(priv,
+ (long)pwdb_all));
+
+ } else {
+ if (rf_rx_num != 0)
+ pstats->SignalStrength = precord_stats->SignalStrength =
+ (u8)(rtl8192_signal_scale_mapping(priv,
+ (long)(total_rssi /= rf_rx_num)));
+ }
+}
+
+static void rtl8192_process_phyinfo(struct r8192_priv *priv, u8 *buffer,
+ struct rtllib_rx_stats *prev_st,
+ struct rtllib_rx_stats *curr_st)
+{
+ bool bcheck = false;
+ u8 rfpath;
+ u32 ij, tmp_val;
+ static u32 slide_rssi_index, slide_rssi_statistics;
+ static u32 slide_evm_index, slide_evm_statistics;
+ static u32 last_rssi, last_evm;
+ static u32 slide_beacon_adc_pwdb_index;
+ static u32 slide_beacon_adc_pwdb_statistics;
+ static u32 last_beacon_adc_pwdb;
+ struct rtllib_hdr_3addr *hdr;
+ u16 sc;
+ unsigned int frag, seq;
+
+ hdr = (struct rtllib_hdr_3addr *)buffer;
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+ seq = WLAN_GET_SEQ_SEQ(sc);
+ curr_st->Seq_Num = seq;
+ if (!prev_st->bIsAMPDU)
+ bcheck = true;
+
+ if (slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
+ slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
+ last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
+ priv->stats.slide_rssi_total -= last_rssi;
+ }
+ priv->stats.slide_rssi_total += prev_st->SignalStrength;
+
+ priv->stats.slide_signal_strength[slide_rssi_index++] =
+ prev_st->SignalStrength;
+ if (slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
+ slide_rssi_index = 0;
+
+ tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
+ priv->stats.signal_strength = rtl819x_translate_todbm(priv,
+ (u8)tmp_val);
+ curr_st->rssi = priv->stats.signal_strength;
+ if (!prev_st->bPacketMatchBSSID) {
+ if (!prev_st->bToSelfBA)
+ return;
+ }
+
+ if (!bcheck)
+ return;
+
+ rtl819x_process_cck_rxpathsel(priv, prev_st);
+
+ priv->stats.num_process_phyinfo++;
+ if (!prev_st->bIsCCK && prev_st->bPacketToSelf) {
+ for (rfpath = RF90_PATH_A; rfpath < RF90_PATH_C; rfpath++) {
+ if (!rtl8192_phy_CheckIsLegalRFPath(priv->rtllib->dev,
+ rfpath))
+ continue;
+ RT_TRACE(COMP_DBG,
+ "Jacken -> pPreviousstats->RxMIMOSignalStrength[rfpath] = %d\n",
+ prev_st->RxMIMOSignalStrength[rfpath]);
+ if (priv->stats.rx_rssi_percentage[rfpath] == 0) {
+ priv->stats.rx_rssi_percentage[rfpath] =
+ prev_st->RxMIMOSignalStrength[rfpath];
+ }
+ if (prev_st->RxMIMOSignalStrength[rfpath] >
+ priv->stats.rx_rssi_percentage[rfpath]) {
+ priv->stats.rx_rssi_percentage[rfpath] =
+ ((priv->stats.rx_rssi_percentage[rfpath]
+ * (RX_SMOOTH - 1)) +
+ (prev_st->RxMIMOSignalStrength
+ [rfpath])) / (RX_SMOOTH);
+ priv->stats.rx_rssi_percentage[rfpath] =
+ priv->stats.rx_rssi_percentage[rfpath]
+ + 1;
+ } else {
+ priv->stats.rx_rssi_percentage[rfpath] =
+ ((priv->stats.rx_rssi_percentage[rfpath] *
+ (RX_SMOOTH-1)) +
+ (prev_st->RxMIMOSignalStrength[rfpath])) /
+ (RX_SMOOTH);
+ }
+ RT_TRACE(COMP_DBG,
+ "Jacken -> priv->RxStats.RxRSSIPercentage[rfPath] = %d\n",
+ priv->stats.rx_rssi_percentage[rfpath]);
+ }
+ }
+
+
+ if (prev_st->bPacketBeacon) {
+ if (slide_beacon_adc_pwdb_statistics++ >=
+ PHY_Beacon_RSSI_SLID_WIN_MAX) {
+ slide_beacon_adc_pwdb_statistics =
+ PHY_Beacon_RSSI_SLID_WIN_MAX;
+ last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb
+ [slide_beacon_adc_pwdb_index];
+ priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
+ }
+ priv->stats.Slide_Beacon_Total += prev_st->RxPWDBAll;
+ priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] =
+ prev_st->RxPWDBAll;
+ slide_beacon_adc_pwdb_index++;
+ if (slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
+ slide_beacon_adc_pwdb_index = 0;
+ prev_st->RxPWDBAll = priv->stats.Slide_Beacon_Total /
+ slide_beacon_adc_pwdb_statistics;
+ if (prev_st->RxPWDBAll >= 3)
+ prev_st->RxPWDBAll -= 3;
+ }
+
+ RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
+ prev_st->bIsCCK ? "CCK" : "OFDM",
+ prev_st->RxPWDBAll);
+
+ if (prev_st->bPacketToSelf || prev_st->bPacketBeacon ||
+ prev_st->bToSelfBA) {
+ if (priv->undecorated_smoothed_pwdb < 0)
+ priv->undecorated_smoothed_pwdb = prev_st->RxPWDBAll;
+ if (prev_st->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) {
+ priv->undecorated_smoothed_pwdb =
+ (((priv->undecorated_smoothed_pwdb) *
+ (RX_SMOOTH-1)) +
+ (prev_st->RxPWDBAll)) / (RX_SMOOTH);
+ priv->undecorated_smoothed_pwdb =
+ priv->undecorated_smoothed_pwdb + 1;
+ } else {
+ priv->undecorated_smoothed_pwdb =
+ (((priv->undecorated_smoothed_pwdb) *
+ (RX_SMOOTH-1)) +
+ (prev_st->RxPWDBAll)) / (RX_SMOOTH);
+ }
+ rtl819x_update_rxsignalstatistics8190pci(priv, prev_st);
+ }
+
+ if (prev_st->SignalQuality != 0) {
+ if (prev_st->bPacketToSelf || prev_st->bPacketBeacon ||
+ prev_st->bToSelfBA) {
+ if (slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX) {
+ slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
+ last_evm =
+ priv->stats.slide_evm[slide_evm_index];
+ priv->stats.slide_evm_total -= last_evm;
+ }
+
+ priv->stats.slide_evm_total += prev_st->SignalQuality;
+
+ priv->stats.slide_evm[slide_evm_index++] =
+ prev_st->SignalQuality;
+ if (slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
+ slide_evm_index = 0;
+
+ tmp_val = priv->stats.slide_evm_total /
+ slide_evm_statistics;
+ priv->stats.signal_quality = tmp_val;
+ priv->stats.last_signal_strength_inpercent = tmp_val;
+ }
+
+ if (prev_st->bPacketToSelf ||
+ prev_st->bPacketBeacon ||
+ prev_st->bToSelfBA) {
+ for (ij = 0; ij < 2; ij++) {
+ if (prev_st->RxMIMOSignalQuality[ij] != -1) {
+ if (priv->stats.rx_evm_percentage[ij] == 0)
+ priv->stats.rx_evm_percentage[ij] =
+ prev_st->RxMIMOSignalQuality[ij];
+ priv->stats.rx_evm_percentage[ij] =
+ ((priv->stats.rx_evm_percentage[ij] *
+ (RX_SMOOTH - 1)) +
+ (prev_st->RxMIMOSignalQuality[ij])) /
+ (RX_SMOOTH);
+ }
+ }
+ }
+ }
+}
+
+static void rtl8192_TranslateRxSignalStuff(struct net_device *dev,
+ struct sk_buff *skb,
+ struct rtllib_rx_stats *pstats,
+ struct rx_desc *pdesc,
+ struct rx_fwinfo *pdrvinfo)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ bool bpacket_match_bssid, bpacket_toself;
+ bool bPacketBeacon = false;
+ struct rtllib_hdr_3addr *hdr;
+ bool bToSelfBA = false;
+ static struct rtllib_rx_stats previous_stats;
+ u16 fc, type;
+ u8 *tmp_buf;
+ u8 *praddr;
+
+ tmp_buf = skb->data + pstats->RxDrvInfoSize + pstats->RxBufShift;
+
+ hdr = (struct rtllib_hdr_3addr *)tmp_buf;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ praddr = hdr->addr1;
+
+ bpacket_match_bssid =
+ ((RTLLIB_FTYPE_CTL != type) &&
+ ether_addr_equal(priv->rtllib->current_network.bssid,
+ (fc & RTLLIB_FCTL_TODS) ? hdr->addr1 :
+ (fc & RTLLIB_FCTL_FROMDS) ? hdr->addr2 :
+ hdr->addr3) &&
+ (!pstats->bHwError) && (!pstats->bCRC) && (!pstats->bICV));
+ bpacket_toself = bpacket_match_bssid && /* check this */
+ ether_addr_equal(praddr, priv->rtllib->dev->dev_addr);
+ if (WLAN_FC_GET_FRAMETYPE(fc) == RTLLIB_STYPE_BEACON)
+ bPacketBeacon = true;
+ if (bpacket_match_bssid)
+ priv->stats.numpacket_matchbssid++;
+ if (bpacket_toself)
+ priv->stats.numpacket_toself++;
+ rtl8192_process_phyinfo(priv, tmp_buf, &previous_stats, pstats);
+ rtl8192_query_rxphystatus(priv, pstats, pdesc, pdrvinfo,
+ &previous_stats, bpacket_match_bssid,
+ bpacket_toself, bPacketBeacon, bToSelfBA);
+ rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
+}
+
+static void rtl8192_UpdateReceivedRateHistogramStatistics(
+ struct net_device *dev,
+ struct rtllib_rx_stats *pstats)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ u32 rcvType = 1;
+ u32 rateIndex;
+ u32 preamble_guardinterval;
+
+ if (pstats->bCRC)
+ rcvType = 2;
+ else if (pstats->bICV)
+ rcvType = 3;
+
+ if (pstats->bShortPreamble)
+ preamble_guardinterval = 1;
+ else
+ preamble_guardinterval = 0;
+
+ switch (pstats->rate) {
+ case MGN_1M:
+ rateIndex = 0;
+ break;
+ case MGN_2M:
+ rateIndex = 1;
+ break;
+ case MGN_5_5M:
+ rateIndex = 2;
+ break;
+ case MGN_11M:
+ rateIndex = 3;
+ break;
+ case MGN_6M:
+ rateIndex = 4;
+ break;
+ case MGN_9M:
+ rateIndex = 5;
+ break;
+ case MGN_12M:
+ rateIndex = 6;
+ break;
+ case MGN_18M:
+ rateIndex = 7;
+ break;
+ case MGN_24M:
+ rateIndex = 8;
+ break;
+ case MGN_36M:
+ rateIndex = 9;
+ break;
+ case MGN_48M:
+ rateIndex = 10;
+ break;
+ case MGN_54M:
+ rateIndex = 11;
+ break;
+ case MGN_MCS0:
+ rateIndex = 12;
+ break;
+ case MGN_MCS1:
+ rateIndex = 13;
+ break;
+ case MGN_MCS2:
+ rateIndex = 14;
+ break;
+ case MGN_MCS3:
+ rateIndex = 15;
+ break;
+ case MGN_MCS4:
+ rateIndex = 16;
+ break;
+ case MGN_MCS5:
+ rateIndex = 17;
+ break;
+ case MGN_MCS6:
+ rateIndex = 18;
+ break;
+ case MGN_MCS7:
+ rateIndex = 19;
+ break;
+ case MGN_MCS8:
+ rateIndex = 20;
+ break;
+ case MGN_MCS9:
+ rateIndex = 21;
+ break;
+ case MGN_MCS10:
+ rateIndex = 22;
+ break;
+ case MGN_MCS11:
+ rateIndex = 23;
+ break;
+ case MGN_MCS12:
+ rateIndex = 24;
+ break;
+ case MGN_MCS13:
+ rateIndex = 25;
+ break;
+ case MGN_MCS14:
+ rateIndex = 26;
+ break;
+ case MGN_MCS15:
+ rateIndex = 27;
+ break;
+ default:
+ rateIndex = 28;
+ break;
+ }
+ priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
+ priv->stats.received_rate_histogram[0][rateIndex]++;
+ priv->stats.received_rate_histogram[rcvType][rateIndex]++;
+}
+
+bool rtl8192_rx_query_status_desc(struct net_device *dev,
+ struct rtllib_rx_stats *stats,
+ struct rx_desc *pdesc,
+ struct sk_buff *skb)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rx_fwinfo *pDrvInfo = NULL;
+
+ stats->bICV = pdesc->ICV;
+ stats->bCRC = pdesc->CRC32;
+ stats->bHwError = pdesc->CRC32 | pdesc->ICV;
+
+ stats->Length = pdesc->Length;
+ if (stats->Length < 24)
+ stats->bHwError |= 1;
+
+ if (stats->bHwError) {
+ stats->bShift = false;
+
+ if (pdesc->CRC32) {
+ if (pdesc->Length < 500)
+ priv->stats.rxcrcerrmin++;
+ else if (pdesc->Length > 1000)
+ priv->stats.rxcrcerrmax++;
+ else
+ priv->stats.rxcrcerrmid++;
+ }
+ return false;
+ }
+
+ stats->RxDrvInfoSize = pdesc->RxDrvInfoSize;
+ stats->RxBufShift = ((pdesc->Shift)&0x03);
+ stats->Decrypted = !pdesc->SWDec;
+
+ pDrvInfo = (struct rx_fwinfo *)(skb->data + stats->RxBufShift);
+
+ stats->rate = HwRateToMRate90((bool)pDrvInfo->RxHT,
+ (u8)pDrvInfo->RxRate);
+ stats->bShortPreamble = pDrvInfo->SPLCP;
+
+ rtl8192_UpdateReceivedRateHistogramStatistics(dev, stats);
+
+ stats->bIsAMPDU = (pDrvInfo->PartAggr == 1);
+ stats->bFirstMPDU = (pDrvInfo->PartAggr == 1) &&
+ (pDrvInfo->FirstAGGR == 1);
+
+ stats->TimeStampLow = pDrvInfo->TSFL;
+ stats->TimeStampHigh = read_nic_dword(dev, TSFR+4);
+
+ rtl819x_UpdateRxPktTimeStamp(dev, stats);
+
+ if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0)
+ stats->bShift = 1;
+
+ stats->RxIs40MHzPacket = pDrvInfo->BW;
+
+ rtl8192_TranslateRxSignalStuff(dev, skb, stats, pdesc,
+ pDrvInfo);
+
+ if (pDrvInfo->FirstAGGR == 1 || pDrvInfo->PartAggr == 1)
+ RT_TRACE(COMP_RXDESC,
+ "pDrvInfo->FirstAGGR = %d, pDrvInfo->PartAggr = %d\n",
+ pDrvInfo->FirstAGGR, pDrvInfo->PartAggr);
+ skb_trim(skb, skb->len - 4/*sCrcLng*/);
+
+
+ stats->packetlength = stats->Length-4;
+ stats->fraglength = stats->packetlength;
+ stats->fragoffset = 0;
+ stats->ntotalfrag = 1;
+ return true;
+}
+
+void rtl8192_halt_adapter(struct net_device *dev, bool reset)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int i;
+ u8 OpMode;
+ u8 u1bTmp;
+ u32 ulRegRead;
+
+ OpMode = RT_OP_MODE_NO_LINK;
+ priv->rtllib->SetHwRegHandler(dev, HW_VAR_MEDIA_STATUS, &OpMode);
+
+ if (!priv->rtllib->bSupportRemoteWakeUp) {
+ u1bTmp = 0x0;
+ write_nic_byte(dev, CMDR, u1bTmp);
+ }
+
+ mdelay(20);
+
+ if (!reset) {
+ mdelay(150);
+
+ priv->bHwRfOffAction = 2;
+
+ if (!priv->rtllib->bSupportRemoteWakeUp) {
+ PHY_SetRtl8192eRfOff(dev);
+ ulRegRead = read_nic_dword(dev, CPU_GEN);
+ ulRegRead |= CPU_GEN_SYSTEM_RESET;
+ write_nic_dword(dev, CPU_GEN, ulRegRead);
+ } else {
+ write_nic_dword(dev, WFCRC0, 0xffffffff);
+ write_nic_dword(dev, WFCRC1, 0xffffffff);
+ write_nic_dword(dev, WFCRC2, 0xffffffff);
+
+
+ write_nic_byte(dev, PMR, 0x5);
+ write_nic_byte(dev, MacBlkCtrl, 0xa);
+ }
+ }
+
+ for (i = 0; i < MAX_QUEUE_SIZE; i++)
+ skb_queue_purge(&priv->rtllib->skb_waitQ[i]);
+ for (i = 0; i < MAX_QUEUE_SIZE; i++)
+ skb_queue_purge(&priv->rtllib->skb_aggQ[i]);
+
+ skb_queue_purge(&priv->skb_queue);
+}
+
+void rtl8192_update_ratr_table(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+ u8 *pMcsRate = ieee->dot11HTOperationalRateSet;
+ u32 ratr_value = 0;
+ u16 rate_config = 0;
+ u8 rate_index = 0;
+
+ rtl8192_config_rate(dev, &rate_config);
+ ratr_value = rate_config | *pMcsRate << 12;
+ switch (ieee->mode) {
+ case IEEE_A:
+ ratr_value &= 0x00000FF0;
+ break;
+ case IEEE_B:
+ ratr_value &= 0x0000000F;
+ break;
+ case IEEE_G:
+ case IEEE_G|IEEE_B:
+ ratr_value &= 0x00000FF7;
+ break;
+ case IEEE_N_24G:
+ case IEEE_N_5G:
+ if (ieee->pHTInfo->PeerMimoPs == 0) {
+ ratr_value &= 0x0007F007;
+ } else {
+ if (priv->rf_type == RF_1T2R)
+ ratr_value &= 0x000FF007;
+ else
+ ratr_value &= 0x0F81F007;
+ }
+ break;
+ default:
+ break;
+ }
+ ratr_value &= 0x0FFFFFFF;
+ if (ieee->pHTInfo->bCurTxBW40MHz &&
+ ieee->pHTInfo->bCurShortGI40MHz)
+ ratr_value |= 0x80000000;
+ else if (!ieee->pHTInfo->bCurTxBW40MHz &&
+ ieee->pHTInfo->bCurShortGI20MHz)
+ ratr_value |= 0x80000000;
+ write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
+ write_nic_byte(dev, UFWP, 1);
+}
+
+void
+rtl8192_InitializeVariables(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ strcpy(priv->nick, "rtl8192E");
+
+ priv->rtllib->softmac_features = IEEE_SOFTMAC_SCAN |
+ IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
+ IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE;
+
+ priv->rtllib->tx_headroom = sizeof(struct tx_fwinfo_8190pci);
+
+ priv->ShortRetryLimit = 0x30;
+ priv->LongRetryLimit = 0x30;
+
+ priv->EarlyRxThreshold = 7;
+ priv->pwrGroupCnt = 0;
+
+ priv->bIgnoreSilentReset = false;
+ priv->enable_gpio0 = 0;
+
+ priv->TransmitConfig = 0;
+
+ priv->ReceiveConfig = RCR_ADD3 |
+ RCR_AMF | RCR_ADF |
+ RCR_AICV |
+ RCR_AB | RCR_AM | RCR_APM |
+ RCR_AAP | ((u32)7<<RCR_MXDMA_OFFSET) |
+ ((u32)7 << RCR_FIFO_OFFSET) | RCR_ONLYERLPKT;
+
+ priv->irq_mask[0] = (u32)(IMR_ROK | IMR_VODOK | IMR_VIDOK |
+ IMR_BEDOK | IMR_BKDOK | IMR_HCCADOK |
+ IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK |
+ IMR_BDOK | IMR_RXCMDOK | IMR_TIMEOUT0 |
+ IMR_RDU | IMR_RXFOVW | IMR_TXFOVW |
+ IMR_BcnInt | IMR_TBDOK | IMR_TBDER);
+
+
+ priv->MidHighPwrTHR_L1 = 0x3B;
+ priv->MidHighPwrTHR_L2 = 0x40;
+ priv->PwrDomainProtect = false;
+
+ priv->bfirst_after_down = false;
+}
+
+void rtl8192_EnableInterrupt(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ priv->irq_enabled = 1;
+
+ write_nic_dword(dev, INTA_MASK, priv->irq_mask[0]);
+
+}
+
+void rtl8192_DisableInterrupt(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ write_nic_dword(dev, INTA_MASK, 0);
+
+ priv->irq_enabled = 0;
+}
+
+void rtl8192_ClearInterrupt(struct net_device *dev)
+{
+ u32 tmp = 0;
+
+ tmp = read_nic_dword(dev, ISR);
+ write_nic_dword(dev, ISR, tmp);
+}
+
+
+void rtl8192_enable_rx(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ write_nic_dword(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]);
+}
+
+static const u32 TX_DESC_BASE[] = {
+ BKQDA, BEQDA, VIQDA, VOQDA, HCCAQDA, CQDA, MQDA, HQDA, BQDA
+};
+
+void rtl8192_enable_tx(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ u32 i;
+
+ for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
+ write_nic_dword(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma);
+}
+
+
+void rtl8192_interrupt_recognized(struct net_device *dev, u32 *p_inta,
+ u32 *p_intb)
+{
+ *p_inta = read_nic_dword(dev, ISR);
+ write_nic_dword(dev, ISR, *p_inta);
+}
+
+bool rtl8192_HalRxCheckStuck(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u16 RegRxCounter = read_nic_word(dev, 0x130);
+ bool bStuck = false;
+ static u8 rx_chk_cnt;
+ u32 SlotIndex = 0, TotalRxStuckCount = 0;
+ u8 i;
+ u8 SilentResetRxSoltNum = 4;
+
+ RT_TRACE(COMP_RESET, "%s(): RegRxCounter is %d, RxCounter is %d\n",
+ __func__, RegRxCounter, priv->RxCounter);
+
+ rx_chk_cnt++;
+ if (priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5)) {
+ rx_chk_cnt = 0;
+ } else if ((priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High + 5))
+ && (((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) &&
+ (priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_40M))
+ || ((priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) &&
+ (priv->undecorated_smoothed_pwdb >= RateAdaptiveTH_Low_20M)))) {
+ if (rx_chk_cnt < 2)
+ return bStuck;
+ rx_chk_cnt = 0;
+ } else if ((((priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) &&
+ (priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_40M)) ||
+ ((priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) &&
+ (priv->undecorated_smoothed_pwdb < RateAdaptiveTH_Low_20M))) &&
+ priv->undecorated_smoothed_pwdb >= VeryLowRSSI) {
+ if (rx_chk_cnt < 4)
+ return bStuck;
+ rx_chk_cnt = 0;
+ } else {
+ if (rx_chk_cnt < 8)
+ return bStuck;
+ rx_chk_cnt = 0;
+ }
+
+
+ SlotIndex = (priv->SilentResetRxSlotIndex++)%SilentResetRxSoltNum;
+
+ if (priv->RxCounter == RegRxCounter) {
+ priv->SilentResetRxStuckEvent[SlotIndex] = 1;
+
+ for (i = 0; i < SilentResetRxSoltNum; i++)
+ TotalRxStuckCount += priv->SilentResetRxStuckEvent[i];
+
+ if (TotalRxStuckCount == SilentResetRxSoltNum) {
+ bStuck = true;
+ for (i = 0; i < SilentResetRxSoltNum; i++)
+ TotalRxStuckCount +=
+ priv->SilentResetRxStuckEvent[i];
+ }
+
+
+ } else {
+ priv->SilentResetRxStuckEvent[SlotIndex] = 0;
+ }
+
+ priv->RxCounter = RegRxCounter;
+
+ return bStuck;
+}
+
+bool rtl8192_HalTxCheckStuck(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ bool bStuck = false;
+ u16 RegTxCounter = read_nic_word(dev, 0x128);
+
+ RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n",
+ __func__, RegTxCounter, priv->TxCounter);
+
+ if (priv->TxCounter == RegTxCounter)
+ bStuck = true;
+
+ priv->TxCounter = RegTxCounter;
+
+ return bStuck;
+}
+
+bool rtl8192_GetNmodeSupportBySecCfg(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ if (ieee->rtllib_ap_sec_type &&
+ (ieee->rtllib_ap_sec_type(priv->rtllib)&(SEC_ALG_WEP |
+ SEC_ALG_TKIP))) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool rtl8192_GetHalfNmodeSupportByAPs(struct net_device *dev)
+{
+ bool Reval;
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ if (ieee->bHalfWirelessN24GMode == true)
+ Reval = true;
+ else
+ Reval = false;
+
+ return Reval;
+}
+
+u8 rtl8192_QueryIsShort(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc)
+{
+ u8 tmp_Short;
+
+ tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) :
+ ((tcb_desc->bUseShortPreamble) ? 1 : 0);
+ if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
+ tmp_Short = 0;
+
+ return tmp_Short;
+}
+
+void ActUpdateChannelAccessSetting(struct net_device *dev,
+ enum wireless_mode WirelessMode,
+ struct channel_access_setting *ChnlAccessSetting)
+{
+}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h
new file mode 100644
index 000000000..dbe0e1c87
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _RTL8192E_H
+#define _RTL8192E_H
+
+#include "r8190P_def.h"
+
+u8 rtl8192_QueryIsShort(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc);
+bool rtl8192_GetHalfNmodeSupportByAPs(struct net_device *dev);
+bool rtl8192_GetNmodeSupportBySecCfg(struct net_device *dev);
+bool rtl8192_HalTxCheckStuck(struct net_device *dev);
+bool rtl8192_HalRxCheckStuck(struct net_device *dev);
+void rtl8192_interrupt_recognized(struct net_device *dev, u32 *p_inta,
+ u32 *p_intb);
+void rtl8192_enable_rx(struct net_device *dev);
+void rtl8192_enable_tx(struct net_device *dev);
+void rtl8192_EnableInterrupt(struct net_device *dev);
+void rtl8192_DisableInterrupt(struct net_device *dev);
+void rtl8192_ClearInterrupt(struct net_device *dev);
+void rtl8192_InitializeVariables(struct net_device *dev);
+void rtl8192e_start_beacon(struct net_device *dev);
+void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val);
+void rtl8192_get_eeprom_size(struct net_device *dev);
+bool rtl8192_adapter_start(struct net_device *dev);
+void rtl8192_link_change(struct net_device *dev);
+void rtl8192_AllowAllDestAddr(struct net_device *dev, bool bAllowAllDA,
+ bool WriteIntoReg);
+void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc,
+ struct cb_desc *cb_desc,
+ struct sk_buff *skb);
+void rtl8192_tx_fill_cmd_desc(struct net_device *dev,
+ struct tx_desc_cmd *entry,
+ struct cb_desc *cb_desc, struct sk_buff *skb);
+bool rtl8192_rx_query_status_desc(struct net_device *dev,
+ struct rtllib_rx_stats *stats,
+ struct rx_desc *pdesc,
+ struct sk_buff *skb);
+void rtl8192_halt_adapter(struct net_device *dev, bool reset);
+void rtl8192_update_ratr_table(struct net_device *dev);
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
new file mode 100644
index 000000000..fd6574e67
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
@@ -0,0 +1,319 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#include "rtl_core.h"
+#include "r8192E_hw.h"
+#include "r8192E_hwimg.h"
+#include "r8192E_firmware.h"
+#include <linux/firmware.h>
+
+void firmware_init_param(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_firmware *pfirmware = priv->pFirmware;
+
+ pfirmware->cmdpacket_frag_thresold = GET_COMMAND_PACKET_FRAG_THRESHOLD(
+ MAX_TRANSMIT_BUFFER_SIZE);
+}
+
+static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
+ u32 buffer_len)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u16 frag_threshold;
+ u16 frag_length, frag_offset = 0;
+ int i;
+
+ struct rt_firmware *pfirmware = priv->pFirmware;
+ struct sk_buff *skb;
+ unsigned char *seg_ptr;
+ struct cb_desc *tcb_desc;
+ u8 bLastIniPkt;
+
+ firmware_init_param(dev);
+ frag_threshold = pfirmware->cmdpacket_frag_thresold;
+ do {
+ if ((buffer_len - frag_offset) > frag_threshold) {
+ frag_length = frag_threshold;
+ bLastIniPkt = 0;
+
+ } else {
+ frag_length = buffer_len - frag_offset;
+ bLastIniPkt = 1;
+
+ }
+
+ skb = dev_alloc_skb(frag_length + 4);
+ memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
+ tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+ tcb_desc->queue_index = TXCMD_QUEUE;
+ tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
+ tcb_desc->bLastIniPkt = bLastIniPkt;
+
+ seg_ptr = skb->data;
+ for (i = 0; i < frag_length; i += 4) {
+ *seg_ptr++ = ((i+0) < frag_length) ?
+ code_virtual_address[i+3] : 0;
+ *seg_ptr++ = ((i+1) < frag_length) ?
+ code_virtual_address[i+2] : 0;
+ *seg_ptr++ = ((i+2) < frag_length) ?
+ code_virtual_address[i+1] : 0;
+ *seg_ptr++ = ((i+3) < frag_length) ?
+ code_virtual_address[i+0] : 0;
+ }
+ tcb_desc->txbuf_size = (u16)i;
+ skb_put(skb, i);
+
+ if (!priv->rtllib->check_nic_enough_desc(dev, tcb_desc->queue_index) ||
+ (!skb_queue_empty(&priv->rtllib->skb_waitQ[tcb_desc->queue_index])) ||
+ (priv->rtllib->queue_stop)) {
+ RT_TRACE(COMP_FIRMWARE,
+ "===================> tx full!\n");
+ skb_queue_tail(&priv->rtllib->skb_waitQ
+ [tcb_desc->queue_index], skb);
+ } else {
+ priv->rtllib->softmac_hard_start_xmit(skb, dev);
+ }
+
+ code_virtual_address += frag_length;
+ frag_offset += frag_length;
+
+ } while (frag_offset < buffer_len);
+
+ write_nic_byte(dev, TPPoll, TPPoll_CQ);
+
+ return true;
+}
+
+static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
+{
+ bool rt_status = true;
+ u32 CPU_status = 0;
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(200);
+ while (time_before(jiffies, timeout)) {
+ CPU_status = read_nic_dword(dev, CPU_GEN);
+ if (CPU_status & CPU_GEN_PUT_CODE_OK)
+ break;
+ mdelay(2);
+ }
+
+ if (!(CPU_status&CPU_GEN_PUT_CODE_OK)) {
+ RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
+ goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
+ } else {
+ RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
+ }
+
+ CPU_status = read_nic_dword(dev, CPU_GEN);
+ write_nic_byte(dev, CPU_GEN,
+ (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
+ mdelay(1);
+
+ timeout = jiffies + msecs_to_jiffies(200);
+ while (time_before(jiffies, timeout)) {
+ CPU_status = read_nic_dword(dev, CPU_GEN);
+ if (CPU_status&CPU_GEN_BOOT_RDY)
+ break;
+ mdelay(2);
+ }
+
+ if (!(CPU_status&CPU_GEN_BOOT_RDY))
+ goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
+ else
+ RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
+
+ return rt_status;
+
+CPUCheckMainCodeOKAndTurnOnCPU_Fail:
+ RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
+ rt_status = false;
+ return rt_status;
+}
+
+static bool CPUcheck_firmware_ready(struct net_device *dev)
+{
+
+ bool rt_status = true;
+ u32 CPU_status = 0;
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(20);
+ while (time_before(jiffies, timeout)) {
+ CPU_status = read_nic_dword(dev, CPU_GEN);
+ if (CPU_status&CPU_GEN_FIRM_RDY)
+ break;
+ mdelay(2);
+ }
+
+ if (!(CPU_status&CPU_GEN_FIRM_RDY))
+ goto CPUCheckFirmwareReady_Fail;
+ else
+ RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
+
+ return rt_status;
+
+CPUCheckFirmwareReady_Fail:
+ RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
+ rt_status = false;
+ return rt_status;
+
+}
+
+static bool firmware_check_ready(struct net_device *dev,
+ u8 load_fw_status)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_firmware *pfirmware = priv->pFirmware;
+ bool rt_status = true;
+
+ switch (load_fw_status) {
+ case FW_INIT_STEP0_BOOT:
+ pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
+ break;
+
+ case FW_INIT_STEP1_MAIN:
+ pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
+
+ rt_status = CPUcheck_maincodeok_turnonCPU(dev);
+ if (rt_status)
+ pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
+ else
+ RT_TRACE(COMP_FIRMWARE,
+ "CPUcheck_maincodeok_turnonCPU fail!\n");
+
+ break;
+
+ case FW_INIT_STEP2_DATA:
+ pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
+ mdelay(1);
+
+ rt_status = CPUcheck_firmware_ready(dev);
+ if (rt_status)
+ pfirmware->firmware_status = FW_STATUS_5_READY;
+ else
+ RT_TRACE(COMP_FIRMWARE,
+ "CPUcheck_firmware_ready fail(%d)!\n",
+ rt_status);
+
+ break;
+ default:
+ rt_status = false;
+ RT_TRACE(COMP_FIRMWARE, "Unknown firmware status");
+ break;
+ }
+
+ return rt_status;
+}
+
+bool init_firmware(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ bool rt_status = true;
+
+ u32 file_length = 0;
+ u8 *mapped_file = NULL;
+ u8 init_step = 0;
+ enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
+ enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
+
+ struct rt_firmware *pfirmware = priv->pFirmware;
+
+ RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
+
+ if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
+ rst_opt = OPT_SYSTEM_RESET;
+ starting_state = FW_INIT_STEP0_BOOT;
+
+ } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
+ rst_opt = OPT_FIRMWARE_RESET;
+ starting_state = FW_INIT_STEP2_DATA;
+ } else {
+ RT_TRACE(COMP_FIRMWARE,
+ "PlatformInitFirmware: undefined firmware state\n");
+ }
+
+ for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA;
+ init_step++) {
+ if (rst_opt == OPT_SYSTEM_RESET) {
+ if (pfirmware->firmware_buf_size[init_step] == 0) {
+ const char *fw_name[3] = {
+ RTL8192E_BOOT_IMG_FW,
+ RTL8192E_MAIN_IMG_FW,
+ RTL8192E_DATA_IMG_FW
+ };
+ const struct firmware *fw_entry;
+ int rc;
+
+ rc = reject_firmware(&fw_entry,
+ fw_name[init_step],
+ &priv->pdev->dev);
+ if (rc < 0) {
+ RT_TRACE(COMP_FIRMWARE,
+ "request firmware fail!\n");
+ goto download_firmware_fail;
+ }
+ if (fw_entry->size >
+ sizeof(pfirmware->firmware_buf[init_step])) {
+ RT_TRACE(COMP_FIRMWARE,
+ "img file size exceed the container struct buffer fail!\n");
+ goto download_firmware_fail;
+ }
+
+ if (init_step != FW_INIT_STEP1_MAIN) {
+ memcpy(pfirmware->firmware_buf[init_step],
+ fw_entry->data, fw_entry->size);
+ pfirmware->firmware_buf_size[init_step] =
+ fw_entry->size;
+
+ } else {
+ memset(pfirmware->firmware_buf[init_step],
+ 0, 128);
+ memcpy(&pfirmware->firmware_buf[init_step][128],
+ fw_entry->data, fw_entry->size);
+ pfirmware->firmware_buf_size[init_step] =
+ fw_entry->size + 128;
+ }
+
+ if (rst_opt == OPT_SYSTEM_RESET)
+ release_firmware(fw_entry);
+ }
+ }
+
+ mapped_file = pfirmware->firmware_buf[init_step];
+ file_length = pfirmware->firmware_buf_size[init_step];
+
+ rt_status = fw_download_code(dev, mapped_file, file_length);
+ if (!rt_status)
+ goto download_firmware_fail;
+
+ if (!firmware_check_ready(dev, init_step))
+ goto download_firmware_fail;
+ }
+
+ RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
+ return rt_status;
+
+download_firmware_fail:
+ RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
+ rt_status = false;
+ return rt_status;
+
+}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
new file mode 100644
index 000000000..8ffb23433
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_FIRMWARE_H
+#define __INC_FIRMWARE_H
+
+#define RTL8190_CPU_START_OFFSET 0x80
+
+#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4*(v/4) - 8)
+
+#define RTL8192E_BOOT_IMG_FW "/*(DEBLOBBED)*/"
+#define RTL8192E_MAIN_IMG_FW "/*(DEBLOBBED)*/"
+#define RTL8192E_DATA_IMG_FW "/*(DEBLOBBED)*/"
+
+enum firmware_init_step {
+ FW_INIT_STEP0_BOOT = 0,
+ FW_INIT_STEP1_MAIN = 1,
+ FW_INIT_STEP2_DATA = 2,
+};
+
+enum opt_rst_type {
+ OPT_SYSTEM_RESET = 0,
+ OPT_FIRMWARE_RESET = 1,
+};
+
+enum desc_packet_type {
+ DESC_PACKET_TYPE_INIT = 0,
+ DESC_PACKET_TYPE_NORMAL = 1,
+};
+
+enum firmware_status {
+ FW_STATUS_0_INIT = 0,
+ FW_STATUS_1_MOVE_BOOT_CODE = 1,
+ FW_STATUS_2_MOVE_MAIN_CODE = 2,
+ FW_STATUS_3_TURNON_CPU = 3,
+ FW_STATUS_4_MOVE_DATA_CODE = 4,
+ FW_STATUS_5_READY = 5,
+};
+
+struct fw_seg_container {
+ u16 seg_size;
+ u8 *seg_ptr;
+};
+
+struct rt_firmware {
+ enum firmware_status firmware_status;
+ u16 cmdpacket_frag_thresold;
+#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000
+#define MAX_FW_INIT_STEP 3
+ u8 firmware_buf[MAX_FW_INIT_STEP][RTL8190_MAX_FIRMWARE_CODE_SIZE];
+ u16 firmware_buf_size[MAX_FW_INIT_STEP];
+};
+
+bool init_firmware(struct net_device *dev);
+extern void firmware_init_param(struct net_device *dev);
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
new file mode 100644
index 000000000..43c3fb859
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
@@ -0,0 +1,453 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+
+#ifndef R8180_HW
+#define R8180_HW
+
+enum baseband_config {
+ BaseBand_Config_PHY_REG = 0,
+ BaseBand_Config_AGC_TAB = 1,
+};
+
+#define RTL8187_REQT_READ 0xc0
+#define RTL8187_REQT_WRITE 0x40
+#define RTL8187_REQ_GET_REGS 0x05
+#define RTL8187_REQ_SET_REGS 0x05
+
+#define MAX_TX_URB 5
+#define MAX_RX_URB 16
+#define RX_URB_SIZE 9100
+
+#define BB_ANTATTEN_CHAN14 0x0c
+#define BB_ANTENNA_B 0x40
+
+#define BB_HOST_BANG (1<<30)
+#define BB_HOST_BANG_EN (1<<2)
+#define BB_HOST_BANG_CLK (1<<1)
+#define BB_HOST_BANG_RW (1<<3)
+#define BB_HOST_BANG_DATA 1
+
+#define RTL8190_EEPROM_ID 0x8129
+#define EEPROM_VID 0x02
+#define EEPROM_DID 0x04
+#define EEPROM_NODE_ADDRESS_BYTE_0 0x0C
+
+#define EEPROM_TxPowerDiff 0x1F
+
+
+#define EEPROM_PwDiff 0x21
+#define EEPROM_CrystalCap 0x22
+
+
+
+#define EEPROM_TxPwIndex_CCK_V1 0x29
+#define EEPROM_TxPwIndex_OFDM_24G_V1 0x2C
+#define EEPROM_TxPwIndex_Ver 0x27
+
+#define EEPROM_Default_TxPowerDiff 0x0
+#define EEPROM_Default_ThermalMeter 0x77
+#define EEPROM_Default_AntTxPowerDiff 0x0
+#define EEPROM_Default_TxPwDiff_CrystalCap 0x5
+#define EEPROM_Default_PwDiff 0x4
+#define EEPROM_Default_CrystalCap 0x5
+#define EEPROM_Default_TxPower 0x1010
+#define EEPROM_ICVersion_ChannelPlan 0x7C
+#define EEPROM_Customer_ID 0x7B
+#define EEPROM_RFInd_PowerDiff 0x28
+#define EEPROM_ThermalMeter 0x29
+#define EEPROM_TxPwDiff_CrystalCap 0x2A
+#define EEPROM_TxPwIndex_CCK 0x2C
+#define EEPROM_TxPwIndex_OFDM_24G 0x3A
+#define EEPROM_Default_TxPowerLevel 0x10
+#define EEPROM_IC_VER 0x7d
+#define EEPROM_CRC 0x7e
+
+#define EEPROM_CID_DEFAULT 0x0
+#define EEPROM_CID_CAMEO 0x1
+#define EEPROM_CID_RUNTOP 0x2
+#define EEPROM_CID_Senao 0x3
+#define EEPROM_CID_TOSHIBA 0x4
+#define EEPROM_CID_NetCore 0x5
+#define EEPROM_CID_Nettronix 0x6
+#define EEPROM_CID_Pronet 0x7
+#define EEPROM_CID_DLINK 0x8
+#define EEPROM_CID_WHQL 0xFE
+enum _RTL8192Pci_HW {
+ MAC0 = 0x000,
+ MAC1 = 0x001,
+ MAC2 = 0x002,
+ MAC3 = 0x003,
+ MAC4 = 0x004,
+ MAC5 = 0x005,
+ PCIF = 0x009,
+#define MXDMA2_16bytes 0x000
+#define MXDMA2_32bytes 0x001
+#define MXDMA2_64bytes 0x010
+#define MXDMA2_128bytes 0x011
+#define MXDMA2_256bytes 0x100
+#define MXDMA2_512bytes 0x101
+#define MXDMA2_1024bytes 0x110
+#define MXDMA2_NoLimit 0x7
+
+#define MULRW_SHIFT 3
+#define MXDMA2_RX_SHIFT 4
+#define MXDMA2_TX_SHIFT 0
+ PMR = 0x00c,
+ EPROM_CMD = 0x00e,
+#define EPROM_CMD_RESERVED_MASK BIT5
+#define EPROM_CMD_9356SEL BIT4
+#define EPROM_CMD_OPERATING_MODE_SHIFT 6
+#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
+#define EPROM_CMD_CONFIG 0x3
+#define EPROM_CMD_NORMAL 0
+#define EPROM_CMD_LOAD 1
+#define EPROM_CMD_PROGRAM 2
+#define EPROM_CS_SHIFT 3
+#define EPROM_CK_SHIFT 2
+#define EPROM_W_SHIFT 1
+#define EPROM_R_SHIFT 0
+
+ AFR = 0x010,
+#define AFR_CardBEn (1<<0)
+#define AFR_CLKRUN_SEL (1<<1)
+#define AFR_FuncRegEn (1<<2)
+
+ ANAPAR = 0x17,
+#define BB_GLOBAL_RESET_BIT 0x1
+ BB_GLOBAL_RESET = 0x020,
+ BSSIDR = 0x02E,
+ CMDR = 0x037,
+#define CR_RST 0x10
+#define CR_RE 0x08
+#define CR_TE 0x04
+#define CR_MulRW 0x01
+ SIFS = 0x03E,
+ TCR = 0x040,
+ RCR = 0x044,
+#define RCR_FILTER_MASK (BIT0 | BIT1 | BIT2 | BIT3 | BIT5 | BIT12 | \
+ BIT18 | BIT19 | BIT20 | BIT21 | BIT22 | BIT23)
+#define RCR_ONLYERLPKT BIT31
+#define RCR_ENCS2 BIT30
+#define RCR_ENCS1 BIT29
+#define RCR_ENMBID BIT27
+#define RCR_ACKTXBW (BIT24|BIT25)
+#define RCR_CBSSID BIT23
+#define RCR_APWRMGT BIT22
+#define RCR_ADD3 BIT21
+#define RCR_AMF BIT20
+#define RCR_ACF BIT19
+#define RCR_ADF BIT18
+#define RCR_RXFTH BIT13
+#define RCR_AICV BIT12
+#define RCR_ACRC32 BIT5
+#define RCR_AB BIT3
+#define RCR_AM BIT2
+#define RCR_APM BIT1
+#define RCR_AAP BIT0
+#define RCR_MXDMA_OFFSET 8
+#define RCR_FIFO_OFFSET 13
+ SLOT_TIME = 0x049,
+ ACK_TIMEOUT = 0x04c,
+ PIFS_TIME = 0x04d,
+ USTIME = 0x04e,
+ EDCAPARA_BE = 0x050,
+ EDCAPARA_BK = 0x054,
+ EDCAPARA_VO = 0x058,
+ EDCAPARA_VI = 0x05C,
+#define AC_PARAM_TXOP_LIMIT_OFFSET 16
+#define AC_PARAM_ECW_MAX_OFFSET 12
+#define AC_PARAM_ECW_MIN_OFFSET 8
+#define AC_PARAM_AIFS_OFFSET 0
+ RFPC = 0x05F,
+ CWRR = 0x060,
+ BCN_TCFG = 0x062,
+#define BCN_TCFG_CW_SHIFT 8
+#define BCN_TCFG_IFS 0
+ BCN_INTERVAL = 0x070,
+ ATIMWND = 0x072,
+ BCN_DRV_EARLY_INT = 0x074,
+#define BCN_DRV_EARLY_INT_SWBCN_SHIFT 8
+#define BCN_DRV_EARLY_INT_TIME_SHIFT 0
+ BCN_DMATIME = 0x076,
+ BCN_ERR_THRESH = 0x078,
+ RWCAM = 0x0A0,
+#define CAM_CM_SecCAMPolling BIT31
+#define CAM_CM_SecCAMClr BIT30
+#define CAM_CM_SecCAMWE BIT16
+#define CAM_VALID BIT15
+#define CAM_NOTVALID 0x0000
+#define CAM_USEDK BIT5
+
+#define CAM_NONE 0x0
+#define CAM_WEP40 0x01
+#define CAM_TKIP 0x02
+#define CAM_AES 0x04
+#define CAM_WEP104 0x05
+
+#define TOTAL_CAM_ENTRY 32
+
+#define CAM_CONFIG_USEDK true
+#define CAM_CONFIG_NO_USEDK false
+#define CAM_WRITE BIT16
+#define CAM_READ 0x00000000
+#define CAM_POLLINIG BIT31
+#define SCR_UseDK 0x01
+ WCAMI = 0x0A4,
+ RCAMO = 0x0A8,
+ SECR = 0x0B0,
+#define SCR_TxUseDK BIT0
+#define SCR_RxUseDK BIT1
+#define SCR_TxEncEnable BIT2
+#define SCR_RxDecEnable BIT3
+#define SCR_SKByA2 BIT4
+#define SCR_NoSKMC BIT5
+ SWREGULATOR = 0x0BD,
+ INTA_MASK = 0x0f4,
+#define IMR8190_DISABLED 0x0
+#define IMR_ATIMEND BIT28
+#define IMR_TBDOK BIT27
+#define IMR_TBDER BIT26
+#define IMR_TXFOVW BIT15
+#define IMR_TIMEOUT0 BIT14
+#define IMR_BcnInt BIT13
+#define IMR_RXFOVW BIT12
+#define IMR_RDU BIT11
+#define IMR_RXCMDOK BIT10
+#define IMR_BDOK BIT9
+#define IMR_HIGHDOK BIT8
+#define IMR_COMDOK BIT7
+#define IMR_MGNTDOK BIT6
+#define IMR_HCCADOK BIT5
+#define IMR_BKDOK BIT4
+#define IMR_BEDOK BIT3
+#define IMR_VIDOK BIT2
+#define IMR_VODOK BIT1
+#define IMR_ROK BIT0
+ ISR = 0x0f8,
+ TPPoll = 0x0fd,
+#define TPPoll_BKQ BIT0
+#define TPPoll_BEQ BIT1
+#define TPPoll_VIQ BIT2
+#define TPPoll_VOQ BIT3
+#define TPPoll_BQ BIT4
+#define TPPoll_CQ BIT5
+#define TPPoll_MQ BIT6
+#define TPPoll_HQ BIT7
+#define TPPoll_HCCAQ BIT8
+#define TPPoll_StopBK BIT9
+#define TPPoll_StopBE BIT10
+#define TPPoll_StopVI BIT11
+#define TPPoll_StopVO BIT12
+#define TPPoll_StopMgt BIT13
+#define TPPoll_StopHigh BIT14
+#define TPPoll_StopHCCA BIT15
+#define TPPoll_SHIFT 8
+
+ PSR = 0x0ff,
+#define PSR_GEN 0x0
+#define PSR_CPU 0x1
+ CPU_GEN = 0x100,
+ BB_RESET = 0x101,
+#define CPU_CCK_LOOPBACK 0x00030000
+#define CPU_GEN_SYSTEM_RESET 0x00000001
+#define CPU_GEN_FIRMWARE_RESET 0x00000008
+#define CPU_GEN_BOOT_RDY 0x00000010
+#define CPU_GEN_FIRM_RDY 0x00000020
+#define CPU_GEN_PUT_CODE_OK 0x00000080
+#define CPU_GEN_BB_RST 0x00000100
+#define CPU_GEN_PWR_STB_CPU 0x00000004
+#define CPU_GEN_NO_LOOPBACK_MSK 0xFFF8FFFF
+#define CPU_GEN_NO_LOOPBACK_SET 0x00080000
+#define CPU_GEN_GPIO_UART 0x00007000
+
+ LED1Cfg = 0x154,
+ LED0Cfg = 0x155,
+
+ AcmAvg = 0x170,
+ AcmHwCtrl = 0x171,
+#define AcmHw_HwEn BIT0
+#define AcmHw_BeqEn BIT1
+#define AcmHw_ViqEn BIT2
+#define AcmHw_VoqEn BIT3
+#define AcmHw_BeqStatus BIT4
+#define AcmHw_ViqStatus BIT5
+#define AcmHw_VoqStatus BIT6
+ AcmFwCtrl = 0x172,
+#define AcmFw_BeqStatus BIT0
+#define AcmFw_ViqStatus BIT1
+#define AcmFw_VoqStatus BIT2
+ VOAdmTime = 0x174,
+ VIAdmTime = 0x178,
+ BEAdmTime = 0x17C,
+ RQPN1 = 0x180,
+ RQPN2 = 0x184,
+ RQPN3 = 0x188,
+ QPRR = 0x1E0,
+ QPNR = 0x1F0,
+ BQDA = 0x200,
+ HQDA = 0x204,
+ CQDA = 0x208,
+ MQDA = 0x20C,
+ HCCAQDA = 0x210,
+ VOQDA = 0x214,
+ VIQDA = 0x218,
+ BEQDA = 0x21C,
+ BKQDA = 0x220,
+ RCQDA = 0x224,
+ RDQDA = 0x228,
+
+ MAR0 = 0x240,
+ MAR4 = 0x244,
+
+ CCX_PERIOD = 0x250,
+ CLM_RESULT = 0x251,
+ NHM_PERIOD = 0x252,
+
+ NHM_THRESHOLD0 = 0x253,
+ NHM_THRESHOLD1 = 0x254,
+ NHM_THRESHOLD2 = 0x255,
+ NHM_THRESHOLD3 = 0x256,
+ NHM_THRESHOLD4 = 0x257,
+ NHM_THRESHOLD5 = 0x258,
+ NHM_THRESHOLD6 = 0x259,
+
+ MCTRL = 0x25A,
+
+ NHM_RPI_COUNTER0 = 0x264,
+ NHM_RPI_COUNTER1 = 0x265,
+ NHM_RPI_COUNTER2 = 0x266,
+ NHM_RPI_COUNTER3 = 0x267,
+ NHM_RPI_COUNTER4 = 0x268,
+ NHM_RPI_COUNTER5 = 0x269,
+ NHM_RPI_COUNTER6 = 0x26A,
+ NHM_RPI_COUNTER7 = 0x26B,
+ WFCRC0 = 0x2f0,
+ WFCRC1 = 0x2f4,
+ WFCRC2 = 0x2f8,
+
+ BW_OPMODE = 0x300,
+#define BW_OPMODE_11J BIT0
+#define BW_OPMODE_5G BIT1
+#define BW_OPMODE_20MHZ BIT2
+ IC_VERRSION = 0x301,
+ MSR = 0x303,
+#define MSR_LINK_MASK ((1<<0)|(1<<1))
+#define MSR_LINK_MANAGED 2
+#define MSR_LINK_NONE 0
+#define MSR_LINK_SHIFT 0
+#define MSR_LINK_ADHOC 1
+#define MSR_LINK_MASTER 3
+#define MSR_LINK_ENEDCA (1<<4)
+
+#define MSR_NOLINK 0x00
+#define MSR_ADHOC 0x01
+#define MSR_INFRA 0x02
+#define MSR_AP 0x03
+
+ RETRY_LIMIT = 0x304,
+#define RETRY_LIMIT_SHORT_SHIFT 8
+#define RETRY_LIMIT_LONG_SHIFT 0
+ TSFR = 0x308,
+ RRSR = 0x310,
+#define RRSR_RSC_OFFSET 21
+#define RRSR_SHORT_OFFSET 23
+#define RRSR_RSC_DUPLICATE 0x600000
+#define RRSR_RSC_UPSUBCHNL 0x400000
+#define RRSR_RSC_LOWSUBCHNL 0x200000
+#define RRSR_SHORT 0x800000
+#define RRSR_1M BIT0
+#define RRSR_2M BIT1
+#define RRSR_5_5M BIT2
+#define RRSR_11M BIT3
+#define RRSR_6M BIT4
+#define RRSR_9M BIT5
+#define RRSR_12M BIT6
+#define RRSR_18M BIT7
+#define RRSR_24M BIT8
+#define RRSR_36M BIT9
+#define RRSR_48M BIT10
+#define RRSR_54M BIT11
+#define RRSR_MCS0 BIT12
+#define RRSR_MCS1 BIT13
+#define RRSR_MCS2 BIT14
+#define RRSR_MCS3 BIT15
+#define RRSR_MCS4 BIT16
+#define RRSR_MCS5 BIT17
+#define RRSR_MCS6 BIT18
+#define RRSR_MCS7 BIT19
+#define BRSR_AckShortPmb BIT23
+ UFWP = 0x318,
+ RATR0 = 0x320,
+#define RATR_1M 0x00000001
+#define RATR_2M 0x00000002
+#define RATR_55M 0x00000004
+#define RATR_11M 0x00000008
+#define RATR_6M 0x00000010
+#define RATR_9M 0x00000020
+#define RATR_12M 0x00000040
+#define RATR_18M 0x00000080
+#define RATR_24M 0x00000100
+#define RATR_36M 0x00000200
+#define RATR_48M 0x00000400
+#define RATR_54M 0x00000800
+#define RATR_MCS0 0x00001000
+#define RATR_MCS1 0x00002000
+#define RATR_MCS2 0x00004000
+#define RATR_MCS3 0x00008000
+#define RATR_MCS4 0x00010000
+#define RATR_MCS5 0x00020000
+#define RATR_MCS6 0x00040000
+#define RATR_MCS7 0x00080000
+#define RATR_MCS8 0x00100000
+#define RATR_MCS9 0x00200000
+#define RATR_MCS10 0x00400000
+#define RATR_MCS11 0x00800000
+#define RATR_MCS12 0x01000000
+#define RATR_MCS13 0x02000000
+#define RATR_MCS14 0x04000000
+#define RATR_MCS15 0x08000000
+#define RATE_ALL_CCK (RATR_1M | RATR_2M | RATR_55M | RATR_11M)
+#define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | RATR_12M | RATR_18M | \
+ RATR_24M | RATR_36M | RATR_48M | RATR_54M)
+#define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | RATR_MCS2 | \
+ RATR_MCS3 | RATR_MCS4 | RATR_MCS5 | \
+ RATR_MCS6 | RATR_MCS7)
+#define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | RATR_MCS10 | \
+ RATR_MCS11 | RATR_MCS12 | RATR_MCS13 | \
+ RATR_MCS14|RATR_MCS15)
+
+
+ DRIVER_RSSI = 0x32c,
+ MCS_TXAGC = 0x340,
+ CCK_TXAGC = 0x348,
+ MacBlkCtrl = 0x403,
+
+}
+;
+
+#define GPI 0x108
+#define GPO 0x109
+#define GPE 0x10a
+
+#define HWSET_MAX_SIZE_92S 128
+
+#define ANAPAR_FOR_8192PciE 0x17
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c
new file mode 100644
index 000000000..6767b5965
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.c
@@ -0,0 +1,565 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+/*Created on 2008/11/18, 3: 7*/
+
+#include "r8192E_hwimg.h"
+
+u32 Rtl8192PciEPHY_REGArray[PHY_REGArrayLengthPciE] = {0x0,};
+
+u32 Rtl8192PciEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLengthPciE] = {
+ 0x800, 0x00000000,
+ 0x804, 0x00000001,
+ 0x808, 0x0000fc00,
+ 0x80c, 0x0000001c,
+ 0x810, 0x801010aa,
+ 0x814, 0x008514d0,
+ 0x818, 0x00000040,
+ 0x81c, 0x00000000,
+ 0x820, 0x00000004,
+ 0x824, 0x00690000,
+ 0x828, 0x00000004,
+ 0x82c, 0x00e90000,
+ 0x830, 0x00000004,
+ 0x834, 0x00690000,
+ 0x838, 0x00000004,
+ 0x83c, 0x00e90000,
+ 0x840, 0x00000000,
+ 0x844, 0x00000000,
+ 0x848, 0x00000000,
+ 0x84c, 0x00000000,
+ 0x850, 0x00000000,
+ 0x854, 0x00000000,
+ 0x858, 0x65a965a9,
+ 0x85c, 0x65a965a9,
+ 0x860, 0x001f0010,
+ 0x864, 0x007f0010,
+ 0x868, 0x001f0010,
+ 0x86c, 0x007f0010,
+ 0x870, 0x0f100f70,
+ 0x874, 0x0f100f70,
+ 0x878, 0x00000000,
+ 0x87c, 0x00000000,
+ 0x880, 0x6870e36c,
+ 0x884, 0xe3573600,
+ 0x888, 0x4260c340,
+ 0x88c, 0x0000ff00,
+ 0x890, 0x00000000,
+ 0x894, 0xfffffffe,
+ 0x898, 0x4c42382f,
+ 0x89c, 0x00656056,
+ 0x8b0, 0x00000000,
+ 0x8e0, 0x00000000,
+ 0x8e4, 0x00000000,
+ 0x900, 0x00000000,
+ 0x904, 0x00000023,
+ 0x908, 0x00000000,
+ 0x90c, 0x31121311,
+ 0xa00, 0x00d0c7d8,
+ 0xa04, 0x811f0008,
+ 0xa08, 0x80cd8300,
+ 0xa0c, 0x2e62740f,
+ 0xa10, 0x95009b78,
+ 0xa14, 0x11145008,
+ 0xa18, 0x00881117,
+ 0xa1c, 0x89140fa0,
+ 0xa20, 0x1a1b0000,
+ 0xa24, 0x090e1317,
+ 0xa28, 0x00000204,
+ 0xa2c, 0x00000000,
+ 0xc00, 0x00000040,
+ 0xc04, 0x00005433,
+ 0xc08, 0x000000e4,
+ 0xc0c, 0x6c6c6c6c,
+ 0xc10, 0x08800000,
+ 0xc14, 0x40000100,
+ 0xc18, 0x08000000,
+ 0xc1c, 0x40000100,
+ 0xc20, 0x08000000,
+ 0xc24, 0x40000100,
+ 0xc28, 0x08000000,
+ 0xc2c, 0x40000100,
+ 0xc30, 0x6de9ac44,
+ 0xc34, 0x465c52cd,
+ 0xc38, 0x497f5994,
+ 0xc3c, 0x0a969764,
+ 0xc40, 0x1f7c403f,
+ 0xc44, 0x000100b7,
+ 0xc48, 0xec020000,
+ 0xc4c, 0x00000300,
+ 0xc50, 0x69543420,
+ 0xc54, 0x433c0094,
+ 0xc58, 0x69543420,
+ 0xc5c, 0x433c0094,
+ 0xc60, 0x69543420,
+ 0xc64, 0x433c0094,
+ 0xc68, 0x69543420,
+ 0xc6c, 0x433c0094,
+ 0xc70, 0x2c7f000d,
+ 0xc74, 0x0186175b,
+ 0xc78, 0x0000001f,
+ 0xc7c, 0x00b91612,
+ 0xc80, 0x40000100,
+ 0xc84, 0x20000000,
+ 0xc88, 0x40000100,
+ 0xc8c, 0x20200000,
+ 0xc90, 0x40000100,
+ 0xc94, 0x00000000,
+ 0xc98, 0x40000100,
+ 0xc9c, 0x00000000,
+ 0xca0, 0x00492492,
+ 0xca4, 0x00000000,
+ 0xca8, 0x00000000,
+ 0xcac, 0x00000000,
+ 0xcb0, 0x00000000,
+ 0xcb4, 0x00000000,
+ 0xcb8, 0x00000000,
+ 0xcbc, 0x00492492,
+ 0xcc0, 0x00000000,
+ 0xcc4, 0x00000000,
+ 0xcc8, 0x00000000,
+ 0xccc, 0x00000000,
+ 0xcd0, 0x00000000,
+ 0xcd4, 0x00000000,
+ 0xcd8, 0x64b22427,
+ 0xcdc, 0x00766932,
+ 0xce0, 0x00222222,
+ 0xd00, 0x00000750,
+ 0xd04, 0x00000403,
+ 0xd08, 0x0000907f,
+ 0xd0c, 0x00000001,
+ 0xd10, 0xa0633333,
+ 0xd14, 0x33333c63,
+ 0xd18, 0x6a8f5b6b,
+ 0xd1c, 0x00000000,
+ 0xd20, 0x00000000,
+ 0xd24, 0x00000000,
+ 0xd28, 0x00000000,
+ 0xd2c, 0xcc979975,
+ 0xd30, 0x00000000,
+ 0xd34, 0x00000000,
+ 0xd38, 0x00000000,
+ 0xd3c, 0x00027293,
+ 0xd40, 0x00000000,
+ 0xd44, 0x00000000,
+ 0xd48, 0x00000000,
+ 0xd4c, 0x00000000,
+ 0xd50, 0x6437140a,
+ 0xd54, 0x024dbd02,
+ 0xd58, 0x00000000,
+ 0xd5c, 0x04032064,
+ 0xe00, 0x161a1a1a,
+ 0xe04, 0x12121416,
+ 0xe08, 0x00001800,
+ 0xe0c, 0x00000000,
+ 0xe10, 0x161a1a1a,
+ 0xe14, 0x12121416,
+ 0xe18, 0x161a1a1a,
+ 0xe1c, 0x12121416,
+};
+
+u32 Rtl8192PciERadioA_Array[RadioA_ArrayLengthPciE] = {
+ 0x019, 0x00000003,
+ 0x000, 0x000000bf,
+ 0x001, 0x00000ee0,
+ 0x002, 0x0000004c,
+ 0x003, 0x000007f1,
+ 0x004, 0x00000975,
+ 0x005, 0x00000c58,
+ 0x006, 0x00000ae6,
+ 0x007, 0x000000ca,
+ 0x008, 0x00000e1c,
+ 0x009, 0x000007f0,
+ 0x00a, 0x000009d0,
+ 0x00b, 0x000001ba,
+ 0x00c, 0x00000240,
+ 0x00e, 0x00000020,
+ 0x00f, 0x00000990,
+ 0x012, 0x00000806,
+ 0x014, 0x000005ab,
+ 0x015, 0x00000f80,
+ 0x016, 0x00000020,
+ 0x017, 0x00000597,
+ 0x018, 0x0000050a,
+ 0x01a, 0x00000f80,
+ 0x01b, 0x00000f5e,
+ 0x01c, 0x00000008,
+ 0x01d, 0x00000607,
+ 0x01e, 0x000006cc,
+ 0x01f, 0x00000000,
+ 0x020, 0x000001a5,
+ 0x01f, 0x00000001,
+ 0x020, 0x00000165,
+ 0x01f, 0x00000002,
+ 0x020, 0x000000c6,
+ 0x01f, 0x00000003,
+ 0x020, 0x00000086,
+ 0x01f, 0x00000004,
+ 0x020, 0x00000046,
+ 0x01f, 0x00000005,
+ 0x020, 0x000001e6,
+ 0x01f, 0x00000006,
+ 0x020, 0x000001a6,
+ 0x01f, 0x00000007,
+ 0x020, 0x00000166,
+ 0x01f, 0x00000008,
+ 0x020, 0x000000c7,
+ 0x01f, 0x00000009,
+ 0x020, 0x00000087,
+ 0x01f, 0x0000000a,
+ 0x020, 0x000000f7,
+ 0x01f, 0x0000000b,
+ 0x020, 0x000000d7,
+ 0x01f, 0x0000000c,
+ 0x020, 0x000000b7,
+ 0x01f, 0x0000000d,
+ 0x020, 0x00000097,
+ 0x01f, 0x0000000e,
+ 0x020, 0x00000077,
+ 0x01f, 0x0000000f,
+ 0x020, 0x00000057,
+ 0x01f, 0x00000010,
+ 0x020, 0x00000037,
+ 0x01f, 0x00000011,
+ 0x020, 0x000000fb,
+ 0x01f, 0x00000012,
+ 0x020, 0x000000db,
+ 0x01f, 0x00000013,
+ 0x020, 0x000000bb,
+ 0x01f, 0x00000014,
+ 0x020, 0x000000ff,
+ 0x01f, 0x00000015,
+ 0x020, 0x000000e3,
+ 0x01f, 0x00000016,
+ 0x020, 0x000000c3,
+ 0x01f, 0x00000017,
+ 0x020, 0x000000a3,
+ 0x01f, 0x00000018,
+ 0x020, 0x00000083,
+ 0x01f, 0x00000019,
+ 0x020, 0x00000063,
+ 0x01f, 0x0000001a,
+ 0x020, 0x00000043,
+ 0x01f, 0x0000001b,
+ 0x020, 0x00000023,
+ 0x01f, 0x0000001c,
+ 0x020, 0x00000003,
+ 0x01f, 0x0000001d,
+ 0x020, 0x000001e3,
+ 0x01f, 0x0000001e,
+ 0x020, 0x000001c3,
+ 0x01f, 0x0000001f,
+ 0x020, 0x000001a3,
+ 0x01f, 0x00000020,
+ 0x020, 0x00000183,
+ 0x01f, 0x00000021,
+ 0x020, 0x00000163,
+ 0x01f, 0x00000022,
+ 0x020, 0x00000143,
+ 0x01f, 0x00000023,
+ 0x020, 0x00000123,
+ 0x01f, 0x00000024,
+ 0x020, 0x00000103,
+ 0x023, 0x00000203,
+ 0x024, 0x00000100,
+ 0x00b, 0x000001ba,
+ 0x02c, 0x000003d7,
+ 0x02d, 0x00000ff0,
+ 0x000, 0x00000037,
+ 0x004, 0x00000160,
+ 0x007, 0x00000080,
+ 0x002, 0x0000088d,
+ 0x0fe, 0x00000000,
+ 0x0fe, 0x00000000,
+ 0x016, 0x00000200,
+ 0x016, 0x00000380,
+ 0x016, 0x00000020,
+ 0x016, 0x000001a0,
+ 0x000, 0x000000bf,
+ 0x00d, 0x0000001f,
+ 0x00d, 0x00000c9f,
+ 0x002, 0x0000004d,
+ 0x000, 0x00000cbf,
+ 0x004, 0x00000975,
+ 0x007, 0x00000700,
+};
+
+u32 Rtl8192PciERadioB_Array[RadioB_ArrayLengthPciE] = {
+ 0x019, 0x00000003,
+ 0x000, 0x000000bf,
+ 0x001, 0x000006e0,
+ 0x002, 0x0000004c,
+ 0x003, 0x000007f1,
+ 0x004, 0x00000975,
+ 0x005, 0x00000c58,
+ 0x006, 0x00000ae6,
+ 0x007, 0x000000ca,
+ 0x008, 0x00000e1c,
+ 0x000, 0x000000b7,
+ 0x00a, 0x00000850,
+ 0x000, 0x000000bf,
+ 0x00b, 0x000001ba,
+ 0x00c, 0x00000240,
+ 0x00e, 0x00000020,
+ 0x015, 0x00000f80,
+ 0x016, 0x00000020,
+ 0x017, 0x00000597,
+ 0x018, 0x0000050a,
+ 0x01a, 0x00000e00,
+ 0x01b, 0x00000f5e,
+ 0x01d, 0x00000607,
+ 0x01e, 0x000006cc,
+ 0x00b, 0x000001ba,
+ 0x023, 0x00000203,
+ 0x024, 0x00000100,
+ 0x000, 0x00000037,
+ 0x004, 0x00000160,
+ 0x016, 0x00000200,
+ 0x016, 0x00000380,
+ 0x016, 0x00000020,
+ 0x016, 0x000001a0,
+ 0x00d, 0x00000ccc,
+ 0x000, 0x000000bf,
+ 0x002, 0x0000004d,
+ 0x000, 0x00000cbf,
+ 0x004, 0x00000975,
+ 0x007, 0x00000700,
+};
+
+u32 Rtl8192PciERadioC_Array[RadioC_ArrayLengthPciE] = {
+ 0x0, };
+
+u32 Rtl8192PciERadioD_Array[RadioD_ArrayLengthPciE] = {
+ 0x0, };
+
+u32 Rtl8192PciEMACPHY_Array[] = {
+ 0x03c, 0xffff0000, 0x00000f0f,
+ 0x340, 0xffffffff, 0x161a1a1a,
+ 0x344, 0xffffffff, 0x12121416,
+ 0x348, 0x0000ffff, 0x00001818,
+ 0x12c, 0xffffffff, 0x04000802,
+ 0x318, 0x00000fff, 0x00000100,
+};
+
+u32 Rtl8192PciEMACPHY_Array_PG[] = {
+ 0x03c, 0xffff0000, 0x00000f0f,
+ 0xe00, 0xffffffff, 0x06090909,
+ 0xe04, 0xffffffff, 0x00030306,
+ 0xe08, 0x0000ff00, 0x00000000,
+ 0xe10, 0xffffffff, 0x0a0c0d0f,
+ 0xe14, 0xffffffff, 0x06070809,
+ 0xe18, 0xffffffff, 0x0a0c0d0f,
+ 0xe1c, 0xffffffff, 0x06070809,
+ 0x12c, 0xffffffff, 0x04000802,
+ 0x318, 0x00000fff, 0x00000800,
+};
+
+u32 Rtl8192PciEAGCTAB_Array[AGCTAB_ArrayLengthPciE] = {
+ 0xc78, 0x7d000001,
+ 0xc78, 0x7d010001,
+ 0xc78, 0x7d020001,
+ 0xc78, 0x7d030001,
+ 0xc78, 0x7d040001,
+ 0xc78, 0x7d050001,
+ 0xc78, 0x7c060001,
+ 0xc78, 0x7b070001,
+ 0xc78, 0x7a080001,
+ 0xc78, 0x79090001,
+ 0xc78, 0x780a0001,
+ 0xc78, 0x770b0001,
+ 0xc78, 0x760c0001,
+ 0xc78, 0x750d0001,
+ 0xc78, 0x740e0001,
+ 0xc78, 0x730f0001,
+ 0xc78, 0x72100001,
+ 0xc78, 0x71110001,
+ 0xc78, 0x70120001,
+ 0xc78, 0x6f130001,
+ 0xc78, 0x6e140001,
+ 0xc78, 0x6d150001,
+ 0xc78, 0x6c160001,
+ 0xc78, 0x6b170001,
+ 0xc78, 0x6a180001,
+ 0xc78, 0x69190001,
+ 0xc78, 0x681a0001,
+ 0xc78, 0x671b0001,
+ 0xc78, 0x661c0001,
+ 0xc78, 0x651d0001,
+ 0xc78, 0x641e0001,
+ 0xc78, 0x491f0001,
+ 0xc78, 0x48200001,
+ 0xc78, 0x47210001,
+ 0xc78, 0x46220001,
+ 0xc78, 0x45230001,
+ 0xc78, 0x44240001,
+ 0xc78, 0x43250001,
+ 0xc78, 0x28260001,
+ 0xc78, 0x27270001,
+ 0xc78, 0x26280001,
+ 0xc78, 0x25290001,
+ 0xc78, 0x242a0001,
+ 0xc78, 0x232b0001,
+ 0xc78, 0x222c0001,
+ 0xc78, 0x212d0001,
+ 0xc78, 0x202e0001,
+ 0xc78, 0x0a2f0001,
+ 0xc78, 0x08300001,
+ 0xc78, 0x06310001,
+ 0xc78, 0x05320001,
+ 0xc78, 0x04330001,
+ 0xc78, 0x03340001,
+ 0xc78, 0x02350001,
+ 0xc78, 0x01360001,
+ 0xc78, 0x00370001,
+ 0xc78, 0x00380001,
+ 0xc78, 0x00390001,
+ 0xc78, 0x003a0001,
+ 0xc78, 0x003b0001,
+ 0xc78, 0x003c0001,
+ 0xc78, 0x003d0001,
+ 0xc78, 0x003e0001,
+ 0xc78, 0x003f0001,
+ 0xc78, 0x7d400001,
+ 0xc78, 0x7d410001,
+ 0xc78, 0x7d420001,
+ 0xc78, 0x7d430001,
+ 0xc78, 0x7d440001,
+ 0xc78, 0x7d450001,
+ 0xc78, 0x7c460001,
+ 0xc78, 0x7b470001,
+ 0xc78, 0x7a480001,
+ 0xc78, 0x79490001,
+ 0xc78, 0x784a0001,
+ 0xc78, 0x774b0001,
+ 0xc78, 0x764c0001,
+ 0xc78, 0x754d0001,
+ 0xc78, 0x744e0001,
+ 0xc78, 0x734f0001,
+ 0xc78, 0x72500001,
+ 0xc78, 0x71510001,
+ 0xc78, 0x70520001,
+ 0xc78, 0x6f530001,
+ 0xc78, 0x6e540001,
+ 0xc78, 0x6d550001,
+ 0xc78, 0x6c560001,
+ 0xc78, 0x6b570001,
+ 0xc78, 0x6a580001,
+ 0xc78, 0x69590001,
+ 0xc78, 0x685a0001,
+ 0xc78, 0x675b0001,
+ 0xc78, 0x665c0001,
+ 0xc78, 0x655d0001,
+ 0xc78, 0x645e0001,
+ 0xc78, 0x495f0001,
+ 0xc78, 0x48600001,
+ 0xc78, 0x47610001,
+ 0xc78, 0x46620001,
+ 0xc78, 0x45630001,
+ 0xc78, 0x44640001,
+ 0xc78, 0x43650001,
+ 0xc78, 0x28660001,
+ 0xc78, 0x27670001,
+ 0xc78, 0x26680001,
+ 0xc78, 0x25690001,
+ 0xc78, 0x246a0001,
+ 0xc78, 0x236b0001,
+ 0xc78, 0x226c0001,
+ 0xc78, 0x216d0001,
+ 0xc78, 0x206e0001,
+ 0xc78, 0x0a6f0001,
+ 0xc78, 0x08700001,
+ 0xc78, 0x06710001,
+ 0xc78, 0x05720001,
+ 0xc78, 0x04730001,
+ 0xc78, 0x03740001,
+ 0xc78, 0x02750001,
+ 0xc78, 0x01760001,
+ 0xc78, 0x00770001,
+ 0xc78, 0x00780001,
+ 0xc78, 0x00790001,
+ 0xc78, 0x007a0001,
+ 0xc78, 0x007b0001,
+ 0xc78, 0x007c0001,
+ 0xc78, 0x007d0001,
+ 0xc78, 0x007e0001,
+ 0xc78, 0x007f0001,
+ 0xc78, 0x2e00001e,
+ 0xc78, 0x2e01001e,
+ 0xc78, 0x2e02001e,
+ 0xc78, 0x2e03001e,
+ 0xc78, 0x2e04001e,
+ 0xc78, 0x2e05001e,
+ 0xc78, 0x3006001e,
+ 0xc78, 0x3407001e,
+ 0xc78, 0x3908001e,
+ 0xc78, 0x3c09001e,
+ 0xc78, 0x3f0a001e,
+ 0xc78, 0x420b001e,
+ 0xc78, 0x440c001e,
+ 0xc78, 0x450d001e,
+ 0xc78, 0x460e001e,
+ 0xc78, 0x460f001e,
+ 0xc78, 0x4710001e,
+ 0xc78, 0x4811001e,
+ 0xc78, 0x4912001e,
+ 0xc78, 0x4a13001e,
+ 0xc78, 0x4b14001e,
+ 0xc78, 0x4b15001e,
+ 0xc78, 0x4c16001e,
+ 0xc78, 0x4d17001e,
+ 0xc78, 0x4e18001e,
+ 0xc78, 0x4f19001e,
+ 0xc78, 0x4f1a001e,
+ 0xc78, 0x501b001e,
+ 0xc78, 0x511c001e,
+ 0xc78, 0x521d001e,
+ 0xc78, 0x521e001e,
+ 0xc78, 0x531f001e,
+ 0xc78, 0x5320001e,
+ 0xc78, 0x5421001e,
+ 0xc78, 0x5522001e,
+ 0xc78, 0x5523001e,
+ 0xc78, 0x5624001e,
+ 0xc78, 0x5725001e,
+ 0xc78, 0x5726001e,
+ 0xc78, 0x5827001e,
+ 0xc78, 0x5828001e,
+ 0xc78, 0x5929001e,
+ 0xc78, 0x592a001e,
+ 0xc78, 0x5a2b001e,
+ 0xc78, 0x5b2c001e,
+ 0xc78, 0x5c2d001e,
+ 0xc78, 0x5c2e001e,
+ 0xc78, 0x5d2f001e,
+ 0xc78, 0x5e30001e,
+ 0xc78, 0x5f31001e,
+ 0xc78, 0x6032001e,
+ 0xc78, 0x6033001e,
+ 0xc78, 0x6134001e,
+ 0xc78, 0x6235001e,
+ 0xc78, 0x6336001e,
+ 0xc78, 0x6437001e,
+ 0xc78, 0x6438001e,
+ 0xc78, 0x6539001e,
+ 0xc78, 0x663a001e,
+ 0xc78, 0x673b001e,
+ 0xc78, 0x673c001e,
+ 0xc78, 0x683d001e,
+ 0xc78, 0x693e001e,
+ 0xc78, 0x6a3f001e,
+};
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.h
new file mode 100644
index 000000000..d804876dd
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hwimg.h
@@ -0,0 +1,51 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_HAL8192PciE_FW_IMG_H
+#define __INC_HAL8192PciE_FW_IMG_H
+
+/*Created on 2008/11/18, 3: 7*/
+
+#include <linux/types.h>
+
+#define BootArrayLengthPciE 344
+extern u8 Rtl8192PciEFwBootArray[BootArrayLengthPciE];
+#define MainArrayLengthPciE 43012
+extern u8 Rtl8192PciEFwMainArray[MainArrayLengthPciE];
+#define DataArrayLengthPciE 848
+extern u8 Rtl8192PciEFwDataArray[DataArrayLengthPciE];
+#define PHY_REGArrayLengthPciE 1
+extern u32 Rtl8192PciEPHY_REGArray[PHY_REGArrayLengthPciE];
+#define PHY_REG_1T2RArrayLengthPciE 296
+extern u32 Rtl8192PciEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLengthPciE];
+#define RadioA_ArrayLengthPciE 246
+extern u32 Rtl8192PciERadioA_Array[RadioA_ArrayLengthPciE];
+#define RadioB_ArrayLengthPciE 78
+extern u32 Rtl8192PciERadioB_Array[RadioB_ArrayLengthPciE];
+#define RadioC_ArrayLengthPciE 2
+extern u32 Rtl8192PciERadioC_Array[RadioC_ArrayLengthPciE];
+#define RadioD_ArrayLengthPciE 2
+extern u32 Rtl8192PciERadioD_Array[RadioD_ArrayLengthPciE];
+#define MACPHY_ArrayLengthPciE 18
+extern u32 Rtl8192PciEMACPHY_Array[MACPHY_ArrayLengthPciE];
+#define MACPHY_Array_PGLengthPciE 30
+extern u32 Rtl8192PciEMACPHY_Array_PG[MACPHY_Array_PGLengthPciE];
+#define AGCTAB_ArrayLengthPciE 384
+extern u32 Rtl8192PciEAGCTAB_Array[AGCTAB_ArrayLengthPciE];
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
new file mode 100644
index 000000000..4664a4fd1
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
@@ -0,0 +1,1636 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#include "rtl_core.h"
+#include "r8192E_hw.h"
+#include "r8192E_phyreg.h"
+#include "r8190P_rtl8256.h"
+#include "r8192E_phy.h"
+#include "rtl_dm.h"
+
+#include "r8192E_hwimg.h"
+
+static u32 RF_CHANNEL_TABLE_ZEBRA[] = {
+ 0,
+ 0x085c,
+ 0x08dc,
+ 0x095c,
+ 0x09dc,
+ 0x0a5c,
+ 0x0adc,
+ 0x0b5c,
+ 0x0bdc,
+ 0x0c5c,
+ 0x0cdc,
+ 0x0d5c,
+ 0x0ddc,
+ 0x0e5c,
+ 0x0f72,
+};
+
+/*************************Define local function prototype**********************/
+
+static u32 phy_FwRFSerialRead(struct net_device *dev,
+ enum rf90_radio_path eRFPath,
+ u32 Offset);
+static void phy_FwRFSerialWrite(struct net_device *dev,
+ enum rf90_radio_path eRFPath,
+ u32 Offset, u32 Data);
+
+static u32 rtl8192_CalculateBitShift(u32 dwBitMask)
+{
+ u32 i;
+
+ for (i = 0; i <= 31; i++) {
+ if (((dwBitMask >> i) & 0x1) == 1)
+ break;
+ }
+ return i;
+}
+
+u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath)
+{
+ u8 ret = 1;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->rf_type == RF_2T4R)
+ ret = 0;
+ else if (priv->rf_type == RF_1T2R) {
+ if (eRFPath == RF90_PATH_A || eRFPath == RF90_PATH_B)
+ ret = 1;
+ else if (eRFPath == RF90_PATH_C || eRFPath == RF90_PATH_D)
+ ret = 0;
+ }
+ return ret;
+}
+
+void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask,
+ u32 dwData)
+{
+
+ u32 OriginalValue, BitShift, NewValue;
+
+ if (dwBitMask != bMaskDWord) {
+ OriginalValue = read_nic_dword(dev, dwRegAddr);
+ BitShift = rtl8192_CalculateBitShift(dwBitMask);
+ NewValue = (((OriginalValue) & (~dwBitMask)) |
+ (dwData << BitShift));
+ write_nic_dword(dev, dwRegAddr, NewValue);
+ } else
+ write_nic_dword(dev, dwRegAddr, dwData);
+}
+
+u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask)
+{
+ u32 Ret = 0, OriginalValue, BitShift;
+
+ OriginalValue = read_nic_dword(dev, dwRegAddr);
+ BitShift = rtl8192_CalculateBitShift(dwBitMask);
+ Ret = (OriginalValue & dwBitMask) >> BitShift;
+
+ return Ret;
+}
+static u32 rtl8192_phy_RFSerialRead(struct net_device *dev,
+ enum rf90_radio_path eRFPath, u32 Offset)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 ret = 0;
+ u32 NewOffset = 0;
+ struct bb_reg_definition *pPhyReg = &priv->PHYRegDef[eRFPath];
+
+ Offset &= 0x3f;
+
+ if (priv->rf_chip == RF_8256) {
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
+ if (Offset >= 31) {
+ priv->RfReg0Value[eRFPath] |= 0x140;
+ rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
+ bMaskDWord,
+ (priv->RfReg0Value[eRFPath]<<16));
+ NewOffset = Offset - 30;
+ } else if (Offset >= 16) {
+ priv->RfReg0Value[eRFPath] |= 0x100;
+ priv->RfReg0Value[eRFPath] &= (~0x40);
+ rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
+ bMaskDWord,
+ (priv->RfReg0Value[eRFPath]<<16));
+
+ NewOffset = Offset - 15;
+ } else
+ NewOffset = Offset;
+ } else {
+ RT_TRACE((COMP_PHY|COMP_ERR),
+ "check RF type here, need to be 8256\n");
+ NewOffset = Offset;
+ }
+ rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress,
+ NewOffset);
+ rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x0);
+ rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x1);
+
+ mdelay(1);
+
+ ret = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack,
+ bLSSIReadBackData);
+
+ if (priv->rf_chip == RF_8256) {
+ priv->RfReg0Value[eRFPath] &= 0xebf;
+
+ rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord,
+ (priv->RfReg0Value[eRFPath] << 16));
+
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
+ }
+
+
+ return ret;
+
+}
+
+static void rtl8192_phy_RFSerialWrite(struct net_device *dev,
+ enum rf90_radio_path eRFPath, u32 Offset,
+ u32 Data)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 DataAndAddr = 0, NewOffset = 0;
+ struct bb_reg_definition *pPhyReg = &priv->PHYRegDef[eRFPath];
+
+ Offset &= 0x3f;
+ if (priv->rf_chip == RF_8256) {
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
+
+ if (Offset >= 31) {
+ priv->RfReg0Value[eRFPath] |= 0x140;
+ rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
+ bMaskDWord,
+ (priv->RfReg0Value[eRFPath] << 16));
+ NewOffset = Offset - 30;
+ } else if (Offset >= 16) {
+ priv->RfReg0Value[eRFPath] |= 0x100;
+ priv->RfReg0Value[eRFPath] &= (~0x40);
+ rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
+ bMaskDWord,
+ (priv->RfReg0Value[eRFPath] << 16));
+ NewOffset = Offset - 15;
+ } else
+ NewOffset = Offset;
+ } else {
+ RT_TRACE((COMP_PHY|COMP_ERR),
+ "check RF type here, need to be 8256\n");
+ NewOffset = Offset;
+ }
+
+ DataAndAddr = (Data<<16) | (NewOffset&0x3f);
+
+ rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
+
+ if (Offset == 0x0)
+ priv->RfReg0Value[eRFPath] = Data;
+
+ if (priv->rf_chip == RF_8256) {
+ if (Offset != 0) {
+ priv->RfReg0Value[eRFPath] &= 0xebf;
+ rtl8192_setBBreg(
+ dev,
+ pPhyReg->rf3wireOffset,
+ bMaskDWord,
+ (priv->RfReg0Value[eRFPath] << 16));
+ }
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
+ }
+}
+
+void rtl8192_phy_SetRFReg(struct net_device *dev, enum rf90_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask, u32 Data)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 Original_Value, BitShift, New_Value;
+
+ if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+ return;
+ if (priv->rtllib->eRFPowerState != eRfOn && !priv->being_init_adapter)
+ return;
+
+ RT_TRACE(COMP_PHY, "FW RF CTRL is not ready now\n");
+ if (priv->Rf_Mode == RF_OP_By_FW) {
+ if (BitMask != bMask12Bits) {
+ Original_Value = phy_FwRFSerialRead(dev, eRFPath,
+ RegAddr);
+ BitShift = rtl8192_CalculateBitShift(BitMask);
+ New_Value = (((Original_Value) & (~BitMask)) |
+ (Data << BitShift));
+
+ phy_FwRFSerialWrite(dev, eRFPath, RegAddr, New_Value);
+ } else
+ phy_FwRFSerialWrite(dev, eRFPath, RegAddr, Data);
+ udelay(200);
+
+ } else {
+ if (BitMask != bMask12Bits) {
+ Original_Value = rtl8192_phy_RFSerialRead(dev, eRFPath,
+ RegAddr);
+ BitShift = rtl8192_CalculateBitShift(BitMask);
+ New_Value = (((Original_Value) & (~BitMask)) |
+ (Data << BitShift));
+
+ rtl8192_phy_RFSerialWrite(dev, eRFPath, RegAddr,
+ New_Value);
+ } else
+ rtl8192_phy_RFSerialWrite(dev, eRFPath, RegAddr, Data);
+ }
+}
+
+u32 rtl8192_phy_QueryRFReg(struct net_device *dev, enum rf90_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask)
+{
+ u32 Original_Value, Readback_Value, BitShift;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+ return 0;
+ if (priv->rtllib->eRFPowerState != eRfOn && !priv->being_init_adapter)
+ return 0;
+ down(&priv->rf_sem);
+ if (priv->Rf_Mode == RF_OP_By_FW) {
+ Original_Value = phy_FwRFSerialRead(dev, eRFPath, RegAddr);
+ udelay(200);
+ } else {
+ Original_Value = rtl8192_phy_RFSerialRead(dev, eRFPath,
+ RegAddr);
+ }
+ BitShift = rtl8192_CalculateBitShift(BitMask);
+ Readback_Value = (Original_Value & BitMask) >> BitShift;
+ up(&priv->rf_sem);
+ return Readback_Value;
+}
+
+static u32 phy_FwRFSerialRead(struct net_device *dev,
+ enum rf90_radio_path eRFPath, u32 Offset)
+{
+ u32 Data = 0;
+ u8 time = 0;
+
+ Data |= ((Offset & 0xFF) << 12);
+ Data |= ((eRFPath & 0x3) << 20);
+ Data |= 0x80000000;
+ while (read_nic_dword(dev, QPNR)&0x80000000) {
+ if (time++ < 100)
+ udelay(10);
+ else
+ break;
+ }
+ write_nic_dword(dev, QPNR, Data);
+ while (read_nic_dword(dev, QPNR) & 0x80000000) {
+ if (time++ < 100)
+ udelay(10);
+ else
+ return 0;
+ }
+ return read_nic_dword(dev, RF_DATA);
+
+}
+
+static void phy_FwRFSerialWrite(struct net_device *dev,
+ enum rf90_radio_path eRFPath,
+ u32 Offset, u32 Data)
+{
+ u8 time = 0;
+
+ Data |= ((Offset & 0xFF) << 12);
+ Data |= ((eRFPath & 0x3) << 20);
+ Data |= 0x400000;
+ Data |= 0x80000000;
+
+ while (read_nic_dword(dev, QPNR) & 0x80000000) {
+ if (time++ < 100)
+ udelay(10);
+ else
+ break;
+ }
+ write_nic_dword(dev, QPNR, Data);
+
+}
+
+
+void rtl8192_phy_configmac(struct net_device *dev)
+{
+ u32 dwArrayLen = 0, i = 0;
+ u32 *pdwArray = NULL;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->bTXPowerDataReadFromEEPORM) {
+ RT_TRACE(COMP_PHY, "Rtl819XMACPHY_Array_PG\n");
+ dwArrayLen = MACPHY_Array_PGLength;
+ pdwArray = Rtl819XMACPHY_Array_PG;
+
+ } else {
+ RT_TRACE(COMP_PHY, "Read rtl819XMACPHY_Array\n");
+ dwArrayLen = MACPHY_ArrayLength;
+ pdwArray = Rtl819XMACPHY_Array;
+ }
+ for (i = 0; i < dwArrayLen; i += 3) {
+ RT_TRACE(COMP_DBG,
+ "The Rtl8190MACPHY_Array[0] is %x Rtl8190MACPHY_Array[1] is %x Rtl8190MACPHY_Array[2] is %x\n",
+ pdwArray[i], pdwArray[i+1], pdwArray[i+2]);
+ if (pdwArray[i] == 0x318)
+ pdwArray[i+2] = 0x00000800;
+ rtl8192_setBBreg(dev, pdwArray[i], pdwArray[i+1],
+ pdwArray[i+2]);
+ }
+ return;
+
+}
+
+void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType)
+{
+ int i;
+ u32 *Rtl819XPHY_REGArray_Table = NULL;
+ u32 *Rtl819XAGCTAB_Array_Table = NULL;
+ u16 AGCTAB_ArrayLen, PHY_REGArrayLen = 0;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ AGCTAB_ArrayLen = AGCTAB_ArrayLength;
+ Rtl819XAGCTAB_Array_Table = Rtl819XAGCTAB_Array;
+ if (priv->rf_type == RF_2T4R) {
+ PHY_REGArrayLen = PHY_REGArrayLength;
+ Rtl819XPHY_REGArray_Table = Rtl819XPHY_REGArray;
+ } else if (priv->rf_type == RF_1T2R) {
+ PHY_REGArrayLen = PHY_REG_1T2RArrayLength;
+ Rtl819XPHY_REGArray_Table = Rtl819XPHY_REG_1T2RArray;
+ }
+
+ if (ConfigType == BaseBand_Config_PHY_REG) {
+ for (i = 0; i < PHY_REGArrayLen; i += 2) {
+ rtl8192_setBBreg(dev, Rtl819XPHY_REGArray_Table[i],
+ bMaskDWord,
+ Rtl819XPHY_REGArray_Table[i+1]);
+ RT_TRACE(COMP_DBG,
+ "i: %x, The Rtl819xUsbPHY_REGArray[0] is %x Rtl819xUsbPHY_REGArray[1] is %x\n",
+ i, Rtl819XPHY_REGArray_Table[i],
+ Rtl819XPHY_REGArray_Table[i+1]);
+ }
+ } else if (ConfigType == BaseBand_Config_AGC_TAB) {
+ for (i = 0; i < AGCTAB_ArrayLen; i += 2) {
+ rtl8192_setBBreg(dev, Rtl819XAGCTAB_Array_Table[i],
+ bMaskDWord,
+ Rtl819XAGCTAB_Array_Table[i+1]);
+ RT_TRACE(COMP_DBG,
+ "i:%x, The rtl819XAGCTAB_Array[0] is %x rtl819XAGCTAB_Array[1] is %x\n",
+ i, Rtl819XAGCTAB_Array_Table[i],
+ Rtl819XAGCTAB_Array_Table[i+1]);
+ }
+ }
+}
+
+static void rtl8192_InitBBRFRegDef(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->PHYRegDef[RF90_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW;
+ priv->PHYRegDef[RF90_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW;
+ priv->PHYRegDef[RF90_PATH_C].rfintfs = rFPGA0_XCD_RFInterfaceSW;
+ priv->PHYRegDef[RF90_PATH_D].rfintfs = rFPGA0_XCD_RFInterfaceSW;
+
+ priv->PHYRegDef[RF90_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB;
+ priv->PHYRegDef[RF90_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB;
+ priv->PHYRegDef[RF90_PATH_C].rfintfi = rFPGA0_XCD_RFInterfaceRB;
+ priv->PHYRegDef[RF90_PATH_D].rfintfi = rFPGA0_XCD_RFInterfaceRB;
+
+ priv->PHYRegDef[RF90_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE;
+ priv->PHYRegDef[RF90_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE;
+ priv->PHYRegDef[RF90_PATH_C].rfintfo = rFPGA0_XC_RFInterfaceOE;
+ priv->PHYRegDef[RF90_PATH_D].rfintfo = rFPGA0_XD_RFInterfaceOE;
+
+ priv->PHYRegDef[RF90_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE;
+ priv->PHYRegDef[RF90_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE;
+ priv->PHYRegDef[RF90_PATH_C].rfintfe = rFPGA0_XC_RFInterfaceOE;
+ priv->PHYRegDef[RF90_PATH_D].rfintfe = rFPGA0_XD_RFInterfaceOE;
+
+ priv->PHYRegDef[RF90_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter;
+ priv->PHYRegDef[RF90_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
+ priv->PHYRegDef[RF90_PATH_C].rf3wireOffset = rFPGA0_XC_LSSIParameter;
+ priv->PHYRegDef[RF90_PATH_D].rf3wireOffset = rFPGA0_XD_LSSIParameter;
+
+ priv->PHYRegDef[RF90_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter;
+ priv->PHYRegDef[RF90_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter;
+ priv->PHYRegDef[RF90_PATH_C].rfLSSI_Select = rFPGA0_XCD_RFParameter;
+ priv->PHYRegDef[RF90_PATH_D].rfLSSI_Select = rFPGA0_XCD_RFParameter;
+
+ priv->PHYRegDef[RF90_PATH_A].rfTxGainStage = rFPGA0_TxGainStage;
+ priv->PHYRegDef[RF90_PATH_B].rfTxGainStage = rFPGA0_TxGainStage;
+ priv->PHYRegDef[RF90_PATH_C].rfTxGainStage = rFPGA0_TxGainStage;
+ priv->PHYRegDef[RF90_PATH_D].rfTxGainStage = rFPGA0_TxGainStage;
+
+ priv->PHYRegDef[RF90_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1;
+ priv->PHYRegDef[RF90_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1;
+ priv->PHYRegDef[RF90_PATH_C].rfHSSIPara1 = rFPGA0_XC_HSSIParameter1;
+ priv->PHYRegDef[RF90_PATH_D].rfHSSIPara1 = rFPGA0_XD_HSSIParameter1;
+
+ priv->PHYRegDef[RF90_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2;
+ priv->PHYRegDef[RF90_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2;
+ priv->PHYRegDef[RF90_PATH_C].rfHSSIPara2 = rFPGA0_XC_HSSIParameter2;
+ priv->PHYRegDef[RF90_PATH_D].rfHSSIPara2 = rFPGA0_XD_HSSIParameter2;
+
+ priv->PHYRegDef[RF90_PATH_A].rfSwitchControl = rFPGA0_XAB_SwitchControl;
+ priv->PHYRegDef[RF90_PATH_B].rfSwitchControl = rFPGA0_XAB_SwitchControl;
+ priv->PHYRegDef[RF90_PATH_C].rfSwitchControl = rFPGA0_XCD_SwitchControl;
+ priv->PHYRegDef[RF90_PATH_D].rfSwitchControl = rFPGA0_XCD_SwitchControl;
+
+ priv->PHYRegDef[RF90_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1;
+ priv->PHYRegDef[RF90_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1;
+ priv->PHYRegDef[RF90_PATH_C].rfAGCControl1 = rOFDM0_XCAGCCore1;
+ priv->PHYRegDef[RF90_PATH_D].rfAGCControl1 = rOFDM0_XDAGCCore1;
+
+ priv->PHYRegDef[RF90_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2;
+ priv->PHYRegDef[RF90_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2;
+ priv->PHYRegDef[RF90_PATH_C].rfAGCControl2 = rOFDM0_XCAGCCore2;
+ priv->PHYRegDef[RF90_PATH_D].rfAGCControl2 = rOFDM0_XDAGCCore2;
+
+ priv->PHYRegDef[RF90_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance;
+ priv->PHYRegDef[RF90_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance;
+ priv->PHYRegDef[RF90_PATH_C].rfRxIQImbalance = rOFDM0_XCRxIQImbalance;
+ priv->PHYRegDef[RF90_PATH_D].rfRxIQImbalance = rOFDM0_XDRxIQImbalance;
+
+ priv->PHYRegDef[RF90_PATH_A].rfRxAFE = rOFDM0_XARxAFE;
+ priv->PHYRegDef[RF90_PATH_B].rfRxAFE = rOFDM0_XBRxAFE;
+ priv->PHYRegDef[RF90_PATH_C].rfRxAFE = rOFDM0_XCRxAFE;
+ priv->PHYRegDef[RF90_PATH_D].rfRxAFE = rOFDM0_XDRxAFE;
+
+ priv->PHYRegDef[RF90_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance;
+ priv->PHYRegDef[RF90_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance;
+ priv->PHYRegDef[RF90_PATH_C].rfTxIQImbalance = rOFDM0_XCTxIQImbalance;
+ priv->PHYRegDef[RF90_PATH_D].rfTxIQImbalance = rOFDM0_XDTxIQImbalance;
+
+ priv->PHYRegDef[RF90_PATH_A].rfTxAFE = rOFDM0_XATxAFE;
+ priv->PHYRegDef[RF90_PATH_B].rfTxAFE = rOFDM0_XBTxAFE;
+ priv->PHYRegDef[RF90_PATH_C].rfTxAFE = rOFDM0_XCTxAFE;
+ priv->PHYRegDef[RF90_PATH_D].rfTxAFE = rOFDM0_XDTxAFE;
+
+ priv->PHYRegDef[RF90_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
+ priv->PHYRegDef[RF90_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
+ priv->PHYRegDef[RF90_PATH_C].rfLSSIReadBack = rFPGA0_XC_LSSIReadBack;
+ priv->PHYRegDef[RF90_PATH_D].rfLSSIReadBack = rFPGA0_XD_LSSIReadBack;
+
+}
+
+bool rtl8192_phy_checkBBAndRF(struct net_device *dev,
+ enum hw90_block CheckBlock,
+ enum rf90_radio_path eRFPath)
+{
+ bool ret = true;
+ u32 i, CheckTimes = 4, dwRegRead = 0;
+ u32 WriteAddr[4];
+ u32 WriteData[] = {0xfffff027, 0xaa55a02f, 0x00000027, 0x55aa502f};
+
+ WriteAddr[HW90_BLOCK_MAC] = 0x100;
+ WriteAddr[HW90_BLOCK_PHY0] = 0x900;
+ WriteAddr[HW90_BLOCK_PHY1] = 0x800;
+ WriteAddr[HW90_BLOCK_RF] = 0x3;
+ RT_TRACE(COMP_PHY, "=======>%s(), CheckBlock:%d\n", __func__,
+ CheckBlock);
+ for (i = 0; i < CheckTimes; i++) {
+ switch (CheckBlock) {
+ case HW90_BLOCK_MAC:
+ RT_TRACE(COMP_ERR,
+ "PHY_CheckBBRFOK(): Never Write 0x100 here!");
+ break;
+
+ case HW90_BLOCK_PHY0:
+ case HW90_BLOCK_PHY1:
+ write_nic_dword(dev, WriteAddr[CheckBlock],
+ WriteData[i]);
+ dwRegRead = read_nic_dword(dev, WriteAddr[CheckBlock]);
+ break;
+
+ case HW90_BLOCK_RF:
+ WriteData[i] &= 0xfff;
+ rtl8192_phy_SetRFReg(dev, eRFPath,
+ WriteAddr[HW90_BLOCK_RF],
+ bMask12Bits, WriteData[i]);
+ mdelay(10);
+ dwRegRead = rtl8192_phy_QueryRFReg(dev, eRFPath,
+ WriteAddr[HW90_BLOCK_RF],
+ bMaskDWord);
+ mdelay(10);
+ break;
+
+ default:
+ ret = false;
+ break;
+ }
+
+
+ if (dwRegRead != WriteData[i]) {
+ RT_TRACE(COMP_ERR,
+ "====>error=====dwRegRead: %x, WriteData: %x\n",
+ dwRegRead, WriteData[i]);
+ ret = false;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static bool rtl8192_BB_Config_ParaFile(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ bool rtStatus = true;
+ u8 bRegValue = 0, eCheckItem = 0;
+ u32 dwRegValue = 0;
+
+ bRegValue = read_nic_byte(dev, BB_GLOBAL_RESET);
+ write_nic_byte(dev, BB_GLOBAL_RESET, (bRegValue|BB_GLOBAL_RESET_BIT));
+
+ dwRegValue = read_nic_dword(dev, CPU_GEN);
+ write_nic_dword(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST)));
+
+ for (eCheckItem = (enum hw90_block)HW90_BLOCK_PHY0;
+ eCheckItem <= HW90_BLOCK_PHY1; eCheckItem++) {
+ rtStatus = rtl8192_phy_checkBBAndRF(dev,
+ (enum hw90_block)eCheckItem,
+ (enum rf90_radio_path)0);
+ if (!rtStatus) {
+ RT_TRACE((COMP_ERR | COMP_PHY),
+ "PHY_RF8256_Config():Check PHY%d Fail!!\n",
+ eCheckItem-1);
+ return rtStatus;
+ }
+ }
+ rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0);
+ rtl8192_phyConfigBB(dev, BaseBand_Config_PHY_REG);
+
+ dwRegValue = read_nic_dword(dev, CPU_GEN);
+ write_nic_dword(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST));
+
+ rtl8192_phyConfigBB(dev, BaseBand_Config_AGC_TAB);
+
+ if (priv->IC_Cut > VERSION_8190_BD) {
+ if (priv->rf_type == RF_2T4R)
+ dwRegValue = (priv->AntennaTxPwDiff[2]<<8 |
+ priv->AntennaTxPwDiff[1]<<4 |
+ priv->AntennaTxPwDiff[0]);
+ else
+ dwRegValue = 0x0;
+ rtl8192_setBBreg(dev, rFPGA0_TxGainStage,
+ (bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue);
+
+
+ dwRegValue = priv->CrystalCap;
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, bXtalCap92x,
+ dwRegValue);
+ }
+
+ return rtStatus;
+}
+bool rtl8192_BBConfig(struct net_device *dev)
+{
+ rtl8192_InitBBRFRegDef(dev);
+ return rtl8192_BB_Config_ParaFile(dev);
+}
+
+void rtl8192_phy_getTxPower(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->MCSTxPowerLevelOriginalOffset[0] =
+ read_nic_dword(dev, rTxAGC_Rate18_06);
+ priv->MCSTxPowerLevelOriginalOffset[1] =
+ read_nic_dword(dev, rTxAGC_Rate54_24);
+ priv->MCSTxPowerLevelOriginalOffset[2] =
+ read_nic_dword(dev, rTxAGC_Mcs03_Mcs00);
+ priv->MCSTxPowerLevelOriginalOffset[3] =
+ read_nic_dword(dev, rTxAGC_Mcs07_Mcs04);
+ priv->MCSTxPowerLevelOriginalOffset[4] =
+ read_nic_dword(dev, rTxAGC_Mcs11_Mcs08);
+ priv->MCSTxPowerLevelOriginalOffset[5] =
+ read_nic_dword(dev, rTxAGC_Mcs15_Mcs12);
+
+ priv->DefaultInitialGain[0] = read_nic_byte(dev, rOFDM0_XAAGCCore1);
+ priv->DefaultInitialGain[1] = read_nic_byte(dev, rOFDM0_XBAGCCore1);
+ priv->DefaultInitialGain[2] = read_nic_byte(dev, rOFDM0_XCAGCCore1);
+ priv->DefaultInitialGain[3] = read_nic_byte(dev, rOFDM0_XDAGCCore1);
+ RT_TRACE(COMP_INIT,
+ "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n",
+ priv->DefaultInitialGain[0], priv->DefaultInitialGain[1],
+ priv->DefaultInitialGain[2], priv->DefaultInitialGain[3]);
+
+ priv->framesync = read_nic_byte(dev, rOFDM0_RxDetector3);
+ priv->framesyncC34 = read_nic_dword(dev, rOFDM0_RxDetector2);
+ RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x\n",
+ rOFDM0_RxDetector3, priv->framesync);
+ priv->SifsTime = read_nic_word(dev, SIFS);
+}
+
+void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 powerlevel = 0, powerlevelOFDM24G = 0;
+ char ant_pwr_diff;
+ u32 u4RegValue;
+
+ if (priv->epromtype == EEPROM_93C46) {
+ powerlevel = priv->TxPowerLevelCCK[channel-1];
+ powerlevelOFDM24G = priv->TxPowerLevelOFDM24G[channel-1];
+ } else if (priv->epromtype == EEPROM_93C56) {
+ if (priv->rf_type == RF_1T2R) {
+ powerlevel = priv->TxPowerLevelCCK_C[channel-1];
+ powerlevelOFDM24G = priv->TxPowerLevelOFDM24G_C[channel-1];
+ } else if (priv->rf_type == RF_2T4R) {
+ powerlevel = priv->TxPowerLevelCCK_A[channel-1];
+ powerlevelOFDM24G = priv->TxPowerLevelOFDM24G_A[channel-1];
+
+ ant_pwr_diff = priv->TxPowerLevelOFDM24G_C[channel-1]
+ - priv->TxPowerLevelOFDM24G_A[channel-1];
+
+ priv->RF_C_TxPwDiff = ant_pwr_diff;
+
+ ant_pwr_diff &= 0xf;
+
+ priv->AntennaTxPwDiff[2] = 0;
+ priv->AntennaTxPwDiff[1] = (u8)(ant_pwr_diff);
+ priv->AntennaTxPwDiff[0] = 0;
+
+ u4RegValue = (priv->AntennaTxPwDiff[2]<<8 |
+ priv->AntennaTxPwDiff[1]<<4 |
+ priv->AntennaTxPwDiff[0]);
+
+ rtl8192_setBBreg(dev, rFPGA0_TxGainStage,
+ (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue);
+ }
+ }
+ switch (priv->rf_chip) {
+ case RF_8225:
+ break;
+ case RF_8256:
+ PHY_SetRF8256CCKTxPower(dev, powerlevel);
+ PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G);
+ break;
+ case RF_8258:
+ break;
+ default:
+ RT_TRACE(COMP_ERR, "unknown rf chip in function %s()\n",
+ __func__);
+ break;
+ }
+}
+
+bool rtl8192_phy_RFConfig(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ bool rtStatus = true;
+
+ switch (priv->rf_chip) {
+ case RF_8225:
+ break;
+ case RF_8256:
+ rtStatus = PHY_RF8256_Config(dev);
+ break;
+
+ case RF_8258:
+ break;
+ case RF_PSEUDO_11N:
+ break;
+
+ default:
+ RT_TRACE(COMP_ERR, "error chip id\n");
+ break;
+ }
+ return rtStatus;
+}
+
+void rtl8192_phy_updateInitGain(struct net_device *dev)
+{
+}
+
+u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
+ enum rf90_radio_path eRFPath)
+{
+
+ int i;
+
+ switch (eRFPath) {
+ case RF90_PATH_A:
+ for (i = 0; i < RadioA_ArrayLength; i += 2) {
+ if (Rtl819XRadioA_Array[i] == 0xfe) {
+ msleep(100);
+ continue;
+ }
+ rtl8192_phy_SetRFReg(dev, eRFPath,
+ Rtl819XRadioA_Array[i],
+ bMask12Bits,
+ Rtl819XRadioA_Array[i+1]);
+
+ }
+ break;
+ case RF90_PATH_B:
+ for (i = 0; i < RadioB_ArrayLength; i += 2) {
+ if (Rtl819XRadioB_Array[i] == 0xfe) {
+ msleep(100);
+ continue;
+ }
+ rtl8192_phy_SetRFReg(dev, eRFPath,
+ Rtl819XRadioB_Array[i],
+ bMask12Bits,
+ Rtl819XRadioB_Array[i+1]);
+
+ }
+ break;
+ case RF90_PATH_C:
+ for (i = 0; i < RadioC_ArrayLength; i += 2) {
+ if (Rtl819XRadioC_Array[i] == 0xfe) {
+ msleep(100);
+ continue;
+ }
+ rtl8192_phy_SetRFReg(dev, eRFPath,
+ Rtl819XRadioC_Array[i],
+ bMask12Bits,
+ Rtl819XRadioC_Array[i+1]);
+
+ }
+ break;
+ case RF90_PATH_D:
+ for (i = 0; i < RadioD_ArrayLength; i += 2) {
+ if (Rtl819XRadioD_Array[i] == 0xfe) {
+ msleep(100);
+ continue;
+ }
+ rtl8192_phy_SetRFReg(dev, eRFPath,
+ Rtl819XRadioD_Array[i], bMask12Bits,
+ Rtl819XRadioD_Array[i+1]);
+
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+
+}
+static void rtl8192_SetTxPowerLevel(struct net_device *dev, u8 channel)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 powerlevel = priv->TxPowerLevelCCK[channel-1];
+ u8 powerlevelOFDM24G = priv->TxPowerLevelOFDM24G[channel-1];
+
+ switch (priv->rf_chip) {
+ case RF_8225:
+ break;
+
+ case RF_8256:
+ PHY_SetRF8256CCKTxPower(dev, powerlevel);
+ PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G);
+ break;
+
+ case RF_8258:
+ break;
+ default:
+ RT_TRACE(COMP_ERR,
+ "unknown rf chip ID in rtl8192_SetTxPowerLevel()\n");
+ break;
+ }
+}
+
+static u8 rtl8192_phy_SetSwChnlCmdArray(struct sw_chnl_cmd *CmdTable,
+ u32 CmdTableIdx, u32 CmdTableSz,
+ enum sw_chnl_cmd_id CmdID,
+ u32 Para1, u32 Para2, u32 msDelay)
+{
+ struct sw_chnl_cmd *pCmd;
+
+ if (CmdTable == NULL) {
+ RT_TRACE(COMP_ERR,
+ "phy_SetSwChnlCmdArray(): CmdTable cannot be NULL.\n");
+ return false;
+ }
+ if (CmdTableIdx >= CmdTableSz) {
+ RT_TRACE(COMP_ERR,
+ "phy_SetSwChnlCmdArray(): Access invalid index, please check size of the table, CmdTableIdx:%d, CmdTableSz:%d\n",
+ CmdTableIdx, CmdTableSz);
+ return false;
+ }
+
+ pCmd = CmdTable + CmdTableIdx;
+ pCmd->CmdID = CmdID;
+ pCmd->Para1 = Para1;
+ pCmd->Para2 = Para2;
+ pCmd->msDelay = msDelay;
+
+ return true;
+}
+
+static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel,
+ u8 *stage, u8 *step, u32 *delay)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+ u32 PreCommonCmdCnt;
+ u32 PostCommonCmdCnt;
+ u32 RfDependCmdCnt;
+ struct sw_chnl_cmd *CurrentCmd = NULL;
+ u8 eRFPath;
+
+ RT_TRACE(COMP_TRACE, "====>%s()====stage:%d, step:%d, channel:%d\n",
+ __func__, *stage, *step, channel);
+
+ if (!rtllib_legal_channel(priv->rtllib, channel)) {
+ RT_TRACE(COMP_ERR, "=============>set to illegal channel:%d\n",
+ channel);
+ return true;
+ }
+
+ {
+ PreCommonCmdCnt = 0;
+ rtl8192_phy_SetSwChnlCmdArray(ieee->PreCommonCmd,
+ PreCommonCmdCnt++,
+ MAX_PRECMD_CNT, CmdID_SetTxPowerLevel,
+ 0, 0, 0);
+ rtl8192_phy_SetSwChnlCmdArray(ieee->PreCommonCmd,
+ PreCommonCmdCnt++,
+ MAX_PRECMD_CNT, CmdID_End, 0, 0, 0);
+
+ PostCommonCmdCnt = 0;
+
+ rtl8192_phy_SetSwChnlCmdArray(ieee->PostCommonCmd,
+ PostCommonCmdCnt++,
+ MAX_POSTCMD_CNT, CmdID_End, 0, 0, 0);
+
+ RfDependCmdCnt = 0;
+ switch (priv->rf_chip) {
+ case RF_8225:
+ if (!(channel >= 1 && channel <= 14)) {
+ RT_TRACE(COMP_ERR,
+ "illegal channel for Zebra 8225: %d\n",
+ channel);
+ return false;
+ }
+ rtl8192_phy_SetSwChnlCmdArray(ieee->RfDependCmd,
+ RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
+ CmdID_RF_WriteReg, rZebra1_Channel,
+ RF_CHANNEL_TABLE_ZEBRA[channel], 10);
+ rtl8192_phy_SetSwChnlCmdArray(ieee->RfDependCmd,
+ RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
+ CmdID_End, 0, 0, 0);
+ break;
+
+ case RF_8256:
+ if (!(channel >= 1 && channel <= 14)) {
+ RT_TRACE(COMP_ERR,
+ "illegal channel for Zebra 8256: %d\n",
+ channel);
+ return false;
+ }
+ rtl8192_phy_SetSwChnlCmdArray(ieee->RfDependCmd,
+ RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
+ CmdID_RF_WriteReg, rZebra1_Channel, channel,
+ 10);
+ rtl8192_phy_SetSwChnlCmdArray(ieee->RfDependCmd,
+
+ RfDependCmdCnt++,
+ MAX_RFDEPENDCMD_CNT,
+ CmdID_End, 0, 0, 0);
+ break;
+
+ case RF_8258:
+ break;
+
+ default:
+ RT_TRACE(COMP_ERR, "Unknown RFChipID: %d\n",
+ priv->rf_chip);
+ return false;
+ }
+
+
+ do {
+ switch (*stage) {
+ case 0:
+ CurrentCmd = &ieee->PreCommonCmd[*step];
+ break;
+ case 1:
+ CurrentCmd = &ieee->RfDependCmd[*step];
+ break;
+ case 2:
+ CurrentCmd = &ieee->PostCommonCmd[*step];
+ break;
+ }
+
+ if (CurrentCmd && CurrentCmd->CmdID == CmdID_End) {
+ if ((*stage) == 2)
+ return true;
+ (*stage)++;
+ (*step) = 0;
+ continue;
+ }
+
+ if (!CurrentCmd)
+ continue;
+ switch (CurrentCmd->CmdID) {
+ case CmdID_SetTxPowerLevel:
+ if (priv->IC_Cut > (u8)VERSION_8190_BD)
+ rtl8192_SetTxPowerLevel(dev, channel);
+ break;
+ case CmdID_WritePortUlong:
+ write_nic_dword(dev, CurrentCmd->Para1,
+ CurrentCmd->Para2);
+ break;
+ case CmdID_WritePortUshort:
+ write_nic_word(dev, CurrentCmd->Para1,
+ (u16)CurrentCmd->Para2);
+ break;
+ case CmdID_WritePortUchar:
+ write_nic_byte(dev, CurrentCmd->Para1,
+ (u8)CurrentCmd->Para2);
+ break;
+ case CmdID_RF_WriteReg:
+ for (eRFPath = 0; eRFPath <
+ priv->NumTotalRFPath; eRFPath++)
+ rtl8192_phy_SetRFReg(dev,
+ (enum rf90_radio_path)eRFPath,
+ CurrentCmd->Para1, bMask12Bits,
+ CurrentCmd->Para2<<7);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ } while (true);
+ } /*for (Number of RF paths)*/
+
+ (*delay) = CurrentCmd->msDelay;
+ (*step)++;
+ return false;
+}
+
+static void rtl8192_phy_FinishSwChnlNow(struct net_device *dev, u8 channel)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 delay = 0;
+
+ while (!rtl8192_phy_SwChnlStepByStep(dev, channel, &priv->SwChnlStage,
+ &priv->SwChnlStep, &delay)) {
+ if (delay > 0)
+ msleep(delay);
+ if (!priv->up)
+ break;
+ }
+}
+void rtl8192_SwChnl_WorkItem(struct net_device *dev)
+{
+
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ RT_TRACE(COMP_TRACE, "==> SwChnlCallback819xUsbWorkItem()\n");
+
+ RT_TRACE(COMP_TRACE, "=====>--%s(), set chan:%d, priv:%p\n", __func__,
+ priv->chan, priv);
+
+ rtl8192_phy_FinishSwChnlNow(dev , priv->chan);
+
+ RT_TRACE(COMP_TRACE, "<== SwChnlCallback819xUsbWorkItem()\n");
+}
+
+u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ RT_TRACE(COMP_PHY, "=====>%s()\n", __func__);
+ if (!priv->up) {
+ RT_TRACE(COMP_ERR, "%s(): ERR !! driver is not up\n", __func__);
+ return false;
+ }
+ if (priv->SwChnlInProgress)
+ return false;
+
+
+ switch (priv->rtllib->mode) {
+ case WIRELESS_MODE_A:
+ case WIRELESS_MODE_N_5G:
+ if (channel <= 14) {
+ RT_TRACE(COMP_ERR, "WIRELESS_MODE_A but channel<=14");
+ return false;
+ }
+ break;
+ case WIRELESS_MODE_B:
+ if (channel > 14) {
+ RT_TRACE(COMP_ERR, "WIRELESS_MODE_B but channel>14");
+ return false;
+ }
+ break;
+ case WIRELESS_MODE_G:
+ case WIRELESS_MODE_N_24G:
+ if (channel > 14) {
+ RT_TRACE(COMP_ERR, "WIRELESS_MODE_G but channel>14");
+ return false;
+ }
+ break;
+ }
+
+ priv->SwChnlInProgress = true;
+ if (channel == 0)
+ channel = 1;
+
+ priv->chan = channel;
+
+ priv->SwChnlStage = 0;
+ priv->SwChnlStep = 0;
+
+ if (priv->up)
+ rtl8192_SwChnl_WorkItem(dev);
+ priv->SwChnlInProgress = false;
+ return true;
+}
+
+static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ switch (priv->CurrentChannelBW) {
+ case HT_CHANNEL_WIDTH_20:
+ priv->CCKPresentAttentuation =
+ priv->CCKPresentAttentuation_20Mdefault +
+ priv->CCKPresentAttentuation_difference;
+
+ if (priv->CCKPresentAttentuation >
+ (CCKTxBBGainTableLength-1))
+ priv->CCKPresentAttentuation =
+ CCKTxBBGainTableLength-1;
+ if (priv->CCKPresentAttentuation < 0)
+ priv->CCKPresentAttentuation = 0;
+
+ RT_TRACE(COMP_POWER_TRACKING,
+ "20M, priv->CCKPresentAttentuation = %d\n",
+ priv->CCKPresentAttentuation);
+
+ if (priv->rtllib->current_network.channel == 14 &&
+ !priv->bcck_in_ch14) {
+ priv->bcck_in_ch14 = true;
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ } else if (priv->rtllib->current_network.channel !=
+ 14 && priv->bcck_in_ch14) {
+ priv->bcck_in_ch14 = false;
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ } else {
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ }
+ break;
+
+ case HT_CHANNEL_WIDTH_20_40:
+ priv->CCKPresentAttentuation =
+ priv->CCKPresentAttentuation_40Mdefault +
+ priv->CCKPresentAttentuation_difference;
+
+ RT_TRACE(COMP_POWER_TRACKING,
+ "40M, priv->CCKPresentAttentuation = %d\n",
+ priv->CCKPresentAttentuation);
+ if (priv->CCKPresentAttentuation >
+ (CCKTxBBGainTableLength - 1))
+ priv->CCKPresentAttentuation =
+ CCKTxBBGainTableLength-1;
+ if (priv->CCKPresentAttentuation < 0)
+ priv->CCKPresentAttentuation = 0;
+
+ if (priv->rtllib->current_network.channel == 14 &&
+ !priv->bcck_in_ch14) {
+ priv->bcck_in_ch14 = true;
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ } else if (priv->rtllib->current_network.channel != 14
+ && priv->bcck_in_ch14) {
+ priv->bcck_in_ch14 = false;
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ } else {
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ }
+ break;
+ }
+}
+
+static void CCK_Tx_Power_Track_BW_Switch_ThermalMeter(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->rtllib->current_network.channel == 14 &&
+ !priv->bcck_in_ch14)
+ priv->bcck_in_ch14 = true;
+ else if (priv->rtllib->current_network.channel != 14 &&
+ priv->bcck_in_ch14)
+ priv->bcck_in_ch14 = false;
+
+ switch (priv->CurrentChannelBW) {
+ case HT_CHANNEL_WIDTH_20:
+ if (priv->Record_CCK_20Mindex == 0)
+ priv->Record_CCK_20Mindex = 6;
+ priv->CCK_index = priv->Record_CCK_20Mindex;
+ RT_TRACE(COMP_POWER_TRACKING,
+ "20MHz, CCK_Tx_Power_Track_BW_Switch_ThermalMeter(),CCK_index = %d\n",
+ priv->CCK_index);
+ break;
+
+ case HT_CHANNEL_WIDTH_20_40:
+ priv->CCK_index = priv->Record_CCK_40Mindex;
+ RT_TRACE(COMP_POWER_TRACKING,
+ "40MHz, CCK_Tx_Power_Track_BW_Switch_ThermalMeter(), CCK_index = %d\n",
+ priv->CCK_index);
+ break;
+ }
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+}
+
+static void CCK_Tx_Power_Track_BW_Switch(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->IC_Cut >= IC_VersionCut_D)
+ CCK_Tx_Power_Track_BW_Switch_TSSI(dev);
+ else
+ CCK_Tx_Power_Track_BW_Switch_ThermalMeter(dev);
+}
+
+void rtl8192_SetBWModeWorkItem(struct net_device *dev)
+{
+
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 regBwOpMode;
+
+ RT_TRACE(COMP_SWBW,
+ "==>rtl8192_SetBWModeWorkItem() Switch to %s bandwidth\n",
+ priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ?
+ "20MHz" : "40MHz");
+
+
+ if (priv->rf_chip == RF_PSEUDO_11N) {
+ priv->SetBWModeInProgress = false;
+ return;
+ }
+ if (!priv->up) {
+ RT_TRACE(COMP_ERR, "%s(): ERR!! driver is not up\n", __func__);
+ return;
+ }
+ regBwOpMode = read_nic_byte(dev, BW_OPMODE);
+
+ switch (priv->CurrentChannelBW) {
+ case HT_CHANNEL_WIDTH_20:
+ regBwOpMode |= BW_OPMODE_20MHZ;
+ write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+ break;
+
+ case HT_CHANNEL_WIDTH_20_40:
+ regBwOpMode &= ~BW_OPMODE_20MHZ;
+ write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+ break;
+
+ default:
+ RT_TRACE(COMP_ERR,
+ "SetChannelBandwidth819xUsb(): unknown Bandwidth: %#X\n",
+ priv->CurrentChannelBW);
+ break;
+ }
+
+ switch (priv->CurrentChannelBW) {
+ case HT_CHANNEL_WIDTH_20:
+ rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x0);
+ rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x0);
+
+ if (!priv->btxpower_tracking) {
+ write_nic_dword(dev, rCCK0_TxFilter1, 0x1a1b0000);
+ write_nic_dword(dev, rCCK0_TxFilter2, 0x090e1317);
+ write_nic_dword(dev, rCCK0_DebugPort, 0x00000204);
+ } else {
+ CCK_Tx_Power_Track_BW_Switch(dev);
+ }
+
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1);
+
+ break;
+ case HT_CHANNEL_WIDTH_20_40:
+ rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x1);
+ rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x1);
+
+ if (!priv->btxpower_tracking) {
+ write_nic_dword(dev, rCCK0_TxFilter1, 0x35360000);
+ write_nic_dword(dev, rCCK0_TxFilter2, 0x121c252e);
+ write_nic_dword(dev, rCCK0_DebugPort, 0x00000409);
+ } else {
+ CCK_Tx_Power_Track_BW_Switch(dev);
+ }
+
+ rtl8192_setBBreg(dev, rCCK0_System, bCCKSideBand,
+ (priv->nCur40MhzPrimeSC>>1));
+ rtl8192_setBBreg(dev, rOFDM1_LSTF, 0xC00,
+ priv->nCur40MhzPrimeSC);
+
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0);
+ break;
+ default:
+ RT_TRACE(COMP_ERR,
+ "SetChannelBandwidth819xUsb(): unknown Bandwidth: %#X\n",
+ priv->CurrentChannelBW);
+ break;
+
+ }
+
+ switch (priv->rf_chip) {
+ case RF_8225:
+ break;
+
+ case RF_8256:
+ PHY_SetRF8256Bandwidth(dev, priv->CurrentChannelBW);
+ break;
+
+ case RF_8258:
+ break;
+
+ case RF_PSEUDO_11N:
+ break;
+
+ default:
+ RT_TRACE(COMP_ERR, "Unknown RFChipID: %d\n", priv->rf_chip);
+ break;
+ }
+
+ atomic_dec(&(priv->rtllib->atm_swbw));
+ priv->SetBWModeInProgress = false;
+
+ RT_TRACE(COMP_SWBW, "<==SetBWMode819xUsb()");
+}
+
+void rtl8192_SetBWMode(struct net_device *dev, enum ht_channel_width Bandwidth,
+ enum ht_extchnl_offset Offset)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+
+ if (priv->SetBWModeInProgress)
+ return;
+
+ atomic_inc(&(priv->rtllib->atm_swbw));
+ priv->SetBWModeInProgress = true;
+
+ priv->CurrentChannelBW = Bandwidth;
+
+ if (Offset == HT_EXTCHNL_OFFSET_LOWER)
+ priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_UPPER;
+ else if (Offset == HT_EXTCHNL_OFFSET_UPPER)
+ priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_LOWER;
+ else
+ priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+ rtl8192_SetBWModeWorkItem(dev);
+
+}
+
+void InitialGain819xPci(struct net_device *dev, u8 Operation)
+{
+#define SCAN_RX_INITIAL_GAIN 0x17
+#define POWER_DETECTION_TH 0x08
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 BitMask;
+ u8 initial_gain;
+
+ if (priv->up) {
+ switch (Operation) {
+ case IG_Backup:
+ RT_TRACE(COMP_SCAN,
+ "IG_Backup, backup the initial gain.\n");
+ initial_gain = SCAN_RX_INITIAL_GAIN;
+ BitMask = bMaskByte0;
+ if (dm_digtable.dig_algorithm ==
+ DIG_ALGO_BY_FALSE_ALARM)
+ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+ priv->initgain_backup.xaagccore1 =
+ (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1,
+ BitMask);
+ priv->initgain_backup.xbagccore1 =
+ (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1,
+ BitMask);
+ priv->initgain_backup.xcagccore1 =
+ (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1,
+ BitMask);
+ priv->initgain_backup.xdagccore1 =
+ (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1,
+ BitMask);
+ BitMask = bMaskByte2;
+ priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev,
+ rCCK0_CCA, BitMask);
+
+ RT_TRACE(COMP_SCAN,
+ "Scan InitialGainBackup 0xc50 is %x\n",
+ priv->initgain_backup.xaagccore1);
+ RT_TRACE(COMP_SCAN,
+ "Scan InitialGainBackup 0xc58 is %x\n",
+ priv->initgain_backup.xbagccore1);
+ RT_TRACE(COMP_SCAN,
+ "Scan InitialGainBackup 0xc60 is %x\n",
+ priv->initgain_backup.xcagccore1);
+ RT_TRACE(COMP_SCAN,
+ "Scan InitialGainBackup 0xc68 is %x\n",
+ priv->initgain_backup.xdagccore1);
+ RT_TRACE(COMP_SCAN,
+ "Scan InitialGainBackup 0xa0a is %x\n",
+ priv->initgain_backup.cca);
+
+ RT_TRACE(COMP_SCAN, "Write scan initial gain = 0x%x\n",
+ initial_gain);
+ write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain);
+ write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain);
+ write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain);
+ write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain);
+ RT_TRACE(COMP_SCAN, "Write scan 0xa0a = 0x%x\n",
+ POWER_DETECTION_TH);
+ write_nic_byte(dev, 0xa0a, POWER_DETECTION_TH);
+ break;
+ case IG_Restore:
+ RT_TRACE(COMP_SCAN,
+ "IG_Restore, restore the initial gain.\n");
+ BitMask = 0x7f;
+ if (dm_digtable.dig_algorithm ==
+ DIG_ALGO_BY_FALSE_ALARM)
+ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+
+ rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, BitMask,
+ (u32)priv->initgain_backup.xaagccore1);
+ rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, BitMask,
+ (u32)priv->initgain_backup.xbagccore1);
+ rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, BitMask,
+ (u32)priv->initgain_backup.xcagccore1);
+ rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, BitMask,
+ (u32)priv->initgain_backup.xdagccore1);
+ BitMask = bMaskByte2;
+ rtl8192_setBBreg(dev, rCCK0_CCA, BitMask,
+ (u32)priv->initgain_backup.cca);
+
+ RT_TRACE(COMP_SCAN,
+ "Scan BBInitialGainRestore 0xc50 is %x\n",
+ priv->initgain_backup.xaagccore1);
+ RT_TRACE(COMP_SCAN,
+ "Scan BBInitialGainRestore 0xc58 is %x\n",
+ priv->initgain_backup.xbagccore1);
+ RT_TRACE(COMP_SCAN,
+ "Scan BBInitialGainRestore 0xc60 is %x\n",
+ priv->initgain_backup.xcagccore1);
+ RT_TRACE(COMP_SCAN,
+ "Scan BBInitialGainRestore 0xc68 is %x\n",
+ priv->initgain_backup.xdagccore1);
+ RT_TRACE(COMP_SCAN,
+ "Scan BBInitialGainRestore 0xa0a is %x\n",
+ priv->initgain_backup.cca);
+
+ rtl8192_phy_setTxPower(dev,
+ priv->rtllib->current_network.channel);
+
+ if (dm_digtable.dig_algorithm ==
+ DIG_ALGO_BY_FALSE_ALARM)
+ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+ break;
+ default:
+ RT_TRACE(COMP_SCAN, "Unknown IG Operation.\n");
+ break;
+ }
+ }
+}
+
+void PHY_SetRtl8192eRfOff(struct net_device *dev)
+{
+
+ rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
+ rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);
+ rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
+ write_nic_byte(dev, ANAPAR_FOR_8192PciE, 0x07);
+
+}
+
+static bool SetRFPowerState8190(struct net_device *dev,
+ enum rt_rf_power_state eRFPowerState)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ (&(priv->rtllib->PowerSaveControl));
+ bool bResult = true;
+ u8 i = 0, QueueID = 0;
+ struct rtl8192_tx_ring *ring = NULL;
+
+ if (priv->SetRFPowerStateInProgress)
+ return false;
+ RT_TRACE(COMP_PS, "===========> SetRFPowerState8190()!\n");
+ priv->SetRFPowerStateInProgress = true;
+
+ switch (priv->rf_chip) {
+ case RF_8256:
+ switch (eRFPowerState) {
+ case eRfOn:
+ RT_TRACE(COMP_PS, "SetRFPowerState8190() eRfOn!\n");
+ if ((priv->rtllib->eRFPowerState == eRfOff) &&
+ RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) {
+ bool rtstatus = true;
+ u32 InitilizeCount = 3;
+
+ do {
+ InitilizeCount--;
+ priv->RegRfOff = false;
+ rtstatus = NicIFEnableNIC(dev);
+ } while (!rtstatus && (InitilizeCount > 0));
+
+ if (!rtstatus) {
+ RT_TRACE(COMP_ERR,
+ "%s():Initialize Adapter fail,return\n",
+ __func__);
+ priv->SetRFPowerStateInProgress = false;
+ return false;
+ }
+
+ RT_CLEAR_PS_LEVEL(pPSC,
+ RT_RF_OFF_LEVL_HALT_NIC);
+ } else {
+ write_nic_byte(dev, ANAPAR, 0x37);
+ mdelay(1);
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1,
+ 0x4, 0x1);
+ priv->bHwRfOffAction = 0;
+
+ rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE,
+ BIT4, 0x1);
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4,
+ 0x300, 0x3);
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1,
+ 0x18, 0x3);
+ rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x3,
+ 0x3);
+ rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x3,
+ 0x3);
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1,
+ 0x60, 0x3);
+
+ }
+
+ break;
+
+ case eRfSleep:
+ if (priv->rtllib->eRFPowerState == eRfOff)
+ break;
+
+
+ for (QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; ) {
+ ring = &priv->tx_ring[QueueID];
+
+ if (skb_queue_len(&ring->queue) == 0) {
+ QueueID++;
+ continue;
+ } else {
+ RT_TRACE((COMP_POWER|COMP_RF),
+ "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n",
+ (i+1), QueueID);
+ udelay(10);
+ i++;
+ }
+
+ if (i >= MAX_DOZE_WAITING_TIMES_9x) {
+ RT_TRACE(COMP_POWER,
+ "\n\n\n TimeOut!! SetRFPowerState8190(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n",
+ MAX_DOZE_WAITING_TIMES_9x,
+ QueueID);
+ break;
+ }
+ }
+ PHY_SetRtl8192eRfOff(dev);
+ break;
+
+ case eRfOff:
+ RT_TRACE(COMP_PS,
+ "SetRFPowerState8190() eRfOff/Sleep !\n");
+
+ for (QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; ) {
+ ring = &priv->tx_ring[QueueID];
+
+ if (skb_queue_len(&ring->queue) == 0) {
+ QueueID++;
+ continue;
+ } else {
+ RT_TRACE(COMP_POWER,
+ "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n",
+ (i+1), QueueID);
+ udelay(10);
+ i++;
+ }
+
+ if (i >= MAX_DOZE_WAITING_TIMES_9x) {
+ RT_TRACE(COMP_POWER,
+ "\n\n\n SetZebra: RFPowerState8185B(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n",
+ MAX_DOZE_WAITING_TIMES_9x,
+ QueueID);
+ break;
+ }
+ }
+
+ if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC &&
+ !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) {
+ NicIFDisableNIC(dev);
+ RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+ } else if (!(pPSC->RegRfPsLevel &
+ RT_RF_OFF_LEVL_HALT_NIC)) {
+ PHY_SetRtl8192eRfOff(dev);
+ }
+
+ break;
+
+ default:
+ bResult = false;
+ RT_TRACE(COMP_ERR,
+ "SetRFPowerState8190(): unknown state to set: 0x%X!!!\n",
+ eRFPowerState);
+ break;
+ }
+
+ break;
+
+ default:
+ RT_TRACE(COMP_ERR, "SetRFPowerState8190(): Unknown RF type\n");
+ break;
+ }
+
+ if (bResult) {
+ priv->rtllib->eRFPowerState = eRFPowerState;
+
+ switch (priv->rf_chip) {
+ case RF_8256:
+ break;
+
+ default:
+ RT_TRACE(COMP_ERR,
+ "SetRFPowerState8190(): Unknown RF type\n");
+ break;
+ }
+ }
+
+ priv->SetRFPowerStateInProgress = false;
+ RT_TRACE(COMP_PS, "<=========== SetRFPowerState8190() bResult = %d!\n",
+ bResult);
+ return bResult;
+}
+
+bool SetRFPowerState(struct net_device *dev,
+ enum rt_rf_power_state eRFPowerState)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ bool bResult = false;
+
+ RT_TRACE(COMP_PS, "---------> SetRFPowerState(): eRFPowerState(%d)\n",
+ eRFPowerState);
+ if (eRFPowerState == priv->rtllib->eRFPowerState &&
+ priv->bHwRfOffAction == 0) {
+ RT_TRACE(COMP_PS,
+ "<--------- SetRFPowerState(): discard the request for eRFPowerState(%d) is the same.\n",
+ eRFPowerState);
+ return bResult;
+ }
+
+ bResult = SetRFPowerState8190(dev, eRFPowerState);
+
+ RT_TRACE(COMP_PS, "<--------- SetRFPowerState(): bResult(%d)\n",
+ bResult);
+
+ return bResult;
+}
+
+void PHY_ScanOperationBackup8192(struct net_device *dev, u8 Operation)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->up) {
+ switch (Operation) {
+ case SCAN_OPT_BACKUP:
+ priv->rtllib->InitialGainHandler(dev, IG_Backup);
+ break;
+
+ case SCAN_OPT_RESTORE:
+ priv->rtllib->InitialGainHandler(dev, IG_Restore);
+ break;
+
+ default:
+ RT_TRACE(COMP_SCAN, "Unknown Scan Backup Operation.\n");
+ break;
+ }
+ }
+
+}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h
new file mode 100644
index 000000000..7318f8857
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h
@@ -0,0 +1,120 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _R819XU_PHY_H
+#define _R819XU_PHY_H
+
+#define MAX_DOZE_WAITING_TIMES_9x 64
+
+#define AGCTAB_ArrayLength AGCTAB_ArrayLengthPciE
+#define MACPHY_ArrayLength MACPHY_ArrayLengthPciE
+#define RadioA_ArrayLength RadioA_ArrayLengthPciE
+#define RadioB_ArrayLength RadioB_ArrayLengthPciE
+#define MACPHY_Array_PGLength MACPHY_Array_PGLengthPciE
+#define RadioC_ArrayLength RadioC_ArrayLengthPciE
+#define RadioD_ArrayLength RadioD_ArrayLengthPciE
+#define PHY_REGArrayLength PHY_REGArrayLengthPciE
+#define PHY_REG_1T2RArrayLength PHY_REG_1T2RArrayLengthPciE
+
+#define Rtl819XMACPHY_Array_PG Rtl8192PciEMACPHY_Array_PG
+#define Rtl819XMACPHY_Array Rtl8192PciEMACPHY_Array
+#define Rtl819XRadioA_Array Rtl8192PciERadioA_Array
+#define Rtl819XRadioB_Array Rtl8192PciERadioB_Array
+#define Rtl819XRadioC_Array Rtl8192PciERadioC_Array
+#define Rtl819XRadioD_Array Rtl8192PciERadioD_Array
+#define Rtl819XAGCTAB_Array Rtl8192PciEAGCTAB_Array
+#define Rtl819XPHY_REGArray Rtl8192PciEPHY_REGArray
+#define Rtl819XPHY_REG_1T2RArray Rtl8192PciEPHY_REG_1T2RArray
+
+extern u32 rtl819XMACPHY_Array_PG[];
+extern u32 rtl819XPHY_REG_1T2RArray[];
+extern u32 rtl819XAGCTAB_Array[];
+extern u32 rtl819XRadioA_Array[];
+extern u32 rtl819XRadioB_Array[];
+extern u32 rtl819XRadioC_Array[];
+extern u32 rtl819XRadioD_Array[];
+
+enum hw90_block {
+ HW90_BLOCK_MAC = 0,
+ HW90_BLOCK_PHY0 = 1,
+ HW90_BLOCK_PHY1 = 2,
+ HW90_BLOCK_RF = 3,
+ HW90_BLOCK_MAXIMUM = 4,
+};
+
+enum rf90_radio_path {
+ RF90_PATH_A = 0,
+ RF90_PATH_B = 1,
+ RF90_PATH_C = 2,
+ RF90_PATH_D = 3,
+ RF90_PATH_MAX
+};
+
+#define bMaskByte0 0xff
+#define bMaskByte1 0xff00
+#define bMaskByte2 0xff0000
+#define bMaskByte3 0xff000000
+#define bMaskHWord 0xffff0000
+#define bMaskLWord 0x0000ffff
+#define bMaskDWord 0xffffffff
+
+extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev,
+ u32 eRFPath);
+extern void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr,
+ u32 dwBitMask, u32 dwData);
+extern u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr,
+ u32 dwBitMask);
+extern void rtl8192_phy_SetRFReg(struct net_device *dev,
+ enum rf90_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask, u32 Data);
+extern u32 rtl8192_phy_QueryRFReg(struct net_device *dev,
+ enum rf90_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask);
+extern void rtl8192_phy_configmac(struct net_device *dev);
+extern void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType);
+extern bool rtl8192_phy_checkBBAndRF(struct net_device *dev,
+ enum hw90_block CheckBlock,
+ enum rf90_radio_path eRFPath);
+extern bool rtl8192_BBConfig(struct net_device *dev);
+extern void rtl8192_phy_getTxPower(struct net_device *dev);
+extern void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
+extern bool rtl8192_phy_RFConfig(struct net_device *dev);
+extern void rtl8192_phy_updateInitGain(struct net_device *dev);
+extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
+ enum rf90_radio_path eRFPath);
+
+extern u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
+extern void rtl8192_SetBWMode(struct net_device *dev,
+ enum ht_channel_width Bandwidth,
+ enum ht_extchnl_offset Offset);
+extern void rtl8192_SwChnl_WorkItem(struct net_device *dev);
+extern void rtl8192_SetBWModeWorkItem(struct net_device *dev);
+extern void InitialGain819xPci(struct net_device *dev, u8 Operation);
+
+extern void PHY_SetRtl8192eRfOff(struct net_device *dev);
+
+bool
+SetRFPowerState(
+ struct net_device *dev,
+ enum rt_rf_power_state eRFPowerState
+ );
+#define PHY_SetRFPowerState SetRFPowerState
+
+extern void PHY_ScanOperationBackup8192(struct net_device *dev, u8 Operation);
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h
new file mode 100644
index 000000000..7899dd538
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phyreg.h
@@ -0,0 +1,852 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _R819XU_PHYREG_H
+#define _R819XU_PHYREG_H
+
+
+#define RF_DATA 0x1d4
+
+#define rPMAC_Reset 0x100
+#define rPMAC_TxStart 0x104
+#define rPMAC_TxLegacySIG 0x108
+#define rPMAC_TxHTSIG1 0x10c
+#define rPMAC_TxHTSIG2 0x110
+#define rPMAC_PHYDebug 0x114
+#define rPMAC_TxPacketNum 0x118
+#define rPMAC_TxIdle 0x11c
+#define rPMAC_TxMACHeader0 0x120
+#define rPMAC_TxMACHeader1 0x124
+#define rPMAC_TxMACHeader2 0x128
+#define rPMAC_TxMACHeader3 0x12c
+#define rPMAC_TxMACHeader4 0x130
+#define rPMAC_TxMACHeader5 0x134
+#define rPMAC_TxDataType 0x138
+#define rPMAC_TxRandomSeed 0x13c
+#define rPMAC_CCKPLCPPreamble 0x140
+#define rPMAC_CCKPLCPHeader 0x144
+#define rPMAC_CCKCRC16 0x148
+#define rPMAC_OFDMRxCRC32OK 0x170
+#define rPMAC_OFDMRxCRC32Er 0x174
+#define rPMAC_OFDMRxParityEr 0x178
+#define rPMAC_OFDMRxCRC8Er 0x17c
+#define rPMAC_CCKCRxRC16Er 0x180
+#define rPMAC_CCKCRxRC32Er 0x184
+#define rPMAC_CCKCRxRC32OK 0x188
+#define rPMAC_TxStatus 0x18c
+
+#define MCS_TXAGC 0x340
+#define CCK_TXAGC 0x348
+
+/*---------------------0x400~0x4ff----------------------*/
+#define MacBlkCtrl 0x403
+
+#define rFPGA0_RFMOD 0x800
+#define rFPGA0_TxInfo 0x804
+#define rFPGA0_PSDFunction 0x808
+#define rFPGA0_TxGainStage 0x80c
+#define rFPGA0_RFTiming1 0x810
+#define rFPGA0_RFTiming2 0x814
+#define rFPGA0_XA_HSSIParameter1 0x820
+#define rFPGA0_XA_HSSIParameter2 0x824
+#define rFPGA0_XB_HSSIParameter1 0x828
+#define rFPGA0_XB_HSSIParameter2 0x82c
+#define rFPGA0_XC_HSSIParameter1 0x830
+#define rFPGA0_XC_HSSIParameter2 0x834
+#define rFPGA0_XD_HSSIParameter1 0x838
+#define rFPGA0_XD_HSSIParameter2 0x83c
+#define rFPGA0_XA_LSSIParameter 0x840
+#define rFPGA0_XB_LSSIParameter 0x844
+#define rFPGA0_XC_LSSIParameter 0x848
+#define rFPGA0_XD_LSSIParameter 0x84c
+#define rFPGA0_RFWakeUpParameter 0x850
+#define rFPGA0_RFSleepUpParameter 0x854
+#define rFPGA0_XAB_SwitchControl 0x858
+#define rFPGA0_XCD_SwitchControl 0x85c
+#define rFPGA0_XA_RFInterfaceOE 0x860
+#define rFPGA0_XB_RFInterfaceOE 0x864
+#define rFPGA0_XC_RFInterfaceOE 0x868
+#define rFPGA0_XD_RFInterfaceOE 0x86c
+#define rFPGA0_XAB_RFInterfaceSW 0x870
+#define rFPGA0_XCD_RFInterfaceSW 0x874
+#define rFPGA0_XAB_RFParameter 0x878
+#define rFPGA0_XCD_RFParameter 0x87c
+#define rFPGA0_AnalogParameter1 0x880
+#define rFPGA0_AnalogParameter2 0x884
+#define rFPGA0_AnalogParameter3 0x888
+#define rFPGA0_AnalogParameter4 0x88c
+#define rFPGA0_XA_LSSIReadBack 0x8a0
+#define rFPGA0_XB_LSSIReadBack 0x8a4
+#define rFPGA0_XC_LSSIReadBack 0x8a8
+#define rFPGA0_XD_LSSIReadBack 0x8ac
+#define rFPGA0_PSDReport 0x8b4
+#define rFPGA0_XAB_RFInterfaceRB 0x8e0
+#define rFPGA0_XCD_RFInterfaceRB 0x8e4
+
+#define rFPGA1_RFMOD 0x900
+#define rFPGA1_TxBlock 0x904
+#define rFPGA1_DebugSelect 0x908
+#define rFPGA1_TxInfo 0x90c
+
+#define rCCK0_System 0xa00
+#define rCCK0_AFESetting 0xa04
+#define rCCK0_CCA 0xa08
+#define rCCK0_RxAGC1 0xa0c
+#define rCCK0_RxAGC2 0xa10
+#define rCCK0_RxHP 0xa14
+#define rCCK0_DSPParameter1 0xa18
+#define rCCK0_DSPParameter2 0xa1c
+#define rCCK0_TxFilter1 0xa20
+#define rCCK0_TxFilter2 0xa24
+#define rCCK0_DebugPort 0xa28
+#define rCCK0_FalseAlarmReport 0xa2c
+#define rCCK0_TRSSIReport 0xa50
+#define rCCK0_RxReport 0xa54
+#define rCCK0_FACounterLower 0xa5c
+#define rCCK0_FACounterUpper 0xa58
+
+#define rOFDM0_LSTF 0xc00
+#define rOFDM0_TRxPathEnable 0xc04
+#define rOFDM0_TRMuxPar 0xc08
+#define rOFDM0_TRSWIsolation 0xc0c
+#define rOFDM0_XARxAFE 0xc10
+#define rOFDM0_XARxIQImbalance 0xc14
+#define rOFDM0_XBRxAFE 0xc18
+#define rOFDM0_XBRxIQImbalance 0xc1c
+#define rOFDM0_XCRxAFE 0xc20
+#define rOFDM0_XCRxIQImbalance 0xc24
+#define rOFDM0_XDRxAFE 0xc28
+#define rOFDM0_XDRxIQImbalance 0xc2c
+#define rOFDM0_RxDetector1 0xc30
+#define rOFDM0_RxDetector2 0xc34
+#define rOFDM0_RxDetector3 0xc38
+#define rOFDM0_RxDetector4 0xc3c
+#define rOFDM0_RxDSP 0xc40
+#define rOFDM0_CFOandDAGC 0xc44
+#define rOFDM0_CCADropThreshold 0xc48
+#define rOFDM0_ECCAThreshold 0xc4c
+#define rOFDM0_XAAGCCore1 0xc50
+#define rOFDM0_XAAGCCore2 0xc54
+#define rOFDM0_XBAGCCore1 0xc58
+#define rOFDM0_XBAGCCore2 0xc5c
+#define rOFDM0_XCAGCCore1 0xc60
+#define rOFDM0_XCAGCCore2 0xc64
+#define rOFDM0_XDAGCCore1 0xc68
+#define rOFDM0_XDAGCCore2 0xc6c
+#define rOFDM0_AGCParameter1 0xc70
+#define rOFDM0_AGCParameter2 0xc74
+#define rOFDM0_AGCRSSITable 0xc78
+#define rOFDM0_HTSTFAGC 0xc7c
+#define rOFDM0_XATxIQImbalance 0xc80
+#define rOFDM0_XATxAFE 0xc84
+#define rOFDM0_XBTxIQImbalance 0xc88
+#define rOFDM0_XBTxAFE 0xc8c
+#define rOFDM0_XCTxIQImbalance 0xc90
+#define rOFDM0_XCTxAFE 0xc94
+#define rOFDM0_XDTxIQImbalance 0xc98
+#define rOFDM0_XDTxAFE 0xc9c
+#define rOFDM0_RxHPParameter 0xce0
+#define rOFDM0_TxPseudoNoiseWgt 0xce4
+#define rOFDM0_FrameSync 0xcf0
+#define rOFDM0_DFSReport 0xcf4
+#define rOFDM0_TxCoeff1 0xca4
+#define rOFDM0_TxCoeff2 0xca8
+#define rOFDM0_TxCoeff3 0xcac
+#define rOFDM0_TxCoeff4 0xcb0
+#define rOFDM0_TxCoeff5 0xcb4
+#define rOFDM0_TxCoeff6 0xcb8
+
+
+#define rOFDM1_LSTF 0xd00
+#define rOFDM1_TRxPathEnable 0xd04
+#define rOFDM1_CFO 0xd08
+#define rOFDM1_CSI1 0xd10
+#define rOFDM1_SBD 0xd14
+#define rOFDM1_CSI2 0xd18
+#define rOFDM1_CFOTracking 0xd2c
+#define rOFDM1_TRxMesaure1 0xd34
+#define rOFDM1_IntfDet 0xd3c
+#define rOFDM1_PseudoNoiseStateAB 0xd50
+#define rOFDM1_PseudoNoiseStateCD 0xd54
+#define rOFDM1_RxPseudoNoiseWgt 0xd58
+#define rOFDM_PHYCounter1 0xda0
+#define rOFDM_PHYCounter2 0xda4
+#define rOFDM_PHYCounter3 0xda8
+#define rOFDM_ShortCFOAB 0xdac
+#define rOFDM_ShortCFOCD 0xdb0
+#define rOFDM_LongCFOAB 0xdb4
+#define rOFDM_LongCFOCD 0xdb8
+#define rOFDM_TailCFOAB 0xdbc
+#define rOFDM_TailCFOCD 0xdc0
+#define rOFDM_PWMeasure1 0xdc4
+#define rOFDM_PWMeasure2 0xdc8
+#define rOFDM_BWReport 0xdcc
+#define rOFDM_AGCReport 0xdd0
+#define rOFDM_RxSNR 0xdd4
+#define rOFDM_RxEVMCSI 0xdd8
+#define rOFDM_SIGReport 0xddc
+
+#define rTxAGC_Rate18_06 0xe00
+#define rTxAGC_Rate54_24 0xe04
+#define rTxAGC_CCK_Mcs32 0xe08
+#define rTxAGC_Mcs03_Mcs00 0xe10
+#define rTxAGC_Mcs07_Mcs04 0xe14
+#define rTxAGC_Mcs11_Mcs08 0xe18
+#define rTxAGC_Mcs15_Mcs12 0xe1c
+
+
+#define rZebra1_HSSIEnable 0x0
+#define rZebra1_TRxEnable1 0x1
+#define rZebra1_TRxEnable2 0x2
+#define rZebra1_AGC 0x4
+#define rZebra1_ChargePump 0x5
+#define rZebra1_Channel 0x7
+#define rZebra1_TxGain 0x8
+#define rZebra1_TxLPF 0x9
+#define rZebra1_RxLPF 0xb
+#define rZebra1_RxHPFCorner 0xc
+
+#define rGlobalCtrl 0
+#define rRTL8256_TxLPF 19
+#define rRTL8256_RxLPF 11
+
+#define rRTL8258_TxLPF 0x11
+#define rRTL8258_RxLPF 0x13
+#define rRTL8258_RSSILPF 0xa
+
+#define bBBResetB 0x100
+#define bGlobalResetB 0x200
+#define bOFDMTxStart 0x4
+#define bCCKTxStart 0x8
+#define bCRC32Debug 0x100
+#define bPMACLoopback 0x10
+#define bTxLSIG 0xffffff
+#define bOFDMTxRate 0xf
+#define bOFDMTxReserved 0x10
+#define bOFDMTxLength 0x1ffe0
+#define bOFDMTxParity 0x20000
+#define bTxHTSIG1 0xffffff
+#define bTxHTMCSRate 0x7f
+#define bTxHTBW 0x80
+#define bTxHTLength 0xffff00
+#define bTxHTSIG2 0xffffff
+#define bTxHTSmoothing 0x1
+#define bTxHTSounding 0x2
+#define bTxHTReserved 0x4
+#define bTxHTAggreation 0x8
+#define bTxHTSTBC 0x30
+#define bTxHTAdvanceCoding 0x40
+#define bTxHTShortGI 0x80
+#define bTxHTNumberHT_LTF 0x300
+#define bTxHTCRC8 0x3fc00
+#define bCounterReset 0x10000
+#define bNumOfOFDMTx 0xffff
+#define bNumOfCCKTx 0xffff0000
+#define bTxIdleInterval 0xffff
+#define bOFDMService 0xffff0000
+#define bTxMACHeader 0xffffffff
+#define bTxDataInit 0xff
+#define bTxHTMode 0x100
+#define bTxDataType 0x30000
+#define bTxRandomSeed 0xffffffff
+#define bCCKTxPreamble 0x1
+#define bCCKTxSFD 0xffff0000
+#define bCCKTxSIG 0xff
+#define bCCKTxService 0xff00
+#define bCCKLengthExt 0x8000
+#define bCCKTxLength 0xffff0000
+#define bCCKTxCRC16 0xffff
+#define bCCKTxStatus 0x1
+#define bOFDMTxStatus 0x2
+
+#define bRFMOD 0x1
+#define bJapanMode 0x2
+#define bCCKTxSC 0x30
+#define bCCKEn 0x1000000
+#define bOFDMEn 0x2000000
+#define bOFDMRxADCPhase 0x10000
+#define bOFDMTxDACPhase 0x40000
+#define bXATxAGC 0x3f
+#define bXBTxAGC 0xf00
+#define bXCTxAGC 0xf000
+#define bXDTxAGC 0xf0000
+#define bPAStart 0xf0000000
+#define bTRStart 0x00f00000
+#define bRFStart 0x0000f000
+#define bBBStart 0x000000f0
+#define bBBCCKStart 0x0000000f
+#define bPAEnd 0xf
+#define bTREnd 0x0f000000
+#define bRFEnd 0x000f0000
+#define bCCAMask 0x000000f0
+#define bR2RCCAMask 0x00000f00
+#define bHSSI_R2TDelay 0xf8000000
+#define bHSSI_T2RDelay 0xf80000
+#define bContTxHSSI 0x400
+#define bIGFromCCK 0x200
+#define bAGCAddress 0x3f
+#define bRxHPTx 0x7000
+#define bRxHPT2R 0x38000
+#define bRxHPCCKIni 0xc0000
+#define bAGCTxCode 0xc00000
+#define bAGCRxCode 0x300000
+#define b3WireDataLength 0x800
+#define b3WireAddressLength 0x400
+#define b3WireRFPowerDown 0x1
+#define b5GPAPEPolarity 0x40000000
+#define b2GPAPEPolarity 0x80000000
+#define bRFSW_TxDefaultAnt 0x3
+#define bRFSW_TxOptionAnt 0x30
+#define bRFSW_RxDefaultAnt 0x300
+#define bRFSW_RxOptionAnt 0x3000
+#define bRFSI_3WireData 0x1
+#define bRFSI_3WireClock 0x2
+#define bRFSI_3WireLoad 0x4
+#define bRFSI_3WireRW 0x8
+#define bRFSI_3Wire 0xf
+#define bRFSI_RFENV 0x10
+#define bRFSI_TRSW 0x20
+#define bRFSI_TRSWB 0x40
+#define bRFSI_ANTSW 0x100
+#define bRFSI_ANTSWB 0x200
+#define bRFSI_PAPE 0x400
+#define bRFSI_PAPE5G 0x800
+#define bBandSelect 0x1
+#define bHTSIG2_GI 0x80
+#define bHTSIG2_Smoothing 0x01
+#define bHTSIG2_Sounding 0x02
+#define bHTSIG2_Aggreaton 0x08
+#define bHTSIG2_STBC 0x30
+#define bHTSIG2_AdvCoding 0x40
+#define bHTSIG2_NumOfHTLTF 0x300
+#define bHTSIG2_CRC8 0x3fc
+#define bHTSIG1_MCS 0x7f
+#define bHTSIG1_BandWidth 0x80
+#define bHTSIG1_HTLength 0xffff
+#define bLSIG_Rate 0xf
+#define bLSIG_Reserved 0x10
+#define bLSIG_Length 0x1fffe
+#define bLSIG_Parity 0x20
+#define bCCKRxPhase 0x4
+#define bLSSIReadAddress 0x3f000000
+#define bLSSIReadEdge 0x80000000
+#define bLSSIReadBackData 0xfff
+#define bLSSIReadOKFlag 0x1000
+#define bCCKSampleRate 0x8
+
+#define bRegulator0Standby 0x1
+#define bRegulatorPLLStandby 0x2
+#define bRegulator1Standby 0x4
+#define bPLLPowerUp 0x8
+#define bDPLLPowerUp 0x10
+#define bDA10PowerUp 0x20
+#define bAD7PowerUp 0x200
+#define bDA6PowerUp 0x2000
+#define bXtalPowerUp 0x4000
+#define b40MDClkPowerUP 0x8000
+#define bDA6DebugMode 0x20000
+#define bDA6Swing 0x380000
+#define bADClkPhase 0x4000000
+#define b80MClkDelay 0x18000000
+#define bAFEWatchDogEnable 0x20000000
+#define bXtalCap 0x0f000000
+#define bXtalCap01 0xc0000000
+#define bXtalCap23 0x3
+#define bXtalCap92x 0x0f000000
+#define bIntDifClkEnable 0x400
+#define bExtSigClkEnable 0x800
+#define bBandgapMbiasPowerUp 0x10000
+#define bAD11SHGain 0xc0000
+#define bAD11InputRange 0x700000
+#define bAD11OPCurrent 0x3800000
+#define bIPathLoopback 0x4000000
+#define bQPathLoopback 0x8000000
+#define bAFELoopback 0x10000000
+#define bDA10Swing 0x7e0
+#define bDA10Reverse 0x800
+#define bDAClkSource 0x1000
+#define bAD7InputRange 0x6000
+#define bAD7Gain 0x38000
+#define bAD7OutputCMMode 0x40000
+#define bAD7InputCMMode 0x380000
+#define bAD7Current 0xc00000
+#define bRegulatorAdjust 0x7000000
+#define bAD11PowerUpAtTx 0x1
+#define bDA10PSAtTx 0x10
+#define bAD11PowerUpAtRx 0x100
+#define bDA10PSAtRx 0x1000
+
+#define bCCKRxAGCFormat 0x200
+
+#define bPSDFFTSamplepPoint 0xc000
+#define bPSDAverageNum 0x3000
+#define bIQPathControl 0xc00
+#define bPSDFreq 0x3ff
+#define bPSDAntennaPath 0x30
+#define bPSDIQSwitch 0x40
+#define bPSDRxTrigger 0x400000
+#define bPSDTxTrigger 0x80000000
+#define bPSDSineToneScale 0x7f000000
+#define bPSDReport 0xffff
+
+#define bOFDMTxSC 0x30000000
+#define bCCKTxOn 0x1
+#define bOFDMTxOn 0x2
+#define bDebugPage 0xfff
+#define bDebugItem 0xff
+#define bAntL 0x10
+#define bAntNonHT 0x100
+#define bAntHT1 0x1000
+#define bAntHT2 0x10000
+#define bAntHT1S1 0x100000
+#define bAntNonHTS1 0x1000000
+
+#define bCCKBBMode 0x3
+#define bCCKTxPowerSaving 0x80
+#define bCCKRxPowerSaving 0x40
+#define bCCKSideBand 0x10
+#define bCCKScramble 0x8
+#define bCCKAntDiversity 0x8000
+#define bCCKCarrierRecovery 0x4000
+#define bCCKTxRate 0x3000
+#define bCCKDCCancel 0x0800
+#define bCCKISICancel 0x0400
+#define bCCKMatchFilter 0x0200
+#define bCCKEqualizer 0x0100
+#define bCCKPreambleDetect 0x800000
+#define bCCKFastFalseCCA 0x400000
+#define bCCKChEstStart 0x300000
+#define bCCKCCACount 0x080000
+#define bCCKcs_lim 0x070000
+#define bCCKBistMode 0x80000000
+#define bCCKCCAMask 0x40000000
+#define bCCKTxDACPhase 0x4
+#define bCCKRxADCPhase 0x20000000
+#define bCCKr_cp_mode0 0x0100
+#define bCCKTxDCOffset 0xf0
+#define bCCKRxDCOffset 0xf
+#define bCCKCCAMode 0xc000
+#define bCCKFalseCS_lim 0x3f00
+#define bCCKCS_ratio 0xc00000
+#define bCCKCorgBit_sel 0x300000
+#define bCCKPD_lim 0x0f0000
+#define bCCKNewCCA 0x80000000
+#define bCCKRxHPofIG 0x8000
+#define bCCKRxIG 0x7f00
+#define bCCKLNAPolarity 0x800000
+#define bCCKRx1stGain 0x7f0000
+#define bCCKRFExtend 0x20000000
+#define bCCKRxAGCSatLevel 0x1f000000
+#define bCCKRxAGCSatCount 0xe0
+#define bCCKRxRFSettle 0x1f
+#define bCCKFixedRxAGC 0x8000
+#define bCCKAntennaPolarity 0x2000
+#define bCCKTxFilterType 0x0c00
+#define bCCKRxAGCReportType 0x0300
+#define bCCKRxDAGCEn 0x80000000
+#define bCCKRxDAGCPeriod 0x20000000
+#define bCCKRxDAGCSatLevel 0x1f000000
+#define bCCKTimingRecovery 0x800000
+#define bCCKTxC0 0x3f0000
+#define bCCKTxC1 0x3f000000
+#define bCCKTxC2 0x3f
+#define bCCKTxC3 0x3f00
+#define bCCKTxC4 0x3f0000
+#define bCCKTxC5 0x3f000000
+#define bCCKTxC6 0x3f
+#define bCCKTxC7 0x3f00
+#define bCCKDebugPort 0xff0000
+#define bCCKDACDebug 0x0f000000
+#define bCCKFalseAlarmEnable 0x8000
+#define bCCKFalseAlarmRead 0x4000
+#define bCCKTRSSI 0x7f
+#define bCCKRxAGCReport 0xfe
+#define bCCKRxReport_AntSel 0x80000000
+#define bCCKRxReport_MFOff 0x40000000
+#define bCCKRxRxReport_SQLoss 0x20000000
+#define bCCKRxReport_Pktloss 0x10000000
+#define bCCKRxReport_Lockedbit 0x08000000
+#define bCCKRxReport_RateError 0x04000000
+#define bCCKRxReport_RxRate 0x03000000
+#define bCCKRxFACounterLower 0xff
+#define bCCKRxFACounterUpper 0xff000000
+#define bCCKRxHPAGCStart 0xe000
+#define bCCKRxHPAGCFinal 0x1c00
+
+#define bCCKRxFalseAlarmEnable 0x8000
+#define bCCKFACounterFreeze 0x4000
+
+#define bCCKTxPathSel 0x10000000
+#define bCCKDefaultRxPath 0xc000000
+#define bCCKOptionRxPath 0x3000000
+
+#define bNumOfSTF 0x3
+#define bShift_L 0xc0
+#define bGI_TH 0xc
+#define bRxPathA 0x1
+#define bRxPathB 0x2
+#define bRxPathC 0x4
+#define bRxPathD 0x8
+#define bTxPathA 0x1
+#define bTxPathB 0x2
+#define bTxPathC 0x4
+#define bTxPathD 0x8
+#define bTRSSIFreq 0x200
+#define bADCBackoff 0x3000
+#define bDFIRBackoff 0xc000
+#define bTRSSILatchPhase 0x10000
+#define bRxIDCOffset 0xff
+#define bRxQDCOffset 0xff00
+#define bRxDFIRMode 0x1800000
+#define bRxDCNFType 0xe000000
+#define bRXIQImb_A 0x3ff
+#define bRXIQImb_B 0xfc00
+#define bRXIQImb_C 0x3f0000
+#define bRXIQImb_D 0xffc00000
+#define bDC_dc_Notch 0x60000
+#define bRxNBINotch 0x1f000000
+#define bPD_TH 0xf
+#define bPD_TH_Opt2 0xc000
+#define bPWED_TH 0x700
+#define bIfMF_Win_L 0x800
+#define bPD_Option 0x1000
+#define bMF_Win_L 0xe000
+#define bBW_Search_L 0x30000
+#define bwin_enh_L 0xc0000
+#define bBW_TH 0x700000
+#define bED_TH2 0x3800000
+#define bBW_option 0x4000000
+#define bRatio_TH 0x18000000
+#define bWindow_L 0xe0000000
+#define bSBD_Option 0x1
+#define bFrame_TH 0x1c
+#define bFS_Option 0x60
+#define bDC_Slope_check 0x80
+#define bFGuard_Counter_DC_L 0xe00
+#define bFrame_Weight_Short 0x7000
+#define bSub_Tune 0xe00000
+#define bFrame_DC_Length 0xe000000
+#define bSBD_start_offset 0x30000000
+#define bFrame_TH_2 0x7
+#define bFrame_GI2_TH 0x38
+#define bGI2_Sync_en 0x40
+#define bSarch_Short_Early 0x300
+#define bSarch_Short_Late 0xc00
+#define bSarch_GI2_Late 0x70000
+#define bCFOAntSum 0x1
+#define bCFOAcc 0x2
+#define bCFOStartOffset 0xc
+#define bCFOLookBack 0x70
+#define bCFOSumWeight 0x80
+#define bDAGCEnable 0x10000
+#define bTXIQImb_A 0x3ff
+#define bTXIQImb_B 0xfc00
+#define bTXIQImb_C 0x3f0000
+#define bTXIQImb_D 0xffc00000
+#define bTxIDCOffset 0xff
+#define bTxQDCOffset 0xff00
+#define bTxDFIRMode 0x10000
+#define bTxPesudoNoiseOn 0x4000000
+#define bTxPesudoNoise_A 0xff
+#define bTxPesudoNoise_B 0xff00
+#define bTxPesudoNoise_C 0xff0000
+#define bTxPesudoNoise_D 0xff000000
+#define bCCADropOption 0x20000
+#define bCCADropThres 0xfff00000
+#define bEDCCA_H 0xf
+#define bEDCCA_L 0xf0
+#define bLambda_ED 0x300
+#define bRxInitialGain 0x7f
+#define bRxAntDivEn 0x80
+#define bRxAGCAddressForLNA 0x7f00
+#define bRxHighPowerFlow 0x8000
+#define bRxAGCFreezeThres 0xc0000
+#define bRxFreezeStep_AGC1 0x300000
+#define bRxFreezeStep_AGC2 0xc00000
+#define bRxFreezeStep_AGC3 0x3000000
+#define bRxFreezeStep_AGC0 0xc000000
+#define bRxRssi_Cmp_En 0x10000000
+#define bRxQuickAGCEn 0x20000000
+#define bRxAGCFreezeThresMode 0x40000000
+#define bRxOverFlowCheckType 0x80000000
+#define bRxAGCShift 0x7f
+#define bTRSW_Tri_Only 0x80
+#define bPowerThres 0x300
+#define bRxAGCEn 0x1
+#define bRxAGCTogetherEn 0x2
+#define bRxAGCMin 0x4
+#define bRxHP_Ini 0x7
+#define bRxHP_TRLNA 0x70
+#define bRxHP_RSSI 0x700
+#define bRxHP_BBP1 0x7000
+#define bRxHP_BBP2 0x70000
+#define bRxHP_BBP3 0x700000
+#define bRSSI_H 0x7f0000
+#define bRSSI_Gen 0x7f000000
+#define bRxSettle_TRSW 0x7
+#define bRxSettle_LNA 0x38
+#define bRxSettle_RSSI 0x1c0
+#define bRxSettle_BBP 0xe00
+#define bRxSettle_RxHP 0x7000
+#define bRxSettle_AntSW_RSSI 0x38000
+#define bRxSettle_AntSW 0xc0000
+#define bRxProcessTime_DAGC 0x300000
+#define bRxSettle_HSSI 0x400000
+#define bRxProcessTime_BBPPW 0x800000
+#define bRxAntennaPowerShift 0x3000000
+#define bRSSITableSelect 0xc000000
+#define bRxHP_Final 0x7000000
+#define bRxHTSettle_BBP 0x7
+#define bRxHTSettle_HSSI 0x8
+#define bRxHTSettle_RxHP 0x70
+#define bRxHTSettle_BBPPW 0x80
+#define bRxHTSettle_Idle 0x300
+#define bRxHTSettle_Reserved 0x1c00
+#define bRxHTRxHPEn 0x8000
+#define bRxHTAGCFreezeThres 0x30000
+#define bRxHTAGCTogetherEn 0x40000
+#define bRxHTAGCMin 0x80000
+#define bRxHTAGCEn 0x100000
+#define bRxHTDAGCEn 0x200000
+#define bRxHTRxHP_BBP 0x1c00000
+#define bRxHTRxHP_Final 0xe0000000
+#define bRxPWRatioTH 0x3
+#define bRxPWRatioEn 0x4
+#define bRxMFHold 0x3800
+#define bRxPD_Delay_TH1 0x38
+#define bRxPD_Delay_TH2 0x1c0
+#define bRxPD_DC_COUNT_MAX 0x600
+#define bRxPD_Delay_TH 0x8000
+#define bRxProcess_Delay 0xf0000
+#define bRxSearchrange_GI2_Early 0x700000
+#define bRxFrame_Guard_Counter_L 0x3800000
+#define bRxSGI_Guard_L 0xc000000
+#define bRxSGI_Search_L 0x30000000
+#define bRxSGI_TH 0xc0000000
+#define bDFSCnt0 0xff
+#define bDFSCnt1 0xff00
+#define bDFSFlag 0xf0000
+
+#define bMFWeightSum 0x300000
+#define bMinIdxTH 0x7f000000
+
+#define bDAFormat 0x40000
+
+#define bTxChEmuEnable 0x01000000
+
+#define bTRSWIsolation_A 0x7f
+#define bTRSWIsolation_B 0x7f00
+#define bTRSWIsolation_C 0x7f0000
+#define bTRSWIsolation_D 0x7f000000
+
+#define bExtLNAGain 0x7c00
+
+#define bSTBCEn 0x4
+#define bAntennaMapping 0x10
+#define bNss 0x20
+#define bCFOAntSumD 0x200
+#define bPHYCounterReset 0x8000000
+#define bCFOReportGet 0x4000000
+#define bOFDMContinueTx 0x10000000
+#define bOFDMSingleCarrier 0x20000000
+#define bOFDMSingleTone 0x40000000
+#define bHTDetect 0x100
+#define bCFOEn 0x10000
+#define bCFOValue 0xfff00000
+#define bSigTone_Re 0x3f
+#define bSigTone_Im 0x7f00
+#define bCounter_CCA 0xffff
+#define bCounter_ParityFail 0xffff0000
+#define bCounter_RateIllegal 0xffff
+#define bCounter_CRC8Fail 0xffff0000
+#define bCounter_MCSNoSupport 0xffff
+#define bCounter_FastSync 0xffff
+#define bShortCFO 0xfff
+#define bShortCFOTLength 12
+#define bShortCFOFLength 11
+#define bLongCFO 0x7ff
+#define bLongCFOTLength 11
+#define bLongCFOFLength 11
+#define bTailCFO 0x1fff
+#define bTailCFOTLength 13
+#define bTailCFOFLength 12
+
+#define bmax_en_pwdB 0xffff
+#define bCC_power_dB 0xffff0000
+#define bnoise_pwdB 0xffff
+#define bPowerMeasTLength 10
+#define bPowerMeasFLength 3
+#define bRx_HT_BW 0x1
+#define bRxSC 0x6
+#define bRx_HT 0x8
+
+#define bNB_intf_det_on 0x1
+#define bIntf_win_len_cfg 0x30
+#define bNB_Intf_TH_cfg 0x1c0
+
+#define bRFGain 0x3f
+#define bTableSel 0x40
+#define bTRSW 0x80
+
+#define bRxSNR_A 0xff
+#define bRxSNR_B 0xff00
+#define bRxSNR_C 0xff0000
+#define bRxSNR_D 0xff000000
+#define bSNREVMTLength 8
+#define bSNREVMFLength 1
+
+#define bCSI1st 0xff
+#define bCSI2nd 0xff00
+#define bRxEVM1st 0xff0000
+#define bRxEVM2nd 0xff000000
+
+#define bSIGEVM 0xff
+#define bPWDB 0xff00
+#define bSGIEN 0x10000
+
+#define bSFactorQAM1 0xf
+#define bSFactorQAM2 0xf0
+#define bSFactorQAM3 0xf00
+#define bSFactorQAM4 0xf000
+#define bSFactorQAM5 0xf0000
+#define bSFactorQAM6 0xf0000
+#define bSFactorQAM7 0xf00000
+#define bSFactorQAM8 0xf000000
+#define bSFactorQAM9 0xf0000000
+#define bCSIScheme 0x100000
+
+#define bNoiseLvlTopSet 0x3
+#define bChSmooth 0x4
+#define bChSmoothCfg1 0x38
+#define bChSmoothCfg2 0x1c0
+#define bChSmoothCfg3 0xe00
+#define bChSmoothCfg4 0x7000
+#define bMRCMode 0x800000
+#define bTHEVMCfg 0x7000000
+
+#define bLoopFitType 0x1
+#define bUpdCFO 0x40
+#define bUpdCFOOffData 0x80
+#define bAdvUpdCFO 0x100
+#define bAdvTimeCtrl 0x800
+#define bUpdClko 0x1000
+#define bFC 0x6000
+#define bTrackingMode 0x8000
+#define bPhCmpEnable 0x10000
+#define bUpdClkoLTF 0x20000
+#define bComChCFO 0x40000
+#define bCSIEstiMode 0x80000
+#define bAdvUpdEqz 0x100000
+#define bUChCfg 0x7000000
+#define bUpdEqz 0x8000000
+
+#define bTxAGCRate18_06 0x7f7f7f7f
+#define bTxAGCRate54_24 0x7f7f7f7f
+#define bTxAGCRateMCS32 0x7f
+#define bTxAGCRateCCK 0x7f00
+#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f
+#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f
+#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f
+#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f
+
+
+#define bRxPesudoNoiseOn 0x20000000
+#define bRxPesudoNoise_A 0xff
+#define bRxPesudoNoise_B 0xff00
+#define bRxPesudoNoise_C 0xff0000
+#define bRxPesudoNoise_D 0xff000000
+#define bPesudoNoiseState_A 0xffff
+#define bPesudoNoiseState_B 0xffff0000
+#define bPesudoNoiseState_C 0xffff
+#define bPesudoNoiseState_D 0xffff0000
+
+#define bZebra1_HSSIEnable 0x8
+#define bZebra1_TRxControl 0xc00
+#define bZebra1_TRxGainSetting 0x07f
+#define bZebra1_RxCorner 0xc00
+#define bZebra1_TxChargePump 0x38
+#define bZebra1_RxChargePump 0x7
+#define bZebra1_ChannelNum 0xf80
+#define bZebra1_TxLPFBW 0x400
+#define bZebra1_RxLPFBW 0x600
+
+#define bRTL8256RegModeCtrl1 0x100
+#define bRTL8256RegModeCtrl0 0x40
+#define bRTL8256_TxLPFBW 0x18
+#define bRTL8256_RxLPFBW 0x600
+
+#define bRTL8258_TxLPFBW 0xc
+#define bRTL8258_RxLPFBW 0xc00
+#define bRTL8258_RSSILPFBW 0xc0
+
+#define bByte0 0x1
+#define bByte1 0x2
+#define bByte2 0x4
+#define bByte3 0x8
+#define bWord0 0x3
+#define bWord1 0xc
+#define bDWord 0xf
+
+#define bMaskByte0 0xff
+#define bMaskByte1 0xff00
+#define bMaskByte2 0xff0000
+#define bMaskByte3 0xff000000
+#define bMaskHWord 0xffff0000
+#define bMaskLWord 0x0000ffff
+#define bMaskDWord 0xffffffff
+
+#define bMask12Bits 0xfff
+
+#define bEnable 0x1
+#define bDisable 0x0
+
+#define LeftAntenna 0x0
+#define RightAntenna 0x1
+
+#define tCheckTxStatus 500
+#define tUpdateRxCounter 100
+
+#define rateCCK 0
+#define rateOFDM 1
+#define rateHT 2
+
+#define bPMAC_End 0x1ff
+#define bFPGAPHY0_End 0x8ff
+#define bFPGAPHY1_End 0x9ff
+#define bCCKPHY0_End 0xaff
+#define bOFDMPHY0_End 0xcff
+#define bOFDMPHY1_End 0xdff
+
+
+#define bPMACControl 0x0
+#define bWMACControl 0x1
+#define bWNICControl 0x2
+
+#define PathA 0x0
+#define PathB 0x1
+#define PathC 0x2
+#define PathD 0x3
+
+#define rRTL8256RxMixerPole 0xb
+#define bZebraRxMixerPole 0x6
+#define rRTL8256TxBBOPBias 0x9
+#define bRTL8256TxBBOPBias 0x400
+#define rRTL8256TxBBBW 19
+#define bRTL8256TxBBBW 0x18
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h b/drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h
new file mode 100644
index 000000000..03eee3d05
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/r819xE_phyreg.h
@@ -0,0 +1,908 @@
+#ifndef _R819XU_PHYREG_H
+#define _R819XU_PHYREG_H
+
+
+#define RF_DATA 0x1d4 // FW will write RF data in the register.
+
+//Register //duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF
+//page 1
+#define rPMAC_Reset 0x100
+#define rPMAC_TxStart 0x104
+#define rPMAC_TxLegacySIG 0x108
+#define rPMAC_TxHTSIG1 0x10c
+#define rPMAC_TxHTSIG2 0x110
+#define rPMAC_PHYDebug 0x114
+#define rPMAC_TxPacketNum 0x118
+#define rPMAC_TxIdle 0x11c
+#define rPMAC_TxMACHeader0 0x120
+#define rPMAC_TxMACHeader1 0x124
+#define rPMAC_TxMACHeader2 0x128
+#define rPMAC_TxMACHeader3 0x12c
+#define rPMAC_TxMACHeader4 0x130
+#define rPMAC_TxMACHeader5 0x134
+#define rPMAC_TxDataType 0x138
+#define rPMAC_TxRandomSeed 0x13c
+#define rPMAC_CCKPLCPPreamble 0x140
+#define rPMAC_CCKPLCPHeader 0x144
+#define rPMAC_CCKCRC16 0x148
+#define rPMAC_OFDMRxCRC32OK 0x170
+#define rPMAC_OFDMRxCRC32Er 0x174
+#define rPMAC_OFDMRxParityEr 0x178
+#define rPMAC_OFDMRxCRC8Er 0x17c
+#define rPMAC_CCKCRxRC16Er 0x180
+#define rPMAC_CCKCRxRC32Er 0x184
+#define rPMAC_CCKCRxRC32OK 0x188
+#define rPMAC_TxStatus 0x18c
+
+//90P
+#define MCS_TXAGC 0x340 // MCS AGC
+#define CCK_TXAGC 0x348 // CCK AGC
+
+#define MacBlkCtrl 0x403 // Mac block on/off control register
+
+//page8
+#define rFPGA0_RFMOD 0x800 //RF mode & CCK TxSC
+#define rFPGA0_TxInfo 0x804
+#define rFPGA0_PSDFunction 0x808
+#define rFPGA0_TxGainStage 0x80c
+#define rFPGA0_RFTiming1 0x810
+#define rFPGA0_RFTiming2 0x814
+//#define rFPGA0_XC_RFTiming 0x818
+//#define rFPGA0_XD_RFTiming 0x81c
+#define rFPGA0_XA_HSSIParameter1 0x820
+#define rFPGA0_XA_HSSIParameter2 0x824
+#define rFPGA0_XB_HSSIParameter1 0x828
+#define rFPGA0_XB_HSSIParameter2 0x82c
+#define rFPGA0_XC_HSSIParameter1 0x830
+#define rFPGA0_XC_HSSIParameter2 0x834
+#define rFPGA0_XD_HSSIParameter1 0x838
+#define rFPGA0_XD_HSSIParameter2 0x83c
+#define rFPGA0_XA_LSSIParameter 0x840
+#define rFPGA0_XB_LSSIParameter 0x844
+#define rFPGA0_XC_LSSIParameter 0x848
+#define rFPGA0_XD_LSSIParameter 0x84c
+#define rFPGA0_RFWakeUpParameter 0x850
+#define rFPGA0_RFSleepUpParameter 0x854
+#define rFPGA0_XAB_SwitchControl 0x858
+#define rFPGA0_XCD_SwitchControl 0x85c
+#define rFPGA0_XA_RFInterfaceOE 0x860
+#define rFPGA0_XB_RFInterfaceOE 0x864
+#define rFPGA0_XC_RFInterfaceOE 0x868
+#define rFPGA0_XD_RFInterfaceOE 0x86c
+#define rFPGA0_XAB_RFInterfaceSW 0x870
+#define rFPGA0_XCD_RFInterfaceSW 0x874
+#define rFPGA0_XAB_RFParameter 0x878
+#define rFPGA0_XCD_RFParameter 0x87c
+#define rFPGA0_AnalogParameter1 0x880
+#define rFPGA0_AnalogParameter2 0x884
+#define rFPGA0_AnalogParameter3 0x888
+#define rFPGA0_AnalogParameter4 0x88c
+#define rFPGA0_XA_LSSIReadBack 0x8a0
+#define rFPGA0_XB_LSSIReadBack 0x8a4
+#define rFPGA0_XC_LSSIReadBack 0x8a8
+#define rFPGA0_XD_LSSIReadBack 0x8ac
+#define rFPGA0_PSDReport 0x8b4
+#define rFPGA0_XAB_RFInterfaceRB 0x8e0
+#define rFPGA0_XCD_RFInterfaceRB 0x8e4
+
+/* Page 9 - RF mode & OFDM TxSC */
+#define rFPGA1_RFMOD 0x900
+#define rFPGA1_TxBlock 0x904
+#define rFPGA1_DebugSelect 0x908
+#define rFPGA1_TxInfo 0x90c
+
+/* Page a */
+#define rCCK0_System 0xa00
+#define rCCK0_AFESetting 0xa04
+#define rCCK0_CCA 0xa08
+/* AGC default value, saturation level */
+#define rCCK0_RxAGC1 0xa0c
+/* AGC & DAGC */
+#define rCCK0_RxAGC2 0xa10
+#define rCCK0_RxHP 0xa14
+/* Timing recovery & channel estimation threshold */
+#define rCCK0_DSPParameter1 0xa18
+/* SQ threshold */
+#define rCCK0_DSPParameter2 0xa1c
+#define rCCK0_TxFilter1 0xa20
+#define rCCK0_TxFilter2 0xa24
+/* Debug port and TX filter 3 */
+#define rCCK0_DebugPort 0xa28
+#define rCCK0_FalseAlarmReport 0xa2c
+#define rCCK0_TRSSIReport 0xa50
+#define rCCK0_RxReport 0xa54
+#define rCCK0_FACounterLower 0xa5c
+#define rCCK0_FACounterUpper 0xa58
+
+/* Page c */
+#define rOFDM0_LSTF 0xc00
+#define rOFDM0_TRxPathEnable 0xc04
+#define rOFDM0_TRMuxPar 0xc08
+#define rOFDM0_TRSWIsolation 0xc0c
+/* RxIQ DC offset, Rx digital filter, DC notch filter */
+#define rOFDM0_XARxAFE 0xc10
+/* RxIQ imblance matrix */
+#define rOFDM0_XARxIQImbalance 0xc14
+#define rOFDM0_XBRxAFE 0xc18
+#define rOFDM0_XBRxIQImbalance 0xc1c
+#define rOFDM0_XCRxAFE 0xc20
+#define rOFDM0_XCRxIQImbalance 0xc24
+#define rOFDM0_XDRxAFE 0xc28
+#define rOFDM0_XDRxIQImbalance 0xc2c
+/* PD, BW & SBD */
+#define rOFDM0_RxDetector1 0xc30
+/* SBD */
+#define rOFDM0_RxDetector2 0xc34
+/* Frame Sync */
+#define rOFDM0_RxDetector3 0xc38
+/* PD, SBD, Frame Sync & Short-GI */
+#define rOFDM0_RxDetector4 0xc3c
+/* Rx Sync Path */
+#define rOFDM0_RxDSP 0xc40
+/* CFO & DAGC */
+#define rOFDM0_CFOandDAGC 0xc44
+/* CCA Drop threshold */
+#define rOFDM0_CCADropThreshold 0xc48
+/* Energy CCA */
+#define rOFDM0_ECCAThreshold 0xc4c
+#define rOFDM0_XAAGCCore1 0xc50
+#define rOFDM0_XAAGCCore2 0xc54
+#define rOFDM0_XBAGCCore1 0xc58
+#define rOFDM0_XBAGCCore2 0xc5c
+#define rOFDM0_XCAGCCore1 0xc60
+#define rOFDM0_XCAGCCore2 0xc64
+#define rOFDM0_XDAGCCore1 0xc68
+#define rOFDM0_XDAGCCore2 0xc6c
+#define rOFDM0_AGCParameter1 0xc70
+#define rOFDM0_AGCParameter2 0xc74
+#define rOFDM0_AGCRSSITable 0xc78
+#define rOFDM0_HTSTFAGC 0xc7c
+#define rOFDM0_XATxIQImbalance 0xc80
+#define rOFDM0_XATxAFE 0xc84
+#define rOFDM0_XBTxIQImbalance 0xc88
+#define rOFDM0_XBTxAFE 0xc8c
+#define rOFDM0_XCTxIQImbalance 0xc90
+#define rOFDM0_XCTxAFE 0xc94
+#define rOFDM0_XDTxIQImbalance 0xc98
+#define rOFDM0_XDTxAFE 0xc9c
+#define rOFDM0_RxHPParameter 0xce0
+#define rOFDM0_TxPseudoNoiseWgt 0xce4
+#define rOFDM0_FrameSync 0xcf0
+#define rOFDM0_DFSReport 0xcf4
+#define rOFDM0_TxCoeff1 0xca4
+#define rOFDM0_TxCoeff2 0xca8
+#define rOFDM0_TxCoeff3 0xcac
+#define rOFDM0_TxCoeff4 0xcb0
+#define rOFDM0_TxCoeff5 0xcb4
+#define rOFDM0_TxCoeff6 0xcb8
+
+
+/* Page d */
+#define rOFDM1_LSTF 0xd00
+#define rOFDM1_TRxPathEnable 0xd04
+#define rOFDM1_CFO 0xd08
+#define rOFDM1_CSI1 0xd10
+#define rOFDM1_SBD 0xd14
+#define rOFDM1_CSI2 0xd18
+#define rOFDM1_CFOTracking 0xd2c
+#define rOFDM1_TRxMesaure1 0xd34
+#define rOFDM1_IntfDet 0xd3c
+#define rOFDM1_PseudoNoiseStateAB 0xd50
+#define rOFDM1_PseudoNoiseStateCD 0xd54
+#define rOFDM1_RxPseudoNoiseWgt 0xd58
+/* cca, parity fail */
+#define rOFDM_PHYCounter1 0xda0
+/* rate illegal, crc8 fail */
+#define rOFDM_PHYCounter2 0xda4
+/* MCS not supported */
+#define rOFDM_PHYCounter3 0xda8
+#define rOFDM_ShortCFOAB 0xdac
+#define rOFDM_ShortCFOCD 0xdb0
+#define rOFDM_LongCFOAB 0xdb4
+#define rOFDM_LongCFOCD 0xdb8
+#define rOFDM_TailCFOAB 0xdbc
+#define rOFDM_TailCFOCD 0xdc0
+#define rOFDM_PWMeasure1 0xdc4
+#define rOFDM_PWMeasure2 0xdc8
+#define rOFDM_BWReport 0xdcc
+#define rOFDM_AGCReport 0xdd0
+#define rOFDM_RxSNR 0xdd4
+#define rOFDM_RxEVMCSI 0xdd8
+#define rOFDM_SIGReport 0xddc
+
+/* Page e */
+#define rTxAGC_Rate18_06 0xe00
+#define rTxAGC_Rate54_24 0xe04
+#define rTxAGC_CCK_Mcs32 0xe08
+#define rTxAGC_Mcs03_Mcs00 0xe10
+#define rTxAGC_Mcs07_Mcs04 0xe14
+#define rTxAGC_Mcs11_Mcs08 0xe18
+#define rTxAGC_Mcs15_Mcs12 0xe1c
+
+
+/* RF Zebra 1 */
+#define rZebra1_HSSIEnable 0x0
+#define rZebra1_TRxEnable1 0x1
+#define rZebra1_TRxEnable2 0x2
+#define rZebra1_AGC 0x4
+#define rZebra1_ChargePump 0x5
+#define rZebra1_Channel 0x7
+#define rZebra1_TxGain 0x8
+#define rZebra1_TxLPF 0x9
+#define rZebra1_RxLPF 0xb
+#define rZebra1_RxHPFCorner 0xc
+
+/* Zebra 4 */
+#define rGlobalCtrl 0
+#define rRTL8256_TxLPF 19
+#define rRTL8256_RxLPF 11
+
+/* RTL8258 */
+#define rRTL8258_TxLPF 0x11
+#define rRTL8258_RxLPF 0x13
+#define rRTL8258_RSSILPF 0xa
+
+/* Bit Mask */
+/* Page 1 */
+#define bBBResetB 0x100
+#define bGlobalResetB 0x200
+#define bOFDMTxStart 0x4
+#define bCCKTxStart 0x8
+#define bCRC32Debug 0x100
+#define bPMACLoopback 0x10
+#define bTxLSIG 0xffffff
+#define bOFDMTxRate 0xf
+#define bOFDMTxReserved 0x10
+#define bOFDMTxLength 0x1ffe0
+#define bOFDMTxParity 0x20000
+#define bTxHTSIG1 0xffffff
+#define bTxHTMCSRate 0x7f
+#define bTxHTBW 0x80
+#define bTxHTLength 0xffff00
+#define bTxHTSIG2 0xffffff
+#define bTxHTSmoothing 0x1
+#define bTxHTSounding 0x2
+#define bTxHTReserved 0x4
+#define bTxHTAggreation 0x8
+#define bTxHTSTBC 0x30
+#define bTxHTAdvanceCoding 0x40
+#define bTxHTShortGI 0x80
+#define bTxHTNumberHT_LTF 0x300
+#define bTxHTCRC8 0x3fc00
+#define bCounterReset 0x10000
+#define bNumOfOFDMTx 0xffff
+#define bNumOfCCKTx 0xffff0000
+#define bTxIdleInterval 0xffff
+#define bOFDMService 0xffff0000
+#define bTxMACHeader 0xffffffff
+#define bTxDataInit 0xff
+#define bTxHTMode 0x100
+#define bTxDataType 0x30000
+#define bTxRandomSeed 0xffffffff
+#define bCCKTxPreamble 0x1
+#define bCCKTxSFD 0xffff0000
+#define bCCKTxSIG 0xff
+#define bCCKTxService 0xff00
+#define bCCKLengthExt 0x8000
+#define bCCKTxLength 0xffff0000
+#define bCCKTxCRC16 0xffff
+#define bCCKTxStatus 0x1
+#define bOFDMTxStatus 0x2
+
+/* Page 8 */
+#define bRFMOD 0x1
+#define bJapanMode 0x2
+#define bCCKTxSC 0x30
+#define bCCKEn 0x1000000
+#define bOFDMEn 0x2000000
+#define bOFDMRxADCPhase 0x10000
+#define bOFDMTxDACPhase 0x40000
+#define bXATxAGC 0x3f
+#define bXBTxAGC 0xf00
+#define bXCTxAGC 0xf000
+#define bXDTxAGC 0xf0000
+#define bPAStart 0xf0000000
+#define bTRStart 0x00f00000
+#define bRFStart 0x0000f000
+#define bBBStart 0x000000f0
+#define bBBCCKStart 0x0000000f
+/* Reg x814 */
+#define bPAEnd 0xf
+#define bTREnd 0x0f000000
+#define bRFEnd 0x000f0000
+/* T2R */
+#define bCCAMask 0x000000f0
+#define bR2RCCAMask 0x00000f00
+#define bHSSI_R2TDelay 0xf8000000
+#define bHSSI_T2RDelay 0xf80000
+/* Channel gain at continue TX. */
+#define bContTxHSSI 0x400
+#define bIGFromCCK 0x200
+#define bAGCAddress 0x3f
+#define bRxHPTx 0x7000
+#define bRxHPT2R 0x38000
+#define bRxHPCCKIni 0xc0000
+#define bAGCTxCode 0xc00000
+#define bAGCRxCode 0x300000
+#define b3WireDataLength 0x800
+#define b3WireAddressLength 0x400
+#define b3WireRFPowerDown 0x1
+/*#define bHWSISelect 0x8 */
+#define b5GPAPEPolarity 0x40000000
+#define b2GPAPEPolarity 0x80000000
+#define bRFSW_TxDefaultAnt 0x3
+#define bRFSW_TxOptionAnt 0x30
+#define bRFSW_RxDefaultAnt 0x300
+#define bRFSW_RxOptionAnt 0x3000
+#define bRFSI_3WireData 0x1
+#define bRFSI_3WireClock 0x2
+#define bRFSI_3WireLoad 0x4
+#define bRFSI_3WireRW 0x8
+/* 3-wire total control */
+#define bRFSI_3Wire 0xf
+#define bRFSI_RFENV 0x10
+#define bRFSI_TRSW 0x20
+#define bRFSI_TRSWB 0x40
+#define bRFSI_ANTSW 0x100
+#define bRFSI_ANTSWB 0x200
+#define bRFSI_PAPE 0x400
+#define bRFSI_PAPE5G 0x800
+#define bBandSelect 0x1
+#define bHTSIG2_GI 0x80
+#define bHTSIG2_Smoothing 0x01
+#define bHTSIG2_Sounding 0x02
+#define bHTSIG2_Aggreaton 0x08
+#define bHTSIG2_STBC 0x30
+#define bHTSIG2_AdvCoding 0x40
+#define bHTSIG2_NumOfHTLTF 0x300
+#define bHTSIG2_CRC8 0x3fc
+#define bHTSIG1_MCS 0x7f
+#define bHTSIG1_BandWidth 0x80
+#define bHTSIG1_HTLength 0xffff
+#define bLSIG_Rate 0xf
+#define bLSIG_Reserved 0x10
+#define bLSIG_Length 0x1fffe
+#define bLSIG_Parity 0x20
+#define bCCKRxPhase 0x4
+/* LSSI "read" address */
+#define bLSSIReadAddress 0x3f000000
+/* LSSI "read" edge signal */
+#define bLSSIReadEdge 0x80000000
+#define bLSSIReadBackData 0xfff
+#define bLSSIReadOKFlag 0x1000
+/* 0: 44 MHz, 1: 88MHz */
+#define bCCKSampleRate 0x8
+
+#define bRegulator0Standby 0x1
+#define bRegulatorPLLStandby 0x2
+#define bRegulator1Standby 0x4
+#define bPLLPowerUp 0x8
+#define bDPLLPowerUp 0x10
+#define bDA10PowerUp 0x20
+#define bAD7PowerUp 0x200
+#define bDA6PowerUp 0x2000
+#define bXtalPowerUp 0x4000
+#define b40MDClkPowerUP 0x8000
+#define bDA6DebugMode 0x20000
+#define bDA6Swing 0x380000
+#define bADClkPhase 0x4000000
+#define b80MClkDelay 0x18000000
+#define bAFEWatchDogEnable 0x20000000
+#define bXtalCap 0x0f000000
+#define bXtalCap01 0xc0000000
+#define bXtalCap23 0x3
+#define bXtalCap92x 0x0f000000
+#define bIntDifClkEnable 0x400
+#define bExtSigClkEnable 0x800
+#define bBandgapMbiasPowerUp 0x10000
+#define bAD11SHGain 0xc0000
+#define bAD11InputRange 0x700000
+#define bAD11OPCurrent 0x3800000
+#define bIPathLoopback 0x4000000
+#define bQPathLoopback 0x8000000
+#define bAFELoopback 0x10000000
+#define bDA10Swing 0x7e0
+#define bDA10Reverse 0x800
+#define bDAClkSource 0x1000
+#define bAD7InputRange 0x6000
+#define bAD7Gain 0x38000
+#define bAD7OutputCMMode 0x40000
+#define bAD7InputCMMode 0x380000
+#define bAD7Current 0xc00000
+#define bRegulatorAdjust 0x7000000
+#define bAD11PowerUpAtTx 0x1
+#define bDA10PSAtTx 0x10
+#define bAD11PowerUpAtRx 0x100
+#define bDA10PSAtRx 0x1000
+
+#define bCCKRxAGCFormat 0x200
+
+#define bPSDFFTSamplepPoint 0xc000
+#define bPSDAverageNum 0x3000
+#define bIQPathControl 0xc00
+#define bPSDFreq 0x3ff
+#define bPSDAntennaPath 0x30
+#define bPSDIQSwitch 0x40
+#define bPSDRxTrigger 0x400000
+#define bPSDTxTrigger 0x80000000
+#define bPSDSineToneScale 0x7f000000
+#define bPSDReport 0xffff
+
+/* Page 8 */
+#define bOFDMTxSC 0x30000000
+#define bCCKTxOn 0x1
+#define bOFDMTxOn 0x2
+/* Reset debug page and also HWord, LWord */
+#define bDebugPage 0xfff
+/* Reset debug page and LWord */
+#define bDebugItem 0xff
+#define bAntL 0x10
+#define bAntNonHT 0x100
+#define bAntHT1 0x1000
+#define bAntHT2 0x10000
+#define bAntHT1S1 0x100000
+#define bAntNonHTS1 0x1000000
+
+/* Page a */
+#define bCCKBBMode 0x3
+#define bCCKTxPowerSaving 0x80
+#define bCCKRxPowerSaving 0x40
+#define bCCKSideBand 0x10
+#define bCCKScramble 0x8
+#define bCCKAntDiversity 0x8000
+#define bCCKCarrierRecovery 0x4000
+#define bCCKTxRate 0x3000
+#define bCCKDCCancel 0x0800
+#define bCCKISICancel 0x0400
+#define bCCKMatchFilter 0x0200
+#define bCCKEqualizer 0x0100
+#define bCCKPreambleDetect 0x800000
+#define bCCKFastFalseCCA 0x400000
+#define bCCKChEstStart 0x300000
+#define bCCKCCACount 0x080000
+#define bCCKcs_lim 0x070000
+#define bCCKBistMode 0x80000000
+#define bCCKCCAMask 0x40000000
+#define bCCKTxDACPhase 0x4
+/* r_rx_clk */
+#define bCCKRxADCPhase 0x20000000
+#define bCCKr_cp_mode0 0x0100
+#define bCCKTxDCOffset 0xf0
+#define bCCKRxDCOffset 0xf
+#define bCCKCCAMode 0xc000
+#define bCCKFalseCS_lim 0x3f00
+#define bCCKCS_ratio 0xc00000
+#define bCCKCorgBit_sel 0x300000
+#define bCCKPD_lim 0x0f0000
+#define bCCKNewCCA 0x80000000
+#define bCCKRxHPofIG 0x8000
+#define bCCKRxIG 0x7f00
+#define bCCKLNAPolarity 0x800000
+#define bCCKRx1stGain 0x7f0000
+/* CCK Rx Initial gain polarity */
+#define bCCKRFExtend 0x20000000
+#define bCCKRxAGCSatLevel 0x1f000000
+#define bCCKRxAGCSatCount 0xe0
+/* AGCSAmp_dly */
+#define bCCKRxRFSettle 0x1f
+#define bCCKFixedRxAGC 0x8000
+/*#define bCCKRxAGCFormat 0x4000 remove to HSSI register 0x824 */
+#define bCCKAntennaPolarity 0x2000
+#define bCCKTxFilterType 0x0c00
+#define bCCKRxAGCReportType 0x0300
+#define bCCKRxDAGCEn 0x80000000
+#define bCCKRxDAGCPeriod 0x20000000
+#define bCCKRxDAGCSatLevel 0x1f000000
+#define bCCKTimingRecovery 0x800000
+#define bCCKTxC0 0x3f0000
+#define bCCKTxC1 0x3f000000
+#define bCCKTxC2 0x3f
+#define bCCKTxC3 0x3f00
+#define bCCKTxC4 0x3f0000
+#define bCCKTxC5 0x3f000000
+#define bCCKTxC6 0x3f
+#define bCCKTxC7 0x3f00
+#define bCCKDebugPort 0xff0000
+#define bCCKDACDebug 0x0f000000
+#define bCCKFalseAlarmEnable 0x8000
+#define bCCKFalseAlarmRead 0x4000
+#define bCCKTRSSI 0x7f
+#define bCCKRxAGCReport 0xfe
+#define bCCKRxReport_AntSel 0x80000000
+#define bCCKRxReport_MFOff 0x40000000
+#define bCCKRxRxReport_SQLoss 0x20000000
+#define bCCKRxReport_Pktloss 0x10000000
+#define bCCKRxReport_Lockedbit 0x08000000
+#define bCCKRxReport_RateError 0x04000000
+#define bCCKRxReport_RxRate 0x03000000
+#define bCCKRxFACounterLower 0xff
+#define bCCKRxFACounterUpper 0xff000000
+#define bCCKRxHPAGCStart 0xe000
+#define bCCKRxHPAGCFinal 0x1c00
+
+#define bCCKRxFalseAlarmEnable 0x8000
+#define bCCKFACounterFreeze 0x4000
+
+#define bCCKTxPathSel 0x10000000
+#define bCCKDefaultRxPath 0xc000000
+#define bCCKOptionRxPath 0x3000000
+
+/* Page c */
+#define bNumOfSTF 0x3
+#define bShift_L 0xc0
+#define bGI_TH 0xc
+#define bRxPathA 0x1
+#define bRxPathB 0x2
+#define bRxPathC 0x4
+#define bRxPathD 0x8
+#define bTxPathA 0x1
+#define bTxPathB 0x2
+#define bTxPathC 0x4
+#define bTxPathD 0x8
+#define bTRSSIFreq 0x200
+#define bADCBackoff 0x3000
+#define bDFIRBackoff 0xc000
+#define bTRSSILatchPhase 0x10000
+#define bRxIDCOffset 0xff
+#define bRxQDCOffset 0xff00
+#define bRxDFIRMode 0x1800000
+#define bRxDCNFType 0xe000000
+#define bRXIQImb_A 0x3ff
+#define bRXIQImb_B 0xfc00
+#define bRXIQImb_C 0x3f0000
+#define bRXIQImb_D 0xffc00000
+#define bDC_dc_Notch 0x60000
+#define bRxNBINotch 0x1f000000
+#define bPD_TH 0xf
+#define bPD_TH_Opt2 0xc000
+#define bPWED_TH 0x700
+#define bIfMF_Win_L 0x800
+#define bPD_Option 0x1000
+#define bMF_Win_L 0xe000
+#define bBW_Search_L 0x30000
+#define bwin_enh_L 0xc0000
+#define bBW_TH 0x700000
+#define bED_TH2 0x3800000
+#define bBW_option 0x4000000
+#define bRatio_TH 0x18000000
+#define bWindow_L 0xe0000000
+#define bSBD_Option 0x1
+#define bFrame_TH 0x1c
+#define bFS_Option 0x60
+#define bDC_Slope_check 0x80
+#define bFGuard_Counter_DC_L 0xe00
+#define bFrame_Weight_Short 0x7000
+#define bSub_Tune 0xe00000
+#define bFrame_DC_Length 0xe000000
+#define bSBD_start_offset 0x30000000
+#define bFrame_TH_2 0x7
+#define bFrame_GI2_TH 0x38
+#define bGI2_Sync_en 0x40
+#define bSarch_Short_Early 0x300
+#define bSarch_Short_Late 0xc00
+#define bSarch_GI2_Late 0x70000
+#define bCFOAntSum 0x1
+#define bCFOAcc 0x2
+#define bCFOStartOffset 0xc
+#define bCFOLookBack 0x70
+#define bCFOSumWeight 0x80
+#define bDAGCEnable 0x10000
+#define bTXIQImb_A 0x3ff
+#define bTXIQImb_B 0xfc00
+#define bTXIQImb_C 0x3f0000
+#define bTXIQImb_D 0xffc00000
+#define bTxIDCOffset 0xff
+#define bTxQDCOffset 0xff00
+#define bTxDFIRMode 0x10000
+#define bTxPesudoNoiseOn 0x4000000
+#define bTxPesudoNoise_A 0xff
+#define bTxPesudoNoise_B 0xff00
+#define bTxPesudoNoise_C 0xff0000
+#define bTxPesudoNoise_D 0xff000000
+#define bCCADropOption 0x20000
+#define bCCADropThres 0xfff00000
+#define bEDCCA_H 0xf
+#define bEDCCA_L 0xf0
+#define bLambda_ED 0x300
+#define bRxInitialGain 0x7f
+#define bRxAntDivEn 0x80
+#define bRxAGCAddressForLNA 0x7f00
+#define bRxHighPowerFlow 0x8000
+#define bRxAGCFreezeThres 0xc0000
+#define bRxFreezeStep_AGC1 0x300000
+#define bRxFreezeStep_AGC2 0xc00000
+#define bRxFreezeStep_AGC3 0x3000000
+#define bRxFreezeStep_AGC0 0xc000000
+#define bRxRssi_Cmp_En 0x10000000
+#define bRxQuickAGCEn 0x20000000
+#define bRxAGCFreezeThresMode 0x40000000
+#define bRxOverFlowCheckType 0x80000000
+#define bRxAGCShift 0x7f
+#define bTRSW_Tri_Only 0x80
+#define bPowerThres 0x300
+#define bRxAGCEn 0x1
+#define bRxAGCTogetherEn 0x2
+#define bRxAGCMin 0x4
+#define bRxHP_Ini 0x7
+#define bRxHP_TRLNA 0x70
+#define bRxHP_RSSI 0x700
+#define bRxHP_BBP1 0x7000
+#define bRxHP_BBP2 0x70000
+#define bRxHP_BBP3 0x700000
+/* The threshold for high power */
+#define bRSSI_H 0x7f0000
+/* The threshold for ant diversity */
+#define bRSSI_Gen 0x7f000000
+#define bRxSettle_TRSW 0x7
+#define bRxSettle_LNA 0x38
+#define bRxSettle_RSSI 0x1c0
+#define bRxSettle_BBP 0xe00
+#define bRxSettle_RxHP 0x7000
+#define bRxSettle_AntSW_RSSI 0x38000
+#define bRxSettle_AntSW 0xc0000
+#define bRxProcessTime_DAGC 0x300000
+#define bRxSettle_HSSI 0x400000
+#define bRxProcessTime_BBPPW 0x800000
+#define bRxAntennaPowerShift 0x3000000
+#define bRSSITableSelect 0xc000000
+#define bRxHP_Final 0x7000000
+#define bRxHTSettle_BBP 0x7
+#define bRxHTSettle_HSSI 0x8
+#define bRxHTSettle_RxHP 0x70
+#define bRxHTSettle_BBPPW 0x80
+#define bRxHTSettle_Idle 0x300
+#define bRxHTSettle_Reserved 0x1c00
+#define bRxHTRxHPEn 0x8000
+#define bRxHTAGCFreezeThres 0x30000
+#define bRxHTAGCTogetherEn 0x40000
+#define bRxHTAGCMin 0x80000
+#define bRxHTAGCEn 0x100000
+#define bRxHTDAGCEn 0x200000
+#define bRxHTRxHP_BBP 0x1c00000
+#define bRxHTRxHP_Final 0xe0000000
+#define bRxPWRatioTH 0x3
+#define bRxPWRatioEn 0x4
+#define bRxMFHold 0x3800
+#define bRxPD_Delay_TH1 0x38
+#define bRxPD_Delay_TH2 0x1c0
+#define bRxPD_DC_COUNT_MAX 0x600
+/*#define bRxMF_Hold 0x3800*/
+#define bRxPD_Delay_TH 0x8000
+#define bRxProcess_Delay 0xf0000
+#define bRxSearchrange_GI2_Early 0x700000
+#define bRxFrame_Guard_Counter_L 0x3800000
+#define bRxSGI_Guard_L 0xc000000
+#define bRxSGI_Search_L 0x30000000
+#define bRxSGI_TH 0xc0000000
+#define bDFSCnt0 0xff
+#define bDFSCnt1 0xff00
+#define bDFSFlag 0xf0000
+
+#define bMFWeightSum 0x300000
+#define bMinIdxTH 0x7f000000
+
+#define bDAFormat 0x40000
+
+#define bTxChEmuEnable 0x01000000
+
+#define bTRSWIsolation_A 0x7f
+#define bTRSWIsolation_B 0x7f00
+#define bTRSWIsolation_C 0x7f0000
+#define bTRSWIsolation_D 0x7f000000
+
+#define bExtLNAGain 0x7c00
+
+/* Page d */
+#define bSTBCEn 0x4
+#define bAntennaMapping 0x10
+#define bNss 0x20
+#define bCFOAntSumD 0x200
+#define bPHYCounterReset 0x8000000
+#define bCFOReportGet 0x4000000
+#define bOFDMContinueTx 0x10000000
+#define bOFDMSingleCarrier 0x20000000
+#define bOFDMSingleTone 0x40000000
+/*#define bRxPath1 0x01
+#define bRxPath2 0x02
+#define bRxPath3 0x04
+#define bRxPath4 0x08
+#define bTxPath1 0x10
+#define bTxPath2 0x20*/
+#define bHTDetect 0x100
+#define bCFOEn 0x10000
+#define bCFOValue 0xfff00000
+#define bSigTone_Re 0x3f
+#define bSigTone_Im 0x7f00
+#define bCounter_CCA 0xffff
+#define bCounter_ParityFail 0xffff0000
+#define bCounter_RateIllegal 0xffff
+#define bCounter_CRC8Fail 0xffff0000
+#define bCounter_MCSNoSupport 0xffff
+#define bCounter_FastSync 0xffff
+#define bShortCFO 0xfff
+/* total */
+#define bShortCFOTLength 12
+/* fraction */
+#define bShortCFOFLength 11
+#define bLongCFO 0x7ff
+#define bLongCFOTLength 11
+#define bLongCFOFLength 11
+#define bTailCFO 0x1fff
+#define bTailCFOTLength 13
+#define bTailCFOFLength 12
+
+#define bmax_en_pwdB 0xffff
+#define bCC_power_dB 0xffff0000
+#define bnoise_pwdB 0xffff
+#define bPowerMeasTLength 10
+#define bPowerMeasFLength 3
+#define bRx_HT_BW 0x1
+#define bRxSC 0x6
+#define bRx_HT 0x8
+
+#define bNB_intf_det_on 0x1
+#define bIntf_win_len_cfg 0x30
+#define bNB_Intf_TH_cfg 0x1c0
+
+#define bRFGain 0x3f
+#define bTableSel 0x40
+#define bTRSW 0x80
+
+#define bRxSNR_A 0xff
+#define bRxSNR_B 0xff00
+#define bRxSNR_C 0xff0000
+#define bRxSNR_D 0xff000000
+#define bSNREVMTLength 8
+#define bSNREVMFLength 1
+
+#define bCSI1st 0xff
+#define bCSI2nd 0xff00
+#define bRxEVM1st 0xff0000
+#define bRxEVM2nd 0xff000000
+
+#define bSIGEVM 0xff
+#define bPWDB 0xff00
+#define bSGIEN 0x10000
+
+#define bSFactorQAM1 0xf
+#define bSFactorQAM2 0xf0
+#define bSFactorQAM3 0xf00
+#define bSFactorQAM4 0xf000
+#define bSFactorQAM5 0xf0000
+#define bSFactorQAM6 0xf0000
+#define bSFactorQAM7 0xf00000
+#define bSFactorQAM8 0xf000000
+#define bSFactorQAM9 0xf0000000
+#define bCSIScheme 0x100000
+
+#define bNoiseLvlTopSet 0x3
+#define bChSmooth 0x4
+#define bChSmoothCfg1 0x38
+#define bChSmoothCfg2 0x1c0
+#define bChSmoothCfg3 0xe00
+#define bChSmoothCfg4 0x7000
+#define bMRCMode 0x800000
+#define bTHEVMCfg 0x7000000
+
+#define bLoopFitType 0x1
+#define bUpdCFO 0x40
+#define bUpdCFOOffData 0x80
+#define bAdvUpdCFO 0x100
+#define bAdvTimeCtrl 0x800
+#define bUpdClko 0x1000
+#define bFC 0x6000
+#define bTrackingMode 0x8000
+#define bPhCmpEnable 0x10000
+#define bUpdClkoLTF 0x20000
+#define bComChCFO 0x40000
+#define bCSIEstiMode 0x80000
+#define bAdvUpdEqz 0x100000
+#define bUChCfg 0x7000000
+#define bUpdEqz 0x8000000
+
+/* Page e */
+#define bTxAGCRate18_06 0x7f7f7f7f
+#define bTxAGCRate54_24 0x7f7f7f7f
+#define bTxAGCRateMCS32 0x7f
+#define bTxAGCRateCCK 0x7f00
+#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f
+#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f
+#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f
+#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f
+
+
+/* Rx Pseduo noise */
+#define bRxPesudoNoiseOn 0x20000000
+#define bRxPesudoNoise_A 0xff
+#define bRxPesudoNoise_B 0xff00
+#define bRxPesudoNoise_C 0xff0000
+#define bRxPesudoNoise_D 0xff000000
+#define bPesudoNoiseState_A 0xffff
+#define bPesudoNoiseState_B 0xffff0000
+#define bPesudoNoiseState_C 0xffff
+#define bPesudoNoiseState_D 0xffff0000
+
+/* RF Zebra 1 */
+#define bZebra1_HSSIEnable 0x8
+#define bZebra1_TRxControl 0xc00
+#define bZebra1_TRxGainSetting 0x07f
+#define bZebra1_RxCorner 0xc00
+#define bZebra1_TxChargePump 0x38
+#define bZebra1_RxChargePump 0x7
+#define bZebra1_ChannelNum 0xf80
+#define bZebra1_TxLPFBW 0x400
+#define bZebra1_RxLPFBW 0x600
+
+/* Zebra4 */
+#define bRTL8256RegModeCtrl1 0x100
+#define bRTL8256RegModeCtrl0 0x40
+#define bRTL8256_TxLPFBW 0x18
+#define bRTL8256_RxLPFBW 0x600
+
+//RTL8258
+#define bRTL8258_TxLPFBW 0xc
+#define bRTL8258_RxLPFBW 0xc00
+#define bRTL8258_RSSILPFBW 0xc0
+
+/* byte enable for sb_write */
+#define bByte0 0x1
+#define bByte1 0x2
+#define bByte2 0x4
+#define bByte3 0x8
+#define bWord0 0x3
+#define bWord1 0xc
+#define bDWord 0xf
+
+/* for PutRegsetting & GetRegSetting BitMask */
+#define bMaskByte0 0xff
+#define bMaskByte1 0xff00
+#define bMaskByte2 0xff0000
+#define bMaskByte3 0xff000000
+#define bMaskHWord 0xffff0000
+#define bMaskLWord 0x0000ffff
+#define bMaskDWord 0xffffffff
+
+/* for PutRFRegsetting & GetRFRegSetting BitMask */
+#define bMask12Bits 0xfff
+
+#define bEnable 0x1
+#define bDisable 0x0
+
+#define LeftAntenna 0x0
+#define RightAntenna 0x1
+
+/* 500 ms */
+#define tCheckTxStatus 500
+/* 100 ms */
+#define tUpdateRxCounter 100
+
+#define rateCCK 0
+#define rateOFDM 1
+#define rateHT 2
+
+/* define Register-End */
+#define bPMAC_End 0x1ff
+#define bFPGAPHY0_End 0x8ff
+#define bFPGAPHY1_End 0x9ff
+#define bCCKPHY0_End 0xaff
+#define bOFDMPHY0_End 0xcff
+#define bOFDMPHY1_End 0xdff
+
+#define bPMACControl 0x0
+#define bWMACControl 0x1
+#define bWNICControl 0x2
+
+#define PathA 0x0
+#define PathB 0x1
+#define PathC 0x2
+#define PathD 0x3
+
+#define rRTL8256RxMixerPole 0xb
+#define bZebraRxMixerPole 0x6
+#define rRTL8256TxBBOPBias 0x9
+#define bRTL8256TxBBOPBias 0x400
+#define rRTL8256TxBBBW 19
+#define bRTL8256TxBBBW 0x18
+
+
+#endif /* __INC_HAL8190PCIPHYREG_H */
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
new file mode 100644
index 000000000..41b025e25
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
@@ -0,0 +1,277 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtl_core.h"
+#include "r8192E_phy.h"
+#include "r8192E_phyreg.h"
+#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
+#include "r8192E_cmdpkt.h"
+
+void CamResetAllEntry(struct net_device *dev)
+{
+ u32 ulcommand = 0;
+
+ ulcommand |= BIT31|BIT30;
+ write_nic_dword(dev, RWCAM, ulcommand);
+}
+
+void write_cam(struct net_device *dev, u8 addr, u32 data)
+{
+ write_nic_dword(dev, WCAMI, data);
+ write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff));
+}
+
+u32 read_cam(struct net_device *dev, u8 addr)
+{
+ write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff));
+ return read_nic_dword(dev, 0xa8);
+}
+
+void EnableHWSecurityConfig8192(struct net_device *dev)
+{
+ u8 SECR_value = 0x0;
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
+ if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) ||
+ (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) &&
+ (priv->rtllib->auth_mode != 2)) {
+ SECR_value |= SCR_RxUseDK;
+ SECR_value |= SCR_TxUseDK;
+ } else if ((ieee->iw_mode == IW_MODE_ADHOC) &&
+ (ieee->pairwise_key_type & (KEY_TYPE_CCMP |
+ KEY_TYPE_TKIP))) {
+ SECR_value |= SCR_RxUseDK;
+ SECR_value |= SCR_TxUseDK;
+ }
+
+
+ ieee->hwsec_active = 1;
+ if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) {
+ ieee->hwsec_active = 0;
+ SECR_value &= ~SCR_RxDecEnable;
+ }
+
+ RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n",
+ __func__, ieee->hwsec_active, ieee->pairwise_key_type,
+ SECR_value);
+ write_nic_byte(dev, SECR, SECR_value);
+}
+
+void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
+ u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ RT_TRACE(COMP_DBG,
+ "===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n",
+ __func__, EntryNo, KeyIndex, KeyType, is_mesh);
+ if (!is_mesh) {
+ ieee->swcamtable[EntryNo].bused = true;
+ ieee->swcamtable[EntryNo].key_index = KeyIndex;
+ ieee->swcamtable[EntryNo].key_type = KeyType;
+ memcpy(ieee->swcamtable[EntryNo].macaddr, MacAddr, 6);
+ ieee->swcamtable[EntryNo].useDK = DefaultKey;
+ memcpy(ieee->swcamtable[EntryNo].key_buf, (u8 *)KeyContent, 16);
+ }
+}
+
+void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
+ u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
+{
+ u32 TargetCommand = 0;
+ u32 TargetContent = 0;
+ u16 usConfig = 0;
+ u8 i;
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ enum rt_rf_power_state rtState;
+
+ rtState = priv->rtllib->eRFPowerState;
+ if (priv->rtllib->PowerSaveControl.bInactivePs) {
+ if (rtState == eRfOff) {
+ if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
+ RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",
+ __func__);
+ return;
+ }
+ down(&priv->rtllib->ips_sem);
+ IPSLeave(dev);
+ up(&priv->rtllib->ips_sem);
+ }
+ }
+ priv->rtllib->is_set_key = true;
+ if (EntryNo >= TOTAL_CAM_ENTRY)
+ RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
+
+ RT_TRACE(COMP_SEC,
+ "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
+ dev, EntryNo, KeyIndex, KeyType, MacAddr);
+
+ if (DefaultKey)
+ usConfig |= BIT15 | (KeyType<<2);
+ else
+ usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
+
+
+ for (i = 0; i < CAM_CONTENT_COUNT; i++) {
+ TargetCommand = i + CAM_CONTENT_COUNT * EntryNo;
+ TargetCommand |= BIT31|BIT16;
+
+ if (i == 0) {
+ TargetContent = (u32)(*(MacAddr+0)) << 16 |
+ (u32)(*(MacAddr+1)) << 24 |
+ (u32)usConfig;
+
+ write_nic_dword(dev, WCAMI, TargetContent);
+ write_nic_dword(dev, RWCAM, TargetCommand);
+ } else if (i == 1) {
+ TargetContent = (u32)(*(MacAddr+2)) |
+ (u32)(*(MacAddr+3)) << 8 |
+ (u32)(*(MacAddr+4)) << 16 |
+ (u32)(*(MacAddr+5)) << 24;
+ write_nic_dword(dev, WCAMI, TargetContent);
+ write_nic_dword(dev, RWCAM, TargetCommand);
+ } else {
+ if (KeyContent != NULL) {
+ write_nic_dword(dev, WCAMI,
+ (u32)(*(KeyContent+i-2)));
+ write_nic_dword(dev, RWCAM, TargetCommand);
+ udelay(100);
+ }
+ }
+ }
+ RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
+}
+
+void CamRestoreAllEntry(struct net_device *dev)
+{
+ u8 EntryId = 0;
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 *MacAddr = priv->rtllib->current_network.bssid;
+
+ static u8 CAM_CONST_ADDR[4][6] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+ };
+ static u8 CAM_CONST_BROAD[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+ RT_TRACE(COMP_SEC, "CamRestoreAllEntry:\n");
+
+
+ if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
+ (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) {
+
+ for (EntryId = 0; EntryId < 4; EntryId++) {
+ MacAddr = CAM_CONST_ADDR[EntryId];
+ if (priv->rtllib->swcamtable[EntryId].bused) {
+ setKey(dev, EntryId, EntryId,
+ priv->rtllib->pairwise_key_type, MacAddr,
+ 0, (u32 *)(&priv->rtllib->swcamtable
+ [EntryId].key_buf[0]));
+ }
+ }
+
+ } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
+ setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
+ (u8 *)dev->dev_addr, 0,
+ (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
+ } else {
+ setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
+ MacAddr, 0,
+ (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
+ }
+
+ } else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
+ setKey(dev, 4, 0,
+ priv->rtllib->pairwise_key_type,
+ (u8 *)dev->dev_addr, 0,
+ (u32 *)(&priv->rtllib->swcamtable[4].
+ key_buf[0]));
+ } else {
+ setKey(dev, 4, 0,
+ priv->rtllib->pairwise_key_type, MacAddr,
+ 0, (u32 *)(&priv->rtllib->swcamtable[4].
+ key_buf[0]));
+ }
+ }
+
+ if (priv->rtllib->group_key_type == KEY_TYPE_TKIP) {
+ MacAddr = CAM_CONST_BROAD;
+ for (EntryId = 1; EntryId < 4; EntryId++) {
+ if (priv->rtllib->swcamtable[EntryId].bused) {
+ setKey(dev, EntryId, EntryId,
+ priv->rtllib->group_key_type,
+ MacAddr, 0,
+ (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])
+ );
+ }
+ }
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
+ if (priv->rtllib->swcamtable[0].bused) {
+ setKey(dev, 0, 0,
+ priv->rtllib->group_key_type,
+ CAM_CONST_ADDR[0], 0,
+ (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])
+ );
+ } else {
+ RT_TRACE(COMP_ERR,
+ "===>%s():ERR!! ADHOC TKIP ,but 0 entry is have no data\n",
+ __func__);
+ return;
+ }
+ }
+ } else if (priv->rtllib->group_key_type == KEY_TYPE_CCMP) {
+ MacAddr = CAM_CONST_BROAD;
+ for (EntryId = 1; EntryId < 4; EntryId++) {
+ if (priv->rtllib->swcamtable[EntryId].bused) {
+ setKey(dev, EntryId, EntryId,
+ priv->rtllib->group_key_type,
+ MacAddr, 0,
+ (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
+ }
+ }
+
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
+ if (priv->rtllib->swcamtable[0].bused) {
+ setKey(dev, 0, 0,
+ priv->rtllib->group_key_type,
+ CAM_CONST_ADDR[0], 0,
+ (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
+ } else {
+ RT_TRACE(COMP_ERR,
+ "===>%s():ERR!! ADHOC CCMP ,but 0 entry is have no data\n",
+ __func__);
+ return;
+ }
+ }
+ }
+}
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h
new file mode 100644
index 000000000..3c4c0e61c
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _RTL_CAM_H
+#define _RTL_CAM_H
+
+#include <linux/types.h>
+struct net_device;
+
+void CamResetAllEntry(struct net_device *dev);
+void EnableHWSecurityConfig8192(struct net_device *dev);
+void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
+ u8 *MacAddr, u8 DefaultKey, u32 *KeyContent);
+void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
+ u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh);
+void CamPrintDbgReg(struct net_device *dev);
+
+u32 read_cam(struct net_device *dev, u8 addr);
+void write_cam(struct net_device *dev, u8 addr, u32 data);
+
+void CamRestoreAllEntry(struct net_device *dev);
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
new file mode 100644
index 000000000..23ec2d0b7
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -0,0 +1,3120 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#undef RX_DONT_PASS_UL
+#undef DEBUG_EPROM
+#undef DEBUG_RX_VERBOSE
+#undef DUMMY_RX
+#undef DEBUG_ZERO_RX
+#undef DEBUG_RX_SKB
+#undef DEBUG_TX_FRAG
+#undef DEBUG_RX_FRAG
+#undef DEBUG_TX_FILLDESC
+#undef DEBUG_TX
+#undef DEBUG_IRQ
+#undef DEBUG_RX
+#undef DEBUG_RXALLOC
+#undef DEBUG_REGISTERS
+#undef DEBUG_RING
+#undef DEBUG_IRQ_TASKLET
+#undef DEBUG_TX_ALLOC
+#undef DEBUG_TX_DESC
+
+#include <linux/uaccess.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include "rtl_core.h"
+#include "r8192E_phy.h"
+#include "r8192E_phyreg.h"
+#include "r8190P_rtl8256.h"
+#include "r8192E_cmdpkt.h"
+
+#include "rtl_wx.h"
+#include "rtl_dm.h"
+
+#include "rtl_pm.h"
+
+int hwwep = 1;
+static int channels = 0x3fff;
+static char *ifname = "wlan%d";
+
+
+static struct rtl819x_ops rtl819xp_ops = {
+ .nic_type = NIC_8192E,
+ .get_eeprom_size = rtl8192_get_eeprom_size,
+ .init_adapter_variable = rtl8192_InitializeVariables,
+ .initialize_adapter = rtl8192_adapter_start,
+ .link_change = rtl8192_link_change,
+ .tx_fill_descriptor = rtl8192_tx_fill_desc,
+ .tx_fill_cmd_descriptor = rtl8192_tx_fill_cmd_desc,
+ .rx_query_status_descriptor = rtl8192_rx_query_status_desc,
+ .rx_command_packet_handler = NULL,
+ .stop_adapter = rtl8192_halt_adapter,
+ .update_ratr_table = rtl8192_update_ratr_table,
+ .irq_enable = rtl8192_EnableInterrupt,
+ .irq_disable = rtl8192_DisableInterrupt,
+ .irq_clear = rtl8192_ClearInterrupt,
+ .rx_enable = rtl8192_enable_rx,
+ .tx_enable = rtl8192_enable_tx,
+ .interrupt_recognized = rtl8192_interrupt_recognized,
+ .TxCheckStuckHandler = rtl8192_HalTxCheckStuck,
+ .RxCheckStuckHandler = rtl8192_HalRxCheckStuck,
+};
+
+static struct pci_device_id rtl8192_pci_id_tbl[] = {
+ {RTL_PCI_DEVICE(0x10ec, 0x8192, rtl819xp_ops)},
+ {RTL_PCI_DEVICE(0x07aa, 0x0044, rtl819xp_ops)},
+ {RTL_PCI_DEVICE(0x07aa, 0x0047, rtl819xp_ops)},
+ {}
+};
+
+MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl);
+
+static int rtl8192_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id);
+static void rtl8192_pci_disconnect(struct pci_dev *pdev);
+static irqreturn_t rtl8192_interrupt(int irq, void *netdev);
+
+static struct pci_driver rtl8192_pci_driver = {
+ .name = DRV_NAME, /* Driver name */
+ .id_table = rtl8192_pci_id_tbl, /* PCI_ID table */
+ .probe = rtl8192_pci_probe, /* probe fn */
+ .remove = rtl8192_pci_disconnect, /* remove fn */
+ .suspend = rtl8192E_suspend, /* PM suspend fn */
+ .resume = rtl8192E_resume, /* PM resume fn */
+};
+
+/****************************************************************************
+ -----------------------------IO STUFF-------------------------
+*****************************************************************************/
+static bool PlatformIOCheckPageLegalAndGetRegMask(u32 u4bPage, u8 *pu1bPageMask)
+{
+ bool bReturn = false;
+
+ *pu1bPageMask = 0xfe;
+
+ switch (u4bPage) {
+ case 1: case 2: case 3: case 4:
+ case 8: case 9: case 10: case 12: case 13:
+ bReturn = true;
+ *pu1bPageMask = 0xf0;
+ break;
+
+ default:
+ bReturn = false;
+ break;
+ }
+
+ return bReturn;
+}
+
+void write_nic_io_byte(struct net_device *dev, int x, u8 y)
+{
+ u32 u4bPage = x >> 8;
+ u8 u1PageMask = 0;
+ bool bIsLegalPage = false;
+
+ if (u4bPage == 0) {
+ outb(y&0xff, dev->base_addr + x);
+
+ } else {
+ bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
+ &u1PageMask);
+ if (bIsLegalPage) {
+ u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+ write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
+ (u8)u4bPage));
+ write_nic_io_byte(dev, (x & 0xff), y);
+ write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
+ }
+ }
+}
+
+void write_nic_io_word(struct net_device *dev, int x, u16 y)
+{
+ u32 u4bPage = x >> 8;
+ u8 u1PageMask = 0;
+ bool bIsLegalPage = false;
+
+ if (u4bPage == 0) {
+ outw(y, dev->base_addr + x);
+ } else {
+ bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
+ &u1PageMask);
+ if (bIsLegalPage) {
+ u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+ write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
+ (u8)u4bPage));
+ write_nic_io_word(dev, (x & 0xff), y);
+ write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
+
+ }
+ }
+}
+
+void write_nic_io_dword(struct net_device *dev, int x, u32 y)
+{
+ u32 u4bPage = x >> 8;
+ u8 u1PageMask = 0;
+ bool bIsLegalPage = false;
+
+ if (u4bPage == 0) {
+ outl(y, dev->base_addr + x);
+ } else {
+ bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
+ &u1PageMask);
+ if (bIsLegalPage) {
+ u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+ write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
+ (u8)u4bPage));
+ write_nic_io_dword(dev, (x & 0xff), y);
+ write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
+ }
+ }
+}
+
+u8 read_nic_io_byte(struct net_device *dev, int x)
+{
+ u32 u4bPage = x >> 8;
+ u8 u1PageMask = 0;
+ bool bIsLegalPage = false;
+ u8 Data = 0;
+
+ if (u4bPage == 0)
+ return 0xff&inb(dev->base_addr + x);
+
+ bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
+ &u1PageMask);
+ if (bIsLegalPage) {
+ u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+ write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
+ (u8)u4bPage));
+ Data = read_nic_io_byte(dev, (x & 0xff));
+ write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
+ }
+
+ return Data;
+}
+
+u16 read_nic_io_word(struct net_device *dev, int x)
+{
+ u32 u4bPage = x >> 8;
+ u8 u1PageMask = 0;
+ bool bIsLegalPage = false;
+ u16 Data = 0;
+
+ if (u4bPage == 0)
+ return inw(dev->base_addr + x);
+ bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
+ &u1PageMask);
+ if (bIsLegalPage) {
+ u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+ write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
+ (u8)u4bPage));
+ Data = read_nic_io_word(dev, (x & 0xff));
+ write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
+ }
+
+ return Data;
+}
+
+u32 read_nic_io_dword(struct net_device *dev, int x)
+{
+ u32 u4bPage = x >> 8;
+ u8 u1PageMask = 0;
+ bool bIsLegalPage = false;
+ u32 Data = 0;
+
+ if (u4bPage == 0)
+ return inl(dev->base_addr + x);
+ bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
+ &u1PageMask);
+ if (bIsLegalPage) {
+ u8 u1bPsr = read_nic_io_byte(dev, PSR);
+
+ write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
+ (u8)u4bPage));
+ Data = read_nic_io_dword(dev, (x & 0xff));
+ write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
+ }
+
+ return Data;
+}
+
+u8 read_nic_byte(struct net_device *dev, int x)
+{
+ return 0xff & readb((u8 __iomem *)dev->mem_start + x);
+}
+
+u32 read_nic_dword(struct net_device *dev, int x)
+{
+ return readl((u8 __iomem *)dev->mem_start + x);
+}
+
+u16 read_nic_word(struct net_device *dev, int x)
+{
+ return readw((u8 __iomem *)dev->mem_start + x);
+}
+
+void write_nic_byte(struct net_device *dev, int x, u8 y)
+{
+ writeb(y, (u8 __iomem *)dev->mem_start + x);
+
+ udelay(20);
+}
+
+void write_nic_dword(struct net_device *dev, int x, u32 y)
+{
+ writel(y, (u8 __iomem *)dev->mem_start + x);
+
+ udelay(20);
+}
+
+void write_nic_word(struct net_device *dev, int x, u16 y)
+{
+ writew(y, (u8 __iomem *)dev->mem_start + x);
+
+ udelay(20);
+}
+
+/****************************************************************************
+ -----------------------------GENERAL FUNCTION-------------------------
+*****************************************************************************/
+bool MgntActSet_RF_State(struct net_device *dev,
+ enum rt_rf_power_state StateToSet,
+ RT_RF_CHANGE_SOURCE ChangeSource,
+ bool ProtectOrNot)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+ bool bActionAllowed = false;
+ bool bConnectBySSID = false;
+ enum rt_rf_power_state rtState;
+ u16 RFWaitCounter = 0;
+ unsigned long flag;
+
+ RT_TRACE((COMP_PS | COMP_RF),
+ "===>MgntActSet_RF_State(): StateToSet(%d)\n", StateToSet);
+
+ ProtectOrNot = false;
+
+
+ if (!ProtectOrNot) {
+ while (true) {
+ spin_lock_irqsave(&priv->rf_ps_lock, flag);
+ if (priv->RFChangeInProgress) {
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+ RT_TRACE((COMP_PS | COMP_RF),
+ "MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n",
+ StateToSet);
+
+ while (priv->RFChangeInProgress) {
+ RFWaitCounter++;
+ RT_TRACE((COMP_PS | COMP_RF),
+ "MgntActSet_RF_State(): Wait 1 ms (%d times)...\n",
+ RFWaitCounter);
+ mdelay(1);
+
+ if (RFWaitCounter > 100) {
+ RT_TRACE(COMP_ERR,
+ "MgntActSet_RF_State(): Wait too logn to set RF\n");
+ return false;
+ }
+ }
+ } else {
+ priv->RFChangeInProgress = true;
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+ break;
+ }
+ }
+ }
+
+ rtState = priv->rtllib->eRFPowerState;
+
+ switch (StateToSet) {
+ case eRfOn:
+ priv->rtllib->RfOffReason &= (~ChangeSource);
+
+ if ((ChangeSource == RF_CHANGE_BY_HW) && priv->bHwRadioOff)
+ priv->bHwRadioOff = false;
+
+ if (!priv->rtllib->RfOffReason) {
+ priv->rtllib->RfOffReason = 0;
+ bActionAllowed = true;
+
+
+ if (rtState == eRfOff &&
+ ChangeSource >= RF_CHANGE_BY_HW)
+ bConnectBySSID = true;
+ } else {
+ RT_TRACE((COMP_PS | COMP_RF),
+ "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n",
+ priv->rtllib->RfOffReason, ChangeSource);
+ }
+
+ break;
+
+ case eRfOff:
+
+ if ((priv->rtllib->iw_mode == IW_MODE_INFRA) ||
+ (priv->rtllib->iw_mode == IW_MODE_ADHOC)) {
+ if ((priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) ||
+ (ChangeSource > RF_CHANGE_BY_IPS)) {
+ if (ieee->state == RTLLIB_LINKED)
+ priv->blinked_ingpio = true;
+ else
+ priv->blinked_ingpio = false;
+ rtllib_MgntDisconnect(priv->rtllib,
+ disas_lv_ss);
+ }
+ }
+ if ((ChangeSource == RF_CHANGE_BY_HW) && !priv->bHwRadioOff)
+ priv->bHwRadioOff = true;
+ priv->rtllib->RfOffReason |= ChangeSource;
+ bActionAllowed = true;
+ break;
+
+ case eRfSleep:
+ priv->rtllib->RfOffReason |= ChangeSource;
+ bActionAllowed = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if (bActionAllowed) {
+ RT_TRACE((COMP_PS | COMP_RF),
+ "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n",
+ StateToSet, priv->rtllib->RfOffReason);
+ PHY_SetRFPowerState(dev, StateToSet);
+ if (StateToSet == eRfOn) {
+
+ if (bConnectBySSID && priv->blinked_ingpio) {
+ queue_delayed_work_rsl(ieee->wq,
+ &ieee->associate_procedure_wq, 0);
+ priv->blinked_ingpio = false;
+ }
+ }
+ } else {
+ RT_TRACE((COMP_PS | COMP_RF),
+ "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n",
+ StateToSet, ChangeSource, priv->rtllib->RfOffReason);
+ }
+
+ if (!ProtectOrNot) {
+ spin_lock_irqsave(&priv->rf_ps_lock, flag);
+ priv->RFChangeInProgress = false;
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+ }
+
+ RT_TRACE((COMP_PS | COMP_RF), "<===MgntActSet_RF_State()\n");
+ return bActionAllowed;
+}
+
+
+static short rtl8192_get_nic_desc_num(struct net_device *dev, int prio)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
+
+ /* For now, we reserved two free descriptor as a safety boundary
+ * between the tail and the head
+ */
+ if ((prio == MGNT_QUEUE) && (skb_queue_len(&ring->queue) > 10))
+ RT_TRACE(COMP_DBG,
+ "-----[%d]---------ring->idx=%d queue_len=%d---------\n",
+ prio, ring->idx, skb_queue_len(&ring->queue));
+ return skb_queue_len(&ring->queue);
+}
+
+static short rtl8192_check_nic_enough_desc(struct net_device *dev, int prio)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
+
+ if (ring->entries - skb_queue_len(&ring->queue) >= 2)
+ return 1;
+ return 0;
+}
+
+void rtl8192_tx_timeout(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ schedule_work(&priv->reset_wq);
+ netdev_info(dev, "TXTIMEOUT");
+}
+
+void rtl8192_irq_enable(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ priv->irq_enabled = 1;
+
+ priv->ops->irq_enable(dev);
+}
+
+void rtl8192_irq_disable(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ priv->ops->irq_disable(dev);
+
+ priv->irq_enabled = 0;
+}
+
+void rtl8192_set_chan(struct net_device *dev, short ch)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __func__, ch);
+ if (priv->chan_forced)
+ return;
+
+ priv->chan = ch;
+
+ if (priv->rf_set_chan)
+ priv->rf_set_chan(dev, priv->chan);
+}
+
+void rtl8192_update_cap(struct net_device *dev, u16 cap)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_network *net = &priv->rtllib->current_network;
+ bool ShortPreamble;
+
+ if (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) {
+ if (priv->dot11CurrentPreambleMode != PREAMBLE_SHORT) {
+ ShortPreamble = true;
+ priv->dot11CurrentPreambleMode = PREAMBLE_SHORT;
+ RT_TRACE(COMP_DBG,
+ "%s(): WLAN_CAPABILITY_SHORT_PREAMBLE\n",
+ __func__);
+ priv->rtllib->SetHwRegHandler(dev, HW_VAR_ACK_PREAMBLE,
+ (unsigned char *)&ShortPreamble);
+ }
+ } else {
+ if (priv->dot11CurrentPreambleMode != PREAMBLE_LONG) {
+ ShortPreamble = false;
+ priv->dot11CurrentPreambleMode = PREAMBLE_LONG;
+ RT_TRACE(COMP_DBG,
+ "%s(): WLAN_CAPABILITY_LONG_PREAMBLE\n",
+ __func__);
+ priv->rtllib->SetHwRegHandler(dev, HW_VAR_ACK_PREAMBLE,
+ (unsigned char *)&ShortPreamble);
+ }
+ }
+
+ if (net->mode & (IEEE_G|IEEE_N_24G)) {
+ u8 slot_time_val;
+ u8 CurSlotTime = priv->slot_time;
+
+ if ((cap & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
+ (!priv->rtllib->pHTInfo->bCurrentRT2RTLongSlotTime)) {
+ if (CurSlotTime != SHORT_SLOT_TIME) {
+ slot_time_val = SHORT_SLOT_TIME;
+ priv->rtllib->SetHwRegHandler(dev,
+ HW_VAR_SLOT_TIME, &slot_time_val);
+ }
+ } else {
+ if (CurSlotTime != NON_SHORT_SLOT_TIME) {
+ slot_time_val = NON_SHORT_SLOT_TIME;
+ priv->rtllib->SetHwRegHandler(dev,
+ HW_VAR_SLOT_TIME, &slot_time_val);
+ }
+ }
+ }
+}
+
+static struct rtllib_qos_parameters def_qos_parameters = {
+ {cpu_to_le16(3), cpu_to_le16(3), cpu_to_le16(3), cpu_to_le16(3)},
+ {cpu_to_le16(7), cpu_to_le16(7), cpu_to_le16(7), cpu_to_le16(7)},
+ {2, 2, 2, 2},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+};
+
+static void rtl8192_update_beacon(void *data)
+{
+ struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv,
+ update_beacon_wq.work);
+ struct net_device *dev = priv->rtllib->dev;
+ struct rtllib_device *ieee = priv->rtllib;
+ struct rtllib_network *net = &ieee->current_network;
+
+ if (ieee->pHTInfo->bCurrentHTSupport)
+ HT_update_self_and_peer_setting(ieee, net);
+ ieee->pHTInfo->bCurrentRT2RTLongSlotTime =
+ net->bssht.bdRT2RTLongSlotTime;
+ ieee->pHTInfo->RT2RT_HT_Mode = net->bssht.RT2RT_HT_Mode;
+ rtl8192_update_cap(dev, net->capability);
+}
+
+static void rtl8192_qos_activate(void *data)
+{
+ struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv,
+ qos_activate);
+ struct net_device *dev = priv->rtllib->dev;
+ int i;
+
+ mutex_lock(&priv->mutex);
+ if (priv->rtllib->state != RTLLIB_LINKED)
+ goto success;
+ RT_TRACE(COMP_QOS,
+ "qos active process with associate response received\n");
+
+ for (i = 0; i < QOS_QUEUE_NUM; i++)
+ priv->rtllib->SetHwRegHandler(dev, HW_VAR_AC_PARAM, (u8 *)(&i));
+
+
+success:
+ mutex_unlock(&priv->mutex);
+}
+
+static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
+ int active_network,
+ struct rtllib_network *network)
+{
+ int ret = 0;
+ u32 size = sizeof(struct rtllib_qos_parameters);
+
+ if (priv->rtllib->state != RTLLIB_LINKED)
+ return ret;
+
+ if (priv->rtllib->iw_mode != IW_MODE_INFRA)
+ return ret;
+
+ if (network->flags & NETWORK_HAS_QOS_MASK) {
+ if (active_network &&
+ (network->flags & NETWORK_HAS_QOS_PARAMETERS))
+ network->qos_data.active = network->qos_data.supported;
+
+ if ((network->qos_data.active == 1) && (active_network == 1) &&
+ (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
+ (network->qos_data.old_param_count !=
+ network->qos_data.param_count)) {
+ network->qos_data.old_param_count =
+ network->qos_data.param_count;
+ priv->rtllib->wmm_acm = network->qos_data.wmm_acm;
+ queue_work_rsl(priv->priv_wq, &priv->qos_activate);
+ RT_TRACE(COMP_QOS,
+ "QoS parameters change call qos_activate\n");
+ }
+ } else {
+ memcpy(&priv->rtllib->current_network.qos_data.parameters,
+ &def_qos_parameters, size);
+
+ if ((network->qos_data.active == 1) && (active_network == 1)) {
+ queue_work_rsl(priv->priv_wq, &priv->qos_activate);
+ RT_TRACE(COMP_QOS,
+ "QoS was disabled call qos_activate\n");
+ }
+ network->qos_data.active = 0;
+ network->qos_data.supported = 0;
+ }
+
+ return 0;
+}
+
+static int rtl8192_handle_beacon(struct net_device *dev,
+ struct rtllib_beacon *beacon,
+ struct rtllib_network *network)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ rtl8192_qos_handle_probe_response(priv, 1, network);
+
+ queue_delayed_work_rsl(priv->priv_wq, &priv->update_beacon_wq, 0);
+ return 0;
+
+}
+
+static int rtl8192_qos_association_resp(struct r8192_priv *priv,
+ struct rtllib_network *network)
+{
+ unsigned long flags;
+ u32 size = sizeof(struct rtllib_qos_parameters);
+ int set_qos_param = 0;
+
+ if ((priv == NULL) || (network == NULL))
+ return 0;
+
+ if (priv->rtllib->state != RTLLIB_LINKED)
+ return 0;
+
+ if (priv->rtllib->iw_mode != IW_MODE_INFRA)
+ return 0;
+
+ spin_lock_irqsave(&priv->rtllib->lock, flags);
+ if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
+ memcpy(&priv->rtllib->current_network.qos_data.parameters,
+ &network->qos_data.parameters,
+ sizeof(struct rtllib_qos_parameters));
+ priv->rtllib->current_network.qos_data.active = 1;
+ priv->rtllib->wmm_acm = network->qos_data.wmm_acm;
+ set_qos_param = 1;
+ priv->rtllib->current_network.qos_data.old_param_count =
+ priv->rtllib->current_network.qos_data.param_count;
+ priv->rtllib->current_network.qos_data.param_count =
+ network->qos_data.param_count;
+ } else {
+ memcpy(&priv->rtllib->current_network.qos_data.parameters,
+ &def_qos_parameters, size);
+ priv->rtllib->current_network.qos_data.active = 0;
+ priv->rtllib->current_network.qos_data.supported = 0;
+ set_qos_param = 1;
+ }
+
+ spin_unlock_irqrestore(&priv->rtllib->lock, flags);
+
+ RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n", __func__,
+ network->flags, priv->rtllib->current_network.qos_data.active);
+ if (set_qos_param == 1) {
+ dm_init_edca_turbo(priv->rtllib->dev);
+ queue_work_rsl(priv->priv_wq, &priv->qos_activate);
+ }
+ return 0;
+}
+
+static int rtl8192_handle_assoc_response(struct net_device *dev,
+ struct rtllib_assoc_response_frame *resp,
+ struct rtllib_network *network)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ rtl8192_qos_association_resp(priv, network);
+ return 0;
+}
+
+static void rtl8192_prepare_beacon(struct r8192_priv *priv)
+{
+ struct net_device *dev = priv->rtllib->dev;
+ struct sk_buff *pskb = NULL, *pnewskb = NULL;
+ struct cb_desc *tcb_desc = NULL;
+ struct rtl8192_tx_ring *ring = NULL;
+ struct tx_desc *pdesc = NULL;
+
+ ring = &priv->tx_ring[BEACON_QUEUE];
+ pskb = __skb_dequeue(&ring->queue);
+ kfree_skb(pskb);
+
+ pnewskb = rtllib_get_beacon(priv->rtllib);
+ if (!pnewskb)
+ return;
+
+ tcb_desc = (struct cb_desc *)(pnewskb->cb + 8);
+ tcb_desc->queue_index = BEACON_QUEUE;
+ tcb_desc->data_rate = 2;
+ tcb_desc->RATRIndex = 7;
+ tcb_desc->bTxDisableRateFallBack = 1;
+ tcb_desc->bTxUseDriverAssingedRate = 1;
+ skb_push(pnewskb, priv->rtllib->tx_headroom);
+
+ pdesc = &ring->desc[0];
+ priv->ops->tx_fill_descriptor(dev, pdesc, tcb_desc, pnewskb);
+ __skb_queue_tail(&ring->queue, pnewskb);
+ pdesc->OWN = 1;
+}
+
+static void rtl8192_stop_beacon(struct net_device *dev)
+{
+}
+
+void rtl8192_config_rate(struct net_device *dev, u16 *rate_config)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_network *net;
+ u8 i = 0, basic_rate = 0;
+
+ net = &priv->rtllib->current_network;
+
+ for (i = 0; i < net->rates_len; i++) {
+ basic_rate = net->rates[i] & 0x7f;
+ switch (basic_rate) {
+ case MGN_1M:
+ *rate_config |= RRSR_1M;
+ break;
+ case MGN_2M:
+ *rate_config |= RRSR_2M;
+ break;
+ case MGN_5_5M:
+ *rate_config |= RRSR_5_5M;
+ break;
+ case MGN_11M:
+ *rate_config |= RRSR_11M;
+ break;
+ case MGN_6M:
+ *rate_config |= RRSR_6M;
+ break;
+ case MGN_9M:
+ *rate_config |= RRSR_9M;
+ break;
+ case MGN_12M:
+ *rate_config |= RRSR_12M;
+ break;
+ case MGN_18M:
+ *rate_config |= RRSR_18M;
+ break;
+ case MGN_24M:
+ *rate_config |= RRSR_24M;
+ break;
+ case MGN_36M:
+ *rate_config |= RRSR_36M;
+ break;
+ case MGN_48M:
+ *rate_config |= RRSR_48M;
+ break;
+ case MGN_54M:
+ *rate_config |= RRSR_54M;
+ break;
+ }
+ }
+
+ for (i = 0; i < net->rates_ex_len; i++) {
+ basic_rate = net->rates_ex[i] & 0x7f;
+ switch (basic_rate) {
+ case MGN_1M:
+ *rate_config |= RRSR_1M;
+ break;
+ case MGN_2M:
+ *rate_config |= RRSR_2M;
+ break;
+ case MGN_5_5M:
+ *rate_config |= RRSR_5_5M;
+ break;
+ case MGN_11M:
+ *rate_config |= RRSR_11M;
+ break;
+ case MGN_6M:
+ *rate_config |= RRSR_6M;
+ break;
+ case MGN_9M:
+ *rate_config |= RRSR_9M;
+ break;
+ case MGN_12M:
+ *rate_config |= RRSR_12M;
+ break;
+ case MGN_18M:
+ *rate_config |= RRSR_18M;
+ break;
+ case MGN_24M:
+ *rate_config |= RRSR_24M;
+ break;
+ case MGN_36M:
+ *rate_config |= RRSR_36M;
+ break;
+ case MGN_48M:
+ *rate_config |= RRSR_48M;
+ break;
+ case MGN_54M:
+ *rate_config |= RRSR_54M;
+ break;
+ }
+ }
+}
+
+static void rtl8192_refresh_supportrate(struct r8192_priv *priv)
+{
+ struct rtllib_device *ieee = priv->rtllib;
+
+ if (ieee->mode == WIRELESS_MODE_N_24G ||
+ ieee->mode == WIRELESS_MODE_N_5G) {
+ memcpy(ieee->Regdot11HTOperationalRateSet,
+ ieee->RegHTSuppRateSet, 16);
+ memcpy(ieee->Regdot11TxHTOperationalRateSet,
+ ieee->RegHTSuppRateSet, 16);
+
+ } else {
+ memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
+ }
+}
+
+static u8 rtl8192_getSupportedWireleeMode(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 ret = 0;
+
+ switch (priv->rf_chip) {
+ case RF_8225:
+ case RF_8256:
+ case RF_6052:
+ case RF_PSEUDO_11N:
+ ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G | WIRELESS_MODE_B);
+ break;
+ case RF_8258:
+ ret = (WIRELESS_MODE_A | WIRELESS_MODE_N_5G);
+ break;
+ default:
+ ret = WIRELESS_MODE_B;
+ break;
+ }
+ return ret;
+}
+
+void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
+
+ if ((wireless_mode == WIRELESS_MODE_AUTO) ||
+ ((wireless_mode & bSupportMode) == 0)) {
+ if (bSupportMode & WIRELESS_MODE_N_24G) {
+ wireless_mode = WIRELESS_MODE_N_24G;
+ } else if (bSupportMode & WIRELESS_MODE_N_5G) {
+ wireless_mode = WIRELESS_MODE_N_5G;
+ } else if ((bSupportMode & WIRELESS_MODE_A)) {
+ wireless_mode = WIRELESS_MODE_A;
+ } else if ((bSupportMode & WIRELESS_MODE_G)) {
+ wireless_mode = WIRELESS_MODE_G;
+ } else if ((bSupportMode & WIRELESS_MODE_B)) {
+ wireless_mode = WIRELESS_MODE_B;
+ } else {
+ RT_TRACE(COMP_ERR,
+ "%s(), No valid wireless mode supported (%x)!!!\n",
+ __func__, bSupportMode);
+ wireless_mode = WIRELESS_MODE_B;
+ }
+ }
+
+ if ((wireless_mode & (WIRELESS_MODE_B | WIRELESS_MODE_G)) ==
+ (WIRELESS_MODE_G | WIRELESS_MODE_B))
+ wireless_mode = WIRELESS_MODE_G;
+
+ priv->rtllib->mode = wireless_mode;
+
+ ActUpdateChannelAccessSetting(dev, wireless_mode,
+ &priv->ChannelAccessSetting);
+
+ if ((wireless_mode == WIRELESS_MODE_N_24G) ||
+ (wireless_mode == WIRELESS_MODE_N_5G)) {
+ priv->rtllib->pHTInfo->bEnableHT = 1;
+ RT_TRACE(COMP_DBG, "%s(), wireless_mode:%x, bEnableHT = 1\n",
+ __func__, wireless_mode);
+ } else {
+ priv->rtllib->pHTInfo->bEnableHT = 0;
+ RT_TRACE(COMP_DBG, "%s(), wireless_mode:%x, bEnableHT = 0\n",
+ __func__, wireless_mode);
+ }
+
+ RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
+ rtl8192_refresh_supportrate(priv);
+}
+
+static int _rtl8192_sta_up(struct net_device *dev, bool is_silent_reset)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ (&(priv->rtllib->PowerSaveControl));
+ bool init_status = true;
+
+ priv->bDriverIsGoingToUnload = false;
+ priv->bdisable_nic = false;
+
+ priv->up = 1;
+ priv->rtllib->ieee_up = 1;
+
+ priv->up_first_time = 0;
+ RT_TRACE(COMP_INIT, "Bringing up iface");
+ priv->bfirst_init = true;
+ init_status = priv->ops->initialize_adapter(dev);
+ if (!init_status) {
+ RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization is failed!\n",
+ __func__);
+ priv->bfirst_init = false;
+ return -1;
+ }
+
+ RT_TRACE(COMP_INIT, "start adapter finished\n");
+ RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+ priv->bfirst_init = false;
+
+ if (priv->polling_timer_on == 0)
+ check_rfctrl_gpio_timer((unsigned long)dev);
+
+ if (priv->rtllib->state != RTLLIB_LINKED)
+ rtllib_softmac_start_protocol(priv->rtllib, 0);
+ rtllib_reset_queue(priv->rtllib);
+ watch_dog_timer_callback((unsigned long) dev);
+
+ if (!netif_queue_stopped(dev))
+ netif_start_queue(dev);
+ else
+ netif_wake_queue(dev);
+
+ return 0;
+}
+
+static int rtl8192_sta_down(struct net_device *dev, bool shutdownrf)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ unsigned long flags = 0;
+ u8 RFInProgressTimeOut = 0;
+
+ if (priv->up == 0)
+ return -1;
+
+ if (priv->rtllib->rtllib_ips_leave != NULL)
+ priv->rtllib->rtllib_ips_leave(dev);
+
+ if (priv->rtllib->state == RTLLIB_LINKED)
+ LeisurePSLeave(dev);
+
+ priv->bDriverIsGoingToUnload = true;
+ priv->up = 0;
+ priv->rtllib->ieee_up = 0;
+ priv->bfirst_after_down = true;
+ RT_TRACE(COMP_DOWN, "==========>%s()\n", __func__);
+ if (!netif_queue_stopped(dev))
+ netif_stop_queue(dev);
+
+ priv->rtllib->wpa_ie_len = 0;
+ kfree(priv->rtllib->wpa_ie);
+ priv->rtllib->wpa_ie = NULL;
+ CamResetAllEntry(dev);
+ memset(priv->rtllib->swcamtable, 0, sizeof(struct sw_cam_table) * 32);
+ rtl8192_irq_disable(dev);
+
+ del_timer_sync(&priv->watch_dog_timer);
+ rtl8192_cancel_deferred_work(priv);
+ cancel_delayed_work(&priv->rtllib->hw_wakeup_wq);
+
+ rtllib_softmac_stop_protocol(priv->rtllib, 0, true);
+ spin_lock_irqsave(&priv->rf_ps_lock, flags);
+ while (priv->RFChangeInProgress) {
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
+ if (RFInProgressTimeOut > 100) {
+ spin_lock_irqsave(&priv->rf_ps_lock, flags);
+ break;
+ }
+ RT_TRACE(COMP_DBG,
+ "===>%s():RF is in progress, need to wait until rf change is done.\n",
+ __func__);
+ mdelay(1);
+ RFInProgressTimeOut++;
+ spin_lock_irqsave(&priv->rf_ps_lock, flags);
+ }
+ priv->RFChangeInProgress = true;
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
+ priv->ops->stop_adapter(dev, false);
+ spin_lock_irqsave(&priv->rf_ps_lock, flags);
+ priv->RFChangeInProgress = false;
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
+ udelay(100);
+ memset(&priv->rtllib->current_network, 0,
+ offsetof(struct rtllib_network, list));
+ RT_TRACE(COMP_DOWN, "<==========%s()\n", __func__);
+
+ return 0;
+}
+
+static void rtl8192_init_priv_handler(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->rtllib->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
+ priv->rtllib->set_chan = rtl8192_set_chan;
+ priv->rtllib->link_change = priv->ops->link_change;
+ priv->rtllib->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
+ priv->rtllib->data_hard_stop = rtl8192_data_hard_stop;
+ priv->rtllib->data_hard_resume = rtl8192_data_hard_resume;
+ priv->rtllib->check_nic_enough_desc = rtl8192_check_nic_enough_desc;
+ priv->rtllib->get_nic_desc_num = rtl8192_get_nic_desc_num;
+ priv->rtllib->handle_assoc_response = rtl8192_handle_assoc_response;
+ priv->rtllib->handle_beacon = rtl8192_handle_beacon;
+ priv->rtllib->SetWirelessMode = rtl8192_SetWirelessMode;
+ priv->rtllib->LeisurePSLeave = LeisurePSLeave;
+ priv->rtllib->SetBWModeHandler = rtl8192_SetBWMode;
+ priv->rf_set_chan = rtl8192_phy_SwChnl;
+
+ priv->rtllib->start_send_beacons = rtl8192e_start_beacon;
+ priv->rtllib->stop_send_beacons = rtl8192_stop_beacon;
+
+ priv->rtllib->sta_wake_up = rtl8192_hw_wakeup;
+ priv->rtllib->enter_sleep_state = rtl8192_hw_to_sleep;
+ priv->rtllib->ps_is_queue_empty = rtl8192_is_tx_queue_empty;
+
+ priv->rtllib->GetNmodeSupportBySecCfg = rtl8192_GetNmodeSupportBySecCfg;
+ priv->rtllib->GetHalfNmodeSupportByAPsHandler =
+ rtl8192_GetHalfNmodeSupportByAPs;
+
+ priv->rtllib->SetHwRegHandler = rtl8192e_SetHwReg;
+ priv->rtllib->AllowAllDestAddrHandler = rtl8192_AllowAllDestAddr;
+ priv->rtllib->SetFwCmdHandler = NULL;
+ priv->rtllib->InitialGainHandler = InitialGain819xPci;
+ priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq;
+ priv->rtllib->rtllib_ips_leave = rtllib_ips_leave;
+
+ priv->rtllib->LedControlHandler = NULL;
+ priv->rtllib->UpdateBeaconInterruptHandler = NULL;
+
+ priv->rtllib->ScanOperationBackupHandler = PHY_ScanOperationBackup8192;
+
+ priv->rtllib->rtllib_rfkill_poll = NULL;
+}
+
+static void rtl8192_init_priv_constant(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ &(priv->rtllib->PowerSaveControl);
+
+ pPSC->RegMaxLPSAwakeIntvl = 5;
+
+ priv->RegPciASPM = 2;
+
+ priv->RegDevicePciASPMSetting = 0x03;
+
+ priv->RegHostPciASPMSetting = 0x02;
+
+ priv->RegHwSwRfOffD3 = 2;
+
+ priv->RegSupportPciASPM = 2;
+}
+
+
+static void rtl8192_init_priv_variable(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 i;
+
+ priv->AcmMethod = eAcmWay2_SW;
+ priv->dot11CurrentPreambleMode = PREAMBLE_AUTO;
+ priv->rtllib->hwscan_sem_up = 1;
+ priv->rtllib->status = 0;
+ priv->H2CTxCmdSeq = 0;
+ priv->bDisableFrameBursting = false;
+ priv->bDMInitialGainEnable = true;
+ priv->polling_timer_on = 0;
+ priv->up_first_time = 1;
+ priv->blinked_ingpio = false;
+ priv->bDriverIsGoingToUnload = false;
+ priv->being_init_adapter = false;
+ priv->initialized_at_probe = false;
+ priv->sw_radio_on = true;
+ priv->bdisable_nic = false;
+ priv->bfirst_init = false;
+ priv->txringcount = 64;
+ priv->rxbuffersize = 9100;
+ priv->rxringcount = MAX_RX_COUNT;
+ priv->irq_enabled = 0;
+ priv->chan = 1;
+ priv->RegWirelessMode = WIRELESS_MODE_AUTO;
+ priv->RegChannelPlan = 0xf;
+ priv->nrxAMPDU_size = 0;
+ priv->nrxAMPDU_aggr_num = 0;
+ priv->last_rxdesc_tsf_high = 0;
+ priv->last_rxdesc_tsf_low = 0;
+ priv->rtllib->mode = WIRELESS_MODE_AUTO;
+ priv->rtllib->iw_mode = IW_MODE_INFRA;
+ priv->rtllib->bNetPromiscuousMode = false;
+ priv->rtllib->IntelPromiscuousModeInfo.bPromiscuousOn = false;
+ priv->rtllib->IntelPromiscuousModeInfo.bFilterSourceStationFrame =
+ false;
+ priv->rtllib->ieee_up = 0;
+ priv->retry_rts = DEFAULT_RETRY_RTS;
+ priv->retry_data = DEFAULT_RETRY_DATA;
+ priv->rtllib->rts = DEFAULT_RTS_THRESHOLD;
+ priv->rtllib->rate = 110;
+ priv->rtllib->short_slot = 1;
+ priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
+ priv->bcck_in_ch14 = false;
+ priv->bfsync_processing = false;
+ priv->CCKPresentAttentuation = 0;
+ priv->rfa_txpowertrackingindex = 0;
+ priv->rfc_txpowertrackingindex = 0;
+ priv->CckPwEnl = 6;
+ priv->ScanDelay = 50;
+ priv->ResetProgress = RESET_TYPE_NORESET;
+ priv->bForcedSilentReset = false;
+ priv->bDisableNormalResetCheck = false;
+ priv->force_reset = false;
+ memset(priv->rtllib->swcamtable, 0, sizeof(struct sw_cam_table) * 32);
+
+ memset(&priv->InterruptLog, 0, sizeof(struct log_int_8190));
+ priv->RxCounter = 0;
+ priv->rtllib->wx_set_enc = 0;
+ priv->bHwRadioOff = false;
+ priv->RegRfOff = false;
+ priv->isRFOff = false;
+ priv->bInPowerSaveMode = false;
+ priv->rtllib->RfOffReason = 0;
+ priv->RFChangeInProgress = false;
+ priv->bHwRfOffAction = 0;
+ priv->SetRFPowerStateInProgress = false;
+ priv->rtllib->PowerSaveControl.bInactivePs = true;
+ priv->rtllib->PowerSaveControl.bIPSModeBackup = false;
+ priv->rtllib->PowerSaveControl.bLeisurePs = true;
+ priv->rtllib->PowerSaveControl.bFwCtrlLPS = false;
+ priv->rtllib->LPSDelayCnt = 0;
+ priv->rtllib->sta_sleep = LPS_IS_WAKE;
+ priv->rtllib->eRFPowerState = eRfOn;
+
+ priv->txpower_checkcnt = 0;
+ priv->thermal_readback_index = 0;
+ priv->txpower_tracking_callback_cnt = 0;
+ priv->ccktxpower_adjustcnt_ch14 = 0;
+ priv->ccktxpower_adjustcnt_not_ch14 = 0;
+
+ priv->rtllib->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
+ priv->rtllib->iw_mode = IW_MODE_INFRA;
+ priv->rtllib->active_scan = 1;
+ priv->rtllib->be_scan_inprogress = false;
+ priv->rtllib->modulation = RTLLIB_CCK_MODULATION |
+ RTLLIB_OFDM_MODULATION;
+ priv->rtllib->host_encrypt = 1;
+ priv->rtllib->host_decrypt = 1;
+
+ priv->rtllib->dot11PowerSaveMode = eActive;
+ priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD;
+ priv->rtllib->MaxMssDensity = 0;
+ priv->rtllib->MinSpaceCfg = 0;
+
+ priv->card_type = PCI;
+
+ priv->AcmControl = 0;
+ priv->pFirmware = vzalloc(sizeof(struct rt_firmware));
+ if (!priv->pFirmware)
+ netdev_err(dev,
+ "rtl8192e: Unable to allocate space for firmware\n");
+
+ skb_queue_head_init(&priv->rx_queue);
+ skb_queue_head_init(&priv->skb_queue);
+
+ for (i = 0; i < MAX_QUEUE_SIZE; i++)
+ skb_queue_head_init(&priv->rtllib->skb_waitQ[i]);
+ for (i = 0; i < MAX_QUEUE_SIZE; i++)
+ skb_queue_head_init(&priv->rtllib->skb_aggQ[i]);
+}
+
+static void rtl8192_init_priv_lock(struct r8192_priv *priv)
+{
+ spin_lock_init(&priv->fw_scan_lock);
+ spin_lock_init(&priv->tx_lock);
+ spin_lock_init(&priv->irq_lock);
+ spin_lock_init(&priv->irq_th_lock);
+ spin_lock_init(&priv->rf_ps_lock);
+ spin_lock_init(&priv->ps_lock);
+ spin_lock_init(&priv->rf_lock);
+ spin_lock_init(&priv->rt_h2c_lock);
+ sema_init(&priv->wx_sem, 1);
+ sema_init(&priv->rf_sem, 1);
+ mutex_init(&priv->mutex);
+}
+
+static void rtl8192_init_priv_task(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->priv_wq = create_workqueue(DRV_NAME);
+ INIT_WORK_RSL(&priv->reset_wq, (void *)rtl8192_restart, dev);
+ INIT_WORK_RSL(&priv->rtllib->ips_leave_wq, (void *)IPSLeave_wq, dev);
+ INIT_DELAYED_WORK_RSL(&priv->watch_dog_wq,
+ (void *)rtl819x_watchdog_wqcallback, dev);
+ INIT_DELAYED_WORK_RSL(&priv->txpower_tracking_wq,
+ (void *)dm_txpower_trackingcallback, dev);
+ INIT_DELAYED_WORK_RSL(&priv->rfpath_check_wq,
+ (void *)dm_rf_pathcheck_workitemcallback, dev);
+ INIT_DELAYED_WORK_RSL(&priv->update_beacon_wq,
+ (void *)rtl8192_update_beacon, dev);
+ INIT_WORK_RSL(&priv->qos_activate, (void *)rtl8192_qos_activate, dev);
+ INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_wakeup_wq,
+ (void *) rtl8192_hw_wakeup_wq, dev);
+ INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_sleep_wq,
+ (void *) rtl8192_hw_sleep_wq, dev);
+ tasklet_init(&priv->irq_rx_tasklet,
+ (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
+ (unsigned long)priv);
+ tasklet_init(&priv->irq_tx_tasklet,
+ (void(*)(unsigned long))rtl8192_irq_tx_tasklet,
+ (unsigned long)priv);
+ tasklet_init(&priv->irq_prepare_beacon_tasklet,
+ (void(*)(unsigned long))rtl8192_prepare_beacon,
+ (unsigned long)priv);
+}
+
+static short rtl8192_get_channel_map(struct net_device *dev)
+{
+ int i;
+
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if ((priv->rf_chip != RF_8225) && (priv->rf_chip != RF_8256)
+ && (priv->rf_chip != RF_6052)) {
+ RT_TRACE(COMP_ERR,
+ "%s: unknown rf chip, can't set channel map\n",
+ __func__);
+ return -1;
+ }
+
+ if (priv->ChannelPlan >= COUNTRY_CODE_MAX) {
+ netdev_info(dev,
+ "rtl819x_init:Error channel plan! Set to default.\n");
+ priv->ChannelPlan = COUNTRY_CODE_FCC;
+ }
+ RT_TRACE(COMP_INIT, "Channel plan is %d\n", priv->ChannelPlan);
+ dot11d_init(priv->rtllib);
+ Dot11d_Channelmap(priv->ChannelPlan, priv->rtllib);
+ for (i = 1; i <= 11; i++)
+ (priv->rtllib->active_channel_map)[i] = 1;
+ (priv->rtllib->active_channel_map)[12] = 2;
+ (priv->rtllib->active_channel_map)[13] = 2;
+
+ return 0;
+}
+
+static short rtl8192_init(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ memset(&(priv->stats), 0, sizeof(struct rt_stats));
+
+ rtl8192_init_priv_handler(dev);
+ rtl8192_init_priv_constant(dev);
+ rtl8192_init_priv_variable(dev);
+ rtl8192_init_priv_lock(priv);
+ rtl8192_init_priv_task(dev);
+ priv->ops->get_eeprom_size(dev);
+ priv->ops->init_adapter_variable(dev);
+ rtl8192_get_channel_map(dev);
+
+ init_hal_dm(dev);
+
+ init_timer(&priv->watch_dog_timer);
+ setup_timer(&priv->watch_dog_timer,
+ watch_dog_timer_callback,
+ (unsigned long) dev);
+
+ init_timer(&priv->gpio_polling_timer);
+ setup_timer(&priv->gpio_polling_timer,
+ check_rfctrl_gpio_timer,
+ (unsigned long)dev);
+
+ rtl8192_irq_disable(dev);
+ if (request_irq(dev->irq, rtl8192_interrupt, IRQF_SHARED,
+ dev->name, dev)) {
+ netdev_err(dev, "Error allocating IRQ %d", dev->irq);
+ return -1;
+ }
+
+ priv->irq = dev->irq;
+ RT_TRACE(COMP_INIT, "IRQ %d\n", dev->irq);
+
+ if (rtl8192_pci_initdescring(dev) != 0) {
+ netdev_err(dev, "Endopoints initialization failed");
+ free_irq(dev->irq, dev);
+ return -1;
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+ -------------------------------WATCHDOG STUFF---------------------------
+***************************************************************************/
+short rtl8192_is_tx_queue_empty(struct net_device *dev)
+{
+ int i = 0;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ for (i = 0; i <= MGNT_QUEUE; i++) {
+ if ((i == TXCMD_QUEUE) || (i == HCCA_QUEUE))
+ continue;
+ if (skb_queue_len(&(&priv->tx_ring[i])->queue) > 0) {
+ netdev_info(dev, "===>tx queue is not empty:%d, %d\n",
+ i, skb_queue_len(&(&priv->tx_ring[i])->queue));
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static enum reset_type rtl819x_TxCheckStuck(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 QueueID;
+ u8 ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
+ bool bCheckFwTxCnt = false;
+ struct rtl8192_tx_ring *ring = NULL;
+ struct sk_buff *skb = NULL;
+ struct cb_desc *tcb_desc = NULL;
+ unsigned long flags = 0;
+
+ switch (priv->rtllib->ps) {
+ case RTLLIB_PS_DISABLED:
+ ResetThreshold = NIC_SEND_HANG_THRESHOLD_NORMAL;
+ break;
+ case (RTLLIB_PS_MBCAST|RTLLIB_PS_UNICAST):
+ ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
+ break;
+ default:
+ ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
+ break;
+ }
+ spin_lock_irqsave(&priv->irq_th_lock, flags);
+ for (QueueID = 0; QueueID < MAX_TX_QUEUE; QueueID++) {
+ if (QueueID == TXCMD_QUEUE)
+ continue;
+
+ if (QueueID == BEACON_QUEUE)
+ continue;
+
+ ring = &priv->tx_ring[QueueID];
+
+ if (skb_queue_len(&ring->queue) == 0) {
+ continue;
+ } else {
+ skb = (&ring->queue)->next;
+ tcb_desc = (struct cb_desc *)(skb->cb +
+ MAX_DEV_ADDR_SIZE);
+ tcb_desc->nStuckCount++;
+ bCheckFwTxCnt = true;
+ if (tcb_desc->nStuckCount > 1)
+ netdev_info(dev,
+ "%s: QueueID=%d tcb_desc->nStuckCount=%d\n",
+ __func__, QueueID,
+ tcb_desc->nStuckCount);
+ }
+ }
+ spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+
+ if (bCheckFwTxCnt) {
+ if (priv->ops->TxCheckStuckHandler(dev)) {
+ RT_TRACE(COMP_RESET,
+ "TxCheckStuck(): Fw indicates no Tx condition!\n");
+ return RESET_TYPE_SILENT;
+ }
+ }
+
+ return RESET_TYPE_NORESET;
+}
+
+static enum reset_type rtl819x_RxCheckStuck(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->ops->RxCheckStuckHandler(dev)) {
+ RT_TRACE(COMP_RESET, "RxStuck Condition\n");
+ return RESET_TYPE_SILENT;
+ }
+
+ return RESET_TYPE_NORESET;
+}
+
+static enum reset_type rtl819x_ifcheck_resetornot(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ enum reset_type TxResetType = RESET_TYPE_NORESET;
+ enum reset_type RxResetType = RESET_TYPE_NORESET;
+ enum rt_rf_power_state rfState;
+
+ rfState = priv->rtllib->eRFPowerState;
+
+ if (rfState == eRfOn)
+ TxResetType = rtl819x_TxCheckStuck(dev);
+
+ if (rfState == eRfOn &&
+ (priv->rtllib->iw_mode == IW_MODE_INFRA) &&
+ (priv->rtllib->state == RTLLIB_LINKED))
+ RxResetType = rtl819x_RxCheckStuck(dev);
+
+ if (TxResetType == RESET_TYPE_NORMAL ||
+ RxResetType == RESET_TYPE_NORMAL) {
+ netdev_info(dev, "%s(): TxResetType is %d, RxResetType is %d\n",
+ __func__, TxResetType, RxResetType);
+ return RESET_TYPE_NORMAL;
+ } else if (TxResetType == RESET_TYPE_SILENT ||
+ RxResetType == RESET_TYPE_SILENT) {
+ netdev_info(dev, "%s(): TxResetType is %d, RxResetType is %d\n",
+ __func__, TxResetType, RxResetType);
+ return RESET_TYPE_SILENT;
+ } else {
+ return RESET_TYPE_NORESET;
+ }
+
+}
+
+static void rtl819x_silentreset_mesh_bk(struct net_device *dev, u8 IsPortal)
+{
+}
+
+static void rtl819x_ifsilentreset(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 reset_times = 0;
+ int reset_status = 0;
+ struct rtllib_device *ieee = priv->rtllib;
+ unsigned long flag;
+
+ u8 IsPortal = 0;
+
+
+ if (priv->ResetProgress == RESET_TYPE_NORESET) {
+
+ RT_TRACE(COMP_RESET, "=========>Reset progress!!\n");
+
+ priv->ResetProgress = RESET_TYPE_SILENT;
+
+ spin_lock_irqsave(&priv->rf_ps_lock, flag);
+ if (priv->RFChangeInProgress) {
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+ goto END;
+ }
+ priv->RFChangeInProgress = true;
+ priv->bResetInProgress = true;
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+
+RESET_START:
+
+ down(&priv->wx_sem);
+
+ if (priv->rtllib->state == RTLLIB_LINKED)
+ LeisurePSLeave(dev);
+
+ if (priv->up) {
+ RT_TRACE(COMP_ERR,
+ "%s():the driver is not up! return\n",
+ __func__);
+ up(&priv->wx_sem);
+ return;
+ }
+ priv->up = 0;
+
+ RT_TRACE(COMP_RESET, "%s():======>start to down the driver\n",
+ __func__);
+ mdelay(1000);
+ RT_TRACE(COMP_RESET,
+ "%s():111111111111111111111111======>start to down the driver\n",
+ __func__);
+
+ if (!netif_queue_stopped(dev))
+ netif_stop_queue(dev);
+
+ rtl8192_irq_disable(dev);
+ del_timer_sync(&priv->watch_dog_timer);
+ rtl8192_cancel_deferred_work(priv);
+ deinit_hal_dm(dev);
+ rtllib_stop_scan_syncro(ieee);
+
+ if (ieee->state == RTLLIB_LINKED) {
+ SEM_DOWN_IEEE_WX(&ieee->wx_sem);
+ netdev_info(dev, "ieee->state is RTLLIB_LINKED\n");
+ rtllib_stop_send_beacons(priv->rtllib);
+ del_timer_sync(&ieee->associate_timer);
+ cancel_delayed_work(&ieee->associate_retry_wq);
+ rtllib_stop_scan(ieee);
+ netif_carrier_off(dev);
+ SEM_UP_IEEE_WX(&ieee->wx_sem);
+ } else {
+ netdev_info(dev, "ieee->state is NOT LINKED\n");
+ rtllib_softmac_stop_protocol(priv->rtllib, 0 , true);
+ }
+
+ dm_backup_dynamic_mechanism_state(dev);
+
+ up(&priv->wx_sem);
+ RT_TRACE(COMP_RESET,
+ "%s():<==========down process is finished\n",
+ __func__);
+
+ RT_TRACE(COMP_RESET, "%s():<===========up process start\n",
+ __func__);
+ reset_status = _rtl8192_up(dev, true);
+
+ RT_TRACE(COMP_RESET,
+ "%s():<===========up process is finished\n", __func__);
+ if (reset_status == -1) {
+ if (reset_times < 3) {
+ reset_times++;
+ goto RESET_START;
+ } else {
+ RT_TRACE(COMP_ERR,
+ " ERR!!! %s(): Reset Failed!!\n",
+ __func__);
+ }
+ }
+
+ ieee->is_silent_reset = 1;
+
+ spin_lock_irqsave(&priv->rf_ps_lock, flag);
+ priv->RFChangeInProgress = false;
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+
+ EnableHWSecurityConfig8192(dev);
+
+ if (ieee->state == RTLLIB_LINKED && ieee->iw_mode ==
+ IW_MODE_INFRA) {
+ ieee->set_chan(ieee->dev,
+ ieee->current_network.channel);
+
+ queue_work_rsl(ieee->wq, &ieee->associate_complete_wq);
+
+ } else if (ieee->state == RTLLIB_LINKED && ieee->iw_mode ==
+ IW_MODE_ADHOC) {
+ ieee->set_chan(ieee->dev,
+ ieee->current_network.channel);
+ ieee->link_change(ieee->dev);
+
+ notify_wx_assoc_event(ieee);
+
+ rtllib_start_send_beacons(ieee);
+
+ if (ieee->data_hard_resume)
+ ieee->data_hard_resume(ieee->dev);
+ netif_carrier_on(ieee->dev);
+ } else if (ieee->iw_mode == IW_MODE_MESH) {
+ rtl819x_silentreset_mesh_bk(dev, IsPortal);
+ }
+
+ CamRestoreAllEntry(dev);
+ dm_restore_dynamic_mechanism_state(dev);
+END:
+ priv->ResetProgress = RESET_TYPE_NORESET;
+ priv->reset_count++;
+
+ priv->bForcedSilentReset = false;
+ priv->bResetInProgress = false;
+
+ write_nic_byte(dev, UFWP, 1);
+ RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n",
+ priv->reset_count);
+ }
+}
+
+static void rtl819x_update_rxcounts(struct r8192_priv *priv, u32 *TotalRxBcnNum,
+ u32 *TotalRxDataNum)
+{
+ u16 SlotIndex;
+ u8 i;
+
+ *TotalRxBcnNum = 0;
+ *TotalRxDataNum = 0;
+
+ SlotIndex = (priv->rtllib->LinkDetectInfo.SlotIndex++) %
+ (priv->rtllib->LinkDetectInfo.SlotNum);
+ priv->rtllib->LinkDetectInfo.RxBcnNum[SlotIndex] =
+ priv->rtllib->LinkDetectInfo.NumRecvBcnInPeriod;
+ priv->rtllib->LinkDetectInfo.RxDataNum[SlotIndex] =
+ priv->rtllib->LinkDetectInfo.NumRecvDataInPeriod;
+ for (i = 0; i < priv->rtllib->LinkDetectInfo.SlotNum; i++) {
+ *TotalRxBcnNum += priv->rtllib->LinkDetectInfo.RxBcnNum[i];
+ *TotalRxDataNum += priv->rtllib->LinkDetectInfo.RxDataNum[i];
+ }
+}
+
+
+void rtl819x_watchdog_wqcallback(void *data)
+{
+ struct r8192_priv *priv = container_of_dwork_rsl(data,
+ struct r8192_priv, watch_dog_wq);
+ struct net_device *dev = priv->rtllib->dev;
+ struct rtllib_device *ieee = priv->rtllib;
+ enum reset_type ResetType = RESET_TYPE_NORESET;
+ static u8 check_reset_cnt;
+ unsigned long flags;
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ (&(priv->rtllib->PowerSaveControl));
+ bool bBusyTraffic = false;
+ bool bHigherBusyTraffic = false;
+ bool bHigherBusyRxTraffic = false;
+ bool bEnterPS = false;
+
+ if (!priv->up || priv->bHwRadioOff)
+ return;
+
+ if (priv->rtllib->state >= RTLLIB_LINKED) {
+ if (priv->rtllib->CntAfterLink < 2)
+ priv->rtllib->CntAfterLink++;
+ } else {
+ priv->rtllib->CntAfterLink = 0;
+ }
+
+ hal_dm_watchdog(dev);
+
+ if (rtllib_act_scanning(priv->rtllib, false) == false) {
+ if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state ==
+ RTLLIB_NOLINK) &&
+ (ieee->eRFPowerState == eRfOn) && !ieee->is_set_key &&
+ (!ieee->proto_stoppping) && !ieee->wx_set_enc) {
+ if ((ieee->PowerSaveControl.ReturnPoint ==
+ IPS_CALLBACK_NONE) &&
+ (!ieee->bNetPromiscuousMode)) {
+ RT_TRACE(COMP_PS,
+ "====================>haha: IPSEnter()\n");
+ IPSEnter(dev);
+ }
+ }
+ }
+ if ((ieee->state == RTLLIB_LINKED) && (ieee->iw_mode ==
+ IW_MODE_INFRA) && (!ieee->bNetPromiscuousMode)) {
+ if (ieee->LinkDetectInfo.NumRxOkInPeriod > 100 ||
+ ieee->LinkDetectInfo.NumTxOkInPeriod > 100)
+ bBusyTraffic = true;
+
+
+ if (ieee->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
+ ieee->LinkDetectInfo.NumTxOkInPeriod > 4000) {
+ bHigherBusyTraffic = true;
+ if (ieee->LinkDetectInfo.NumRxOkInPeriod > 5000)
+ bHigherBusyRxTraffic = true;
+ else
+ bHigherBusyRxTraffic = false;
+ }
+
+ if (((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +
+ ieee->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
+ (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2))
+ bEnterPS = false;
+ else
+ bEnterPS = true;
+
+ if (ieee->current_network.beacon_interval < 95)
+ bEnterPS = false;
+
+ if (bEnterPS)
+ LeisurePSEnter(dev);
+ else
+ LeisurePSLeave(dev);
+
+ } else {
+ RT_TRACE(COMP_LPS, "====>no link LPS leave\n");
+ LeisurePSLeave(dev);
+ }
+
+ ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
+ ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
+ ieee->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
+ ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
+
+ ieee->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
+ ieee->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
+
+ if (ieee->state == RTLLIB_LINKED && ieee->iw_mode == IW_MODE_INFRA) {
+ u32 TotalRxBcnNum = 0;
+ u32 TotalRxDataNum = 0;
+
+ rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
+
+ if ((TotalRxBcnNum+TotalRxDataNum) == 0)
+ priv->check_roaming_cnt++;
+ else
+ priv->check_roaming_cnt = 0;
+
+
+ if (priv->check_roaming_cnt > 0) {
+ if (ieee->eRFPowerState == eRfOff)
+ RT_TRACE(COMP_ERR, "========>%s()\n", __func__);
+
+ netdev_info(dev,
+ "===>%s(): AP is power off, chan:%d, connect another one\n",
+ __func__, priv->chan);
+
+ ieee->state = RTLLIB_ASSOCIATING;
+
+ RemovePeerTS(priv->rtllib,
+ priv->rtllib->current_network.bssid);
+ ieee->is_roaming = true;
+ ieee->is_set_key = false;
+ ieee->link_change(dev);
+ if (ieee->LedControlHandler)
+ ieee->LedControlHandler(ieee->dev,
+ LED_CTL_START_TO_LINK);
+
+ notify_wx_assoc_event(ieee);
+
+ if (!(ieee->rtllib_ap_sec_type(ieee) &
+ (SEC_ALG_CCMP|SEC_ALG_TKIP)))
+ queue_delayed_work_rsl(ieee->wq,
+ &ieee->associate_procedure_wq, 0);
+
+ priv->check_roaming_cnt = 0;
+ }
+ ieee->LinkDetectInfo.NumRecvBcnInPeriod = 0;
+ ieee->LinkDetectInfo.NumRecvDataInPeriod = 0;
+
+ }
+
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ if ((check_reset_cnt++ >= 3) && (!ieee->is_roaming) &&
+ (!priv->RFChangeInProgress) && (!pPSC->bSwRfProcessing)) {
+ ResetType = rtl819x_ifcheck_resetornot(dev);
+ check_reset_cnt = 3;
+ }
+ spin_unlock_irqrestore(&priv->tx_lock, flags);
+
+ if (!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_NORMAL) {
+ priv->ResetProgress = RESET_TYPE_NORMAL;
+ RT_TRACE(COMP_RESET, "%s(): NOMAL RESET\n", __func__);
+ return;
+ }
+
+ if (((priv->force_reset) || (!priv->bDisableNormalResetCheck &&
+ ResetType == RESET_TYPE_SILENT)))
+ rtl819x_ifsilentreset(dev);
+ priv->force_reset = false;
+ priv->bForcedSilentReset = false;
+ priv->bResetInProgress = false;
+ RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
+}
+
+void watch_dog_timer_callback(unsigned long data)
+{
+ struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
+
+ queue_delayed_work_rsl(priv->priv_wq, &priv->watch_dog_wq, 0);
+ mod_timer(&priv->watch_dog_timer, jiffies +
+ msecs_to_jiffies(RTLLIB_WATCH_DOG_TIME));
+}
+
+/****************************************************************************
+ ---------------------------- NIC TX/RX STUFF---------------------------
+*****************************************************************************/
+void rtl8192_rx_enable(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ priv->ops->rx_enable(dev);
+}
+
+void rtl8192_tx_enable(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ priv->ops->tx_enable(dev);
+
+ rtllib_reset_queue(priv->rtllib);
+}
+
+
+static void rtl8192_free_rx_ring(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int i, rx_queue_idx;
+
+ for (rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE;
+ rx_queue_idx++) {
+ for (i = 0; i < priv->rxringcount; i++) {
+ struct sk_buff *skb = priv->rx_buf[rx_queue_idx][i];
+
+ if (!skb)
+ continue;
+
+ pci_unmap_single(priv->pdev,
+ *((dma_addr_t *)skb->cb),
+ priv->rxbuffersize, PCI_DMA_FROMDEVICE);
+ kfree_skb(skb);
+ }
+
+ pci_free_consistent(priv->pdev,
+ sizeof(*priv->rx_ring[rx_queue_idx]) *
+ priv->rxringcount,
+ priv->rx_ring[rx_queue_idx],
+ priv->rx_ring_dma[rx_queue_idx]);
+ priv->rx_ring[rx_queue_idx] = NULL;
+ }
+}
+
+static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
+
+ while (skb_queue_len(&ring->queue)) {
+ struct tx_desc *entry = &ring->desc[ring->idx];
+ struct sk_buff *skb = __skb_dequeue(&ring->queue);
+
+ pci_unmap_single(priv->pdev, entry->TxBuffAddr,
+ skb->len, PCI_DMA_TODEVICE);
+ kfree_skb(skb);
+ ring->idx = (ring->idx + 1) % ring->entries;
+ }
+
+ pci_free_consistent(priv->pdev, sizeof(*ring->desc)*ring->entries,
+ ring->desc, ring->dma);
+ ring->desc = NULL;
+}
+
+void rtl8192_data_hard_stop(struct net_device *dev)
+{
+}
+
+
+void rtl8192_data_hard_resume(struct net_device *dev)
+{
+}
+
+void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
+ int rate)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ int ret;
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
+ MAX_DEV_ADDR_SIZE);
+ u8 queue_index = tcb_desc->queue_index;
+
+ if ((priv->rtllib->eRFPowerState == eRfOff) || !priv->up ||
+ priv->bResetInProgress) {
+ kfree_skb(skb);
+ return;
+ }
+
+ assert(queue_index != TXCMD_QUEUE);
+
+
+ memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
+ skb_push(skb, priv->rtllib->tx_headroom);
+ ret = rtl8192_tx(dev, skb);
+ if (ret != 0)
+ kfree_skb(skb);
+
+ if (queue_index != MGNT_QUEUE) {
+ priv->rtllib->stats.tx_bytes += (skb->len -
+ priv->rtllib->tx_headroom);
+ priv->rtllib->stats.tx_packets++;
+ }
+}
+
+int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ int ret;
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
+ MAX_DEV_ADDR_SIZE);
+ u8 queue_index = tcb_desc->queue_index;
+
+ if (queue_index != TXCMD_QUEUE) {
+ if ((priv->rtllib->eRFPowerState == eRfOff) ||
+ !priv->up || priv->bResetInProgress) {
+ kfree_skb(skb);
+ return 0;
+ }
+ }
+
+ memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
+ if (queue_index == TXCMD_QUEUE) {
+ rtl8192_tx_cmd(dev, skb);
+ return 0;
+ }
+
+ tcb_desc->RATRIndex = 7;
+ tcb_desc->bTxDisableRateFallBack = 1;
+ tcb_desc->bTxUseDriverAssingedRate = 1;
+ tcb_desc->bTxEnableFwCalcDur = 1;
+ skb_push(skb, priv->rtllib->tx_headroom);
+ ret = rtl8192_tx(dev, skb);
+ if (ret != 0)
+ kfree_skb(skb);
+ return ret;
+}
+
+static void rtl8192_tx_isr(struct net_device *dev, int prio)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
+
+ while (skb_queue_len(&ring->queue)) {
+ struct tx_desc *entry = &ring->desc[ring->idx];
+ struct sk_buff *skb;
+
+ if (prio != BEACON_QUEUE) {
+ if (entry->OWN)
+ return;
+ ring->idx = (ring->idx + 1) % ring->entries;
+ }
+
+ skb = __skb_dequeue(&ring->queue);
+ pci_unmap_single(priv->pdev, entry->TxBuffAddr,
+ skb->len, PCI_DMA_TODEVICE);
+
+ kfree_skb(skb);
+ }
+ if (prio != BEACON_QUEUE)
+ tasklet_schedule(&priv->irq_tx_tasklet);
+}
+
+void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtl8192_tx_ring *ring;
+ struct tx_desc_cmd *entry;
+ unsigned int idx;
+ struct cb_desc *tcb_desc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->irq_th_lock, flags);
+ ring = &priv->tx_ring[TXCMD_QUEUE];
+
+ idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
+ entry = (struct tx_desc_cmd *) &ring->desc[idx];
+
+ tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+
+ priv->ops->tx_fill_cmd_descriptor(dev, entry, tcb_desc, skb);
+
+ __skb_queue_tail(&ring->queue, skb);
+ spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+}
+
+short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtl8192_tx_ring *ring;
+ unsigned long flags;
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
+ MAX_DEV_ADDR_SIZE);
+ struct tx_desc *pdesc = NULL;
+ struct rtllib_hdr_1addr *header = NULL;
+ u16 fc = 0, type = 0, stype = 0;
+ bool multi_addr = false, broad_addr = false, uni_addr = false;
+ u8 *pda_addr = NULL;
+ int idx;
+ u32 fwinfo_size = 0;
+
+ if (priv->bdisable_nic) {
+ RT_TRACE(COMP_ERR,
+ "%s: ERR!! Nic is disabled! Can't tx packet len=%d qidx=%d!!!\n",
+ __func__, skb->len, tcb_desc->queue_index);
+ return skb->len;
+ }
+
+ priv->rtllib->bAwakePktSent = true;
+
+ fwinfo_size = sizeof(struct tx_fwinfo_8190pci);
+
+ header = (struct rtllib_hdr_1addr *)(((u8 *)skb->data) + fwinfo_size);
+ fc = le16_to_cpu(header->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+ pda_addr = header->addr1;
+
+ if (is_broadcast_ether_addr(pda_addr))
+ broad_addr = true;
+ else if (is_multicast_ether_addr(pda_addr))
+ multi_addr = true;
+ else
+ uni_addr = true;
+
+ if (uni_addr)
+ priv->stats.txbytesunicast += skb->len - fwinfo_size;
+ else if (multi_addr)
+ priv->stats.txbytesmulticast += skb->len - fwinfo_size;
+ else
+ priv->stats.txbytesbroadcast += skb->len - fwinfo_size;
+
+ spin_lock_irqsave(&priv->irq_th_lock, flags);
+ ring = &priv->tx_ring[tcb_desc->queue_index];
+ if (tcb_desc->queue_index != BEACON_QUEUE)
+ idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
+ else
+ idx = 0;
+
+ pdesc = &ring->desc[idx];
+ if ((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) {
+ RT_TRACE(COMP_ERR,
+ "No more TX desc@%d, ring->idx = %d, idx = %d, skblen = 0x%x queuelen=%d",
+ tcb_desc->queue_index, ring->idx, idx, skb->len,
+ skb_queue_len(&ring->queue));
+ spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+ return skb->len;
+ }
+
+ if (type == RTLLIB_FTYPE_DATA) {
+ if (priv->rtllib->LedControlHandler)
+ priv->rtllib->LedControlHandler(dev, LED_CTL_TX);
+ }
+ priv->ops->tx_fill_descriptor(dev, pdesc, tcb_desc, skb);
+ __skb_queue_tail(&ring->queue, skb);
+ pdesc->OWN = 1;
+ spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+ dev->trans_start = jiffies;
+
+ write_nic_word(dev, TPPoll, 0x01 << tcb_desc->queue_index);
+ return 0;
+}
+
+static short rtl8192_alloc_rx_desc_ring(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rx_desc *entry = NULL;
+ int i, rx_queue_idx;
+
+ for (rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx++) {
+ priv->rx_ring[rx_queue_idx] =
+ pci_zalloc_consistent(priv->pdev,
+ sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount,
+ &priv->rx_ring_dma[rx_queue_idx]);
+ if (!priv->rx_ring[rx_queue_idx] ||
+ (unsigned long)priv->rx_ring[rx_queue_idx] & 0xFF) {
+ RT_TRACE(COMP_ERR, "Cannot allocate RX ring\n");
+ return -ENOMEM;
+ }
+
+ priv->rx_idx[rx_queue_idx] = 0;
+
+ for (i = 0; i < priv->rxringcount; i++) {
+ struct sk_buff *skb = dev_alloc_skb(priv->rxbuffersize);
+ dma_addr_t *mapping;
+
+ entry = &priv->rx_ring[rx_queue_idx][i];
+ if (!skb)
+ return 0;
+ skb->dev = dev;
+ priv->rx_buf[rx_queue_idx][i] = skb;
+ mapping = (dma_addr_t *)skb->cb;
+ *mapping = pci_map_single(priv->pdev,
+ skb_tail_pointer_rsl(skb),
+ priv->rxbuffersize,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(priv->pdev, *mapping)) {
+ dev_kfree_skb_any(skb);
+ return -1;
+ }
+ entry->BufferAddress = *mapping;
+
+ entry->Length = priv->rxbuffersize;
+ entry->OWN = 1;
+ }
+
+ if(entry)
+ entry->EOR = 1;
+ }
+ return 0;
+}
+
+static int rtl8192_alloc_tx_desc_ring(struct net_device *dev,
+ unsigned int prio, unsigned int entries)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ struct tx_desc *ring;
+ dma_addr_t dma;
+ int i;
+
+ ring = pci_zalloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
+ if (!ring || (unsigned long)ring & 0xFF) {
+ RT_TRACE(COMP_ERR, "Cannot allocate TX ring (prio = %d)\n",
+ prio);
+ return -ENOMEM;
+ }
+
+ priv->tx_ring[prio].desc = ring;
+ priv->tx_ring[prio].dma = dma;
+ priv->tx_ring[prio].idx = 0;
+ priv->tx_ring[prio].entries = entries;
+ skb_queue_head_init(&priv->tx_ring[prio].queue);
+
+ for (i = 0; i < entries; i++)
+ ring[i].NextDescAddress =
+ (u32)dma + ((i + 1) % entries) *
+ sizeof(*ring);
+
+ return 0;
+}
+
+
+short rtl8192_pci_initdescring(struct net_device *dev)
+{
+ u32 ret;
+ int i;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ ret = rtl8192_alloc_rx_desc_ring(dev);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
+ ret = rtl8192_alloc_tx_desc_ring(dev, i, priv->txringcount);
+ if (ret)
+ goto err_free_rings;
+ }
+
+ return 0;
+
+err_free_rings:
+ rtl8192_free_rx_ring(dev);
+ for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
+ if (priv->tx_ring[i].desc)
+ rtl8192_free_tx_ring(dev, i);
+ return 1;
+}
+
+void rtl8192_pci_resetdescring(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int i, rx_queue_idx;
+ unsigned long flags = 0;
+
+ for (rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx++) {
+ if (priv->rx_ring[rx_queue_idx]) {
+ struct rx_desc *entry = NULL;
+
+ for (i = 0; i < priv->rxringcount; i++) {
+ entry = &priv->rx_ring[rx_queue_idx][i];
+ entry->OWN = 1;
+ }
+ priv->rx_idx[rx_queue_idx] = 0;
+ }
+ }
+
+ spin_lock_irqsave(&priv->irq_th_lock, flags);
+ for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
+ if (priv->tx_ring[i].desc) {
+ struct rtl8192_tx_ring *ring = &priv->tx_ring[i];
+
+ while (skb_queue_len(&ring->queue)) {
+ struct tx_desc *entry = &ring->desc[ring->idx];
+ struct sk_buff *skb =
+ __skb_dequeue(&ring->queue);
+
+ pci_unmap_single(priv->pdev,
+ entry->TxBuffAddr,
+ skb->len, PCI_DMA_TODEVICE);
+ kfree_skb(skb);
+ ring->idx = (ring->idx + 1) % ring->entries;
+ }
+ ring->idx = 0;
+ }
+ }
+ spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+}
+
+void rtl819x_UpdateRxPktTimeStamp(struct net_device *dev,
+ struct rtllib_rx_stats *stats)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ if (stats->bIsAMPDU && !stats->bFirstMPDU)
+ stats->mac_time = priv->LastRxDescTSF;
+ else
+ priv->LastRxDescTSF = stats->mac_time;
+}
+
+long rtl819x_translate_todbm(struct r8192_priv *priv, u8 signal_strength_index)
+{
+ long signal_power;
+
+ signal_power = (long)((signal_strength_index + 1) >> 1);
+ signal_power -= 95;
+
+ return signal_power;
+}
+
+
+void
+rtl819x_update_rxsignalstatistics8190pci(
+ struct r8192_priv *priv,
+ struct rtllib_rx_stats *pprevious_stats
+ )
+{
+ int weighting = 0;
+
+
+ if (priv->stats.recv_signal_power == 0)
+ priv->stats.recv_signal_power =
+ pprevious_stats->RecvSignalPower;
+
+ if (pprevious_stats->RecvSignalPower > priv->stats.recv_signal_power)
+ weighting = 5;
+ else if (pprevious_stats->RecvSignalPower <
+ priv->stats.recv_signal_power)
+ weighting = (-5);
+ priv->stats.recv_signal_power = (priv->stats.recv_signal_power * 5 +
+ pprevious_stats->RecvSignalPower +
+ weighting) / 6;
+}
+
+void rtl819x_process_cck_rxpathsel(struct r8192_priv *priv,
+ struct rtllib_rx_stats *pprevious_stats)
+{
+}
+
+
+u8 rtl819x_query_rxpwrpercentage(char antpower)
+{
+ if ((antpower <= -100) || (antpower >= 20))
+ return 0;
+ else if (antpower >= 0)
+ return 100;
+ else
+ return 100 + antpower;
+
+} /* QueryRxPwrPercentage */
+
+u8
+rtl819x_evm_dbtopercentage(
+ char value
+ )
+{
+ char ret_val;
+
+ ret_val = value;
+
+ if (ret_val >= 0)
+ ret_val = 0;
+ if (ret_val <= -33)
+ ret_val = -33;
+ ret_val = 0 - ret_val;
+ ret_val *= 3;
+ if (ret_val == 99)
+ ret_val = 100;
+ return ret_val;
+}
+
+void
+rtl8192_record_rxdesc_forlateruse(
+ struct rtllib_rx_stats *psrc_stats,
+ struct rtllib_rx_stats *ptarget_stats
+)
+{
+ ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
+ ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
+}
+
+
+
+static void rtl8192_rx_normal(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ struct rtllib_hdr_1addr *rtllib_hdr = NULL;
+ bool unicast_packet = false;
+ bool bLedBlinking = true;
+ u16 fc = 0, type = 0;
+ u32 skb_len = 0;
+ int rx_queue_idx = RX_MPDU_QUEUE;
+
+ struct rtllib_rx_stats stats = {
+ .signal = 0,
+ .noise = -98,
+ .rate = 0,
+ .freq = RTLLIB_24GHZ_BAND,
+ };
+ unsigned int count = priv->rxringcount;
+
+ stats.nic_type = NIC_8192E;
+
+ while (count--) {
+ struct rx_desc *pdesc = &priv->rx_ring[rx_queue_idx]
+ [priv->rx_idx[rx_queue_idx]];
+ struct sk_buff *skb = priv->rx_buf[rx_queue_idx]
+ [priv->rx_idx[rx_queue_idx]];
+ struct sk_buff *new_skb;
+
+ if (pdesc->OWN)
+ return;
+ if (!priv->ops->rx_query_status_descriptor(dev, &stats,
+ pdesc, skb))
+ goto done;
+ new_skb = dev_alloc_skb(priv->rxbuffersize);
+ /* if allocation of new skb failed - drop current packet
+ * and reuse skb
+ */
+ if (unlikely(!new_skb))
+ goto done;
+
+ pci_unmap_single(priv->pdev,
+ *((dma_addr_t *)skb->cb),
+ priv->rxbuffersize,
+ PCI_DMA_FROMDEVICE);
+
+ skb_put(skb, pdesc->Length);
+ skb_reserve(skb, stats.RxDrvInfoSize +
+ stats.RxBufShift);
+ skb_trim(skb, skb->len - 4/*sCrcLng*/);
+ rtllib_hdr = (struct rtllib_hdr_1addr *)skb->data;
+ if (!is_multicast_ether_addr(rtllib_hdr->addr1)) {
+ /* unicast packet */
+ unicast_packet = true;
+ }
+ fc = le16_to_cpu(rtllib_hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ if (type == RTLLIB_FTYPE_MGMT)
+ bLedBlinking = false;
+
+ if (bLedBlinking)
+ if (priv->rtllib->LedControlHandler)
+ priv->rtllib->LedControlHandler(dev,
+ LED_CTL_RX);
+
+ if (stats.bCRC) {
+ if (type != RTLLIB_FTYPE_MGMT)
+ priv->stats.rxdatacrcerr++;
+ else
+ priv->stats.rxmgmtcrcerr++;
+ }
+
+ skb_len = skb->len;
+
+ if (!rtllib_rx(priv->rtllib, skb, &stats)) {
+ dev_kfree_skb_any(skb);
+ } else {
+ priv->stats.rxok++;
+ if (unicast_packet)
+ priv->stats.rxbytesunicast += skb_len;
+ }
+
+ skb = new_skb;
+ skb->dev = dev;
+
+ priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]] =
+ skb;
+ *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev,
+ skb_tail_pointer_rsl(skb),
+ priv->rxbuffersize,
+ PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(priv->pdev,
+ *((dma_addr_t *)skb->cb))) {
+ dev_kfree_skb_any(skb);
+ return;
+ }
+done:
+ pdesc->BufferAddress = *((dma_addr_t *)skb->cb);
+ pdesc->OWN = 1;
+ pdesc->Length = priv->rxbuffersize;
+ if (priv->rx_idx[rx_queue_idx] == priv->rxringcount-1)
+ pdesc->EOR = 1;
+ priv->rx_idx[rx_queue_idx] = (priv->rx_idx[rx_queue_idx] + 1) %
+ priv->rxringcount;
+ }
+
+}
+
+static void rtl8192_rx_cmd(struct net_device *dev)
+{
+}
+
+
+static void rtl8192_tx_resume(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+ struct sk_buff *skb;
+ int queue_index;
+
+ for (queue_index = BK_QUEUE;
+ queue_index < MAX_QUEUE_SIZE; queue_index++) {
+ while ((!skb_queue_empty(&ieee->skb_waitQ[queue_index])) &&
+ (priv->rtllib->check_nic_enough_desc(dev, queue_index) > 0)) {
+ skb = skb_dequeue(&ieee->skb_waitQ[queue_index]);
+ ieee->softmac_data_hard_start_xmit(skb, dev, 0);
+ }
+ }
+}
+
+void rtl8192_irq_tx_tasklet(struct r8192_priv *priv)
+{
+ rtl8192_tx_resume(priv->rtllib->dev);
+}
+
+void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
+{
+ rtl8192_rx_normal(priv->rtllib->dev);
+
+ if (MAX_RX_QUEUE > 1)
+ rtl8192_rx_cmd(priv->rtllib->dev);
+
+ write_nic_dword(priv->rtllib->dev, INTA_MASK,
+ read_nic_dword(priv->rtllib->dev, INTA_MASK) | IMR_RDU);
+}
+
+/****************************************************************************
+ ---------------------------- NIC START/CLOSE STUFF---------------------------
+*****************************************************************************/
+void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
+{
+ cancel_delayed_work(&priv->watch_dog_wq);
+ cancel_delayed_work(&priv->update_beacon_wq);
+ cancel_delayed_work(&priv->rtllib->hw_sleep_wq);
+ cancel_work_sync(&priv->reset_wq);
+ cancel_work_sync(&priv->qos_activate);
+}
+
+int _rtl8192_up(struct net_device *dev, bool is_silent_reset)
+{
+ if (_rtl8192_sta_up(dev, is_silent_reset) == -1)
+ return -1;
+ return 0;
+}
+
+
+static int rtl8192_open(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int ret;
+
+ down(&priv->wx_sem);
+ ret = rtl8192_up(dev);
+ up(&priv->wx_sem);
+ return ret;
+
+}
+
+
+int rtl8192_up(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->up == 1)
+ return -1;
+ return _rtl8192_up(dev, false);
+}
+
+
+static int rtl8192_close(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int ret;
+
+ if ((rtllib_act_scanning(priv->rtllib, false)) &&
+ !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)) {
+ rtllib_stop_scan(priv->rtllib);
+ }
+
+ down(&priv->wx_sem);
+
+ ret = rtl8192_down(dev, true);
+
+ up(&priv->wx_sem);
+
+ return ret;
+
+}
+
+int rtl8192_down(struct net_device *dev, bool shutdownrf)
+{
+ if (rtl8192_sta_down(dev, shutdownrf) == -1)
+ return -1;
+
+ return 0;
+}
+
+void rtl8192_commit(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->up == 0)
+ return;
+ rtllib_softmac_stop_protocol(priv->rtllib, 0 , true);
+ rtl8192_irq_disable(dev);
+ priv->ops->stop_adapter(dev, true);
+ _rtl8192_up(dev, false);
+}
+
+void rtl8192_restart(void *data)
+{
+ struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv,
+ reset_wq);
+ struct net_device *dev = priv->rtllib->dev;
+
+ down(&priv->wx_sem);
+
+ rtl8192_commit(dev);
+
+ up(&priv->wx_sem);
+}
+
+static void r8192_set_multicast(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ short promisc;
+
+ promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
+ priv->promisc = promisc;
+
+}
+
+
+static int r8192_set_mac_adr(struct net_device *dev, void *mac)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct sockaddr *addr = mac;
+
+ down(&priv->wx_sem);
+
+ ether_addr_copy(dev->dev_addr, addr->sa_data);
+
+ schedule_work(&priv->reset_wq);
+ up(&priv->wx_sem);
+
+ return 0;
+}
+
+/* based on ipw2200 driver */
+static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ struct iwreq *wrq = (struct iwreq *)rq;
+ int ret = -1;
+ struct rtllib_device *ieee = priv->rtllib;
+ u32 key[4];
+ u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ u8 zero_addr[6] = {0};
+ struct iw_point *p = &wrq->u.data;
+ struct ieee_param *ipw = NULL;
+
+ down(&priv->wx_sem);
+
+ switch (cmd) {
+ case RTL_IOCTL_WPA_SUPPLICANT:
+ if (p->length < sizeof(struct ieee_param) || !p->pointer) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ipw = memdup_user(p->pointer, p->length);
+ if (IS_ERR(ipw)) {
+ ret = PTR_ERR(ipw);
+ goto out;
+ }
+
+ if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) {
+ if (ipw->u.crypt.set_tx) {
+ if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
+ ieee->pairwise_key_type = KEY_TYPE_CCMP;
+ else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
+ ieee->pairwise_key_type = KEY_TYPE_TKIP;
+ else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
+ if (ipw->u.crypt.key_len == 13)
+ ieee->pairwise_key_type =
+ KEY_TYPE_WEP104;
+ else if (ipw->u.crypt.key_len == 5)
+ ieee->pairwise_key_type =
+ KEY_TYPE_WEP40;
+ } else {
+ ieee->pairwise_key_type = KEY_TYPE_NA;
+ }
+
+ if (ieee->pairwise_key_type) {
+ if (memcmp(ieee->ap_mac_addr, zero_addr,
+ 6) == 0)
+ ieee->iw_mode = IW_MODE_ADHOC;
+ memcpy((u8 *)key, ipw->u.crypt.key, 16);
+ EnableHWSecurityConfig8192(dev);
+ set_swcam(dev, 4, ipw->u.crypt.idx,
+ ieee->pairwise_key_type,
+ (u8 *)ieee->ap_mac_addr,
+ 0, key, 0);
+ setKey(dev, 4, ipw->u.crypt.idx,
+ ieee->pairwise_key_type,
+ (u8 *)ieee->ap_mac_addr, 0, key);
+ if (ieee->iw_mode == IW_MODE_ADHOC) {
+ set_swcam(dev, ipw->u.crypt.idx,
+ ipw->u.crypt.idx,
+ ieee->pairwise_key_type,
+ (u8 *)ieee->ap_mac_addr,
+ 0, key, 0);
+ setKey(dev, ipw->u.crypt.idx,
+ ipw->u.crypt.idx,
+ ieee->pairwise_key_type,
+ (u8 *)ieee->ap_mac_addr,
+ 0, key);
+ }
+ }
+ if ((ieee->pairwise_key_type == KEY_TYPE_CCMP)
+ && ieee->pHTInfo->bCurrentHTSupport) {
+ write_nic_byte(dev, 0x173, 1);
+ }
+
+ } else {
+ memcpy((u8 *)key, ipw->u.crypt.key, 16);
+ if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
+ ieee->group_key_type = KEY_TYPE_CCMP;
+ else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
+ ieee->group_key_type = KEY_TYPE_TKIP;
+ else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
+ if (ipw->u.crypt.key_len == 13)
+ ieee->group_key_type =
+ KEY_TYPE_WEP104;
+ else if (ipw->u.crypt.key_len == 5)
+ ieee->group_key_type =
+ KEY_TYPE_WEP40;
+ } else
+ ieee->group_key_type = KEY_TYPE_NA;
+
+ if (ieee->group_key_type) {
+ set_swcam(dev, ipw->u.crypt.idx,
+ ipw->u.crypt.idx,
+ ieee->group_key_type,
+ broadcast_addr, 0, key, 0);
+ setKey(dev, ipw->u.crypt.idx,
+ ipw->u.crypt.idx,
+ ieee->group_key_type,
+ broadcast_addr, 0, key);
+ }
+ }
+ }
+
+ ret = rtllib_wpa_supplicant_ioctl(priv->rtllib, &wrq->u.data,
+ 0);
+ kfree(ipw);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+out:
+ up(&priv->wx_sem);
+
+ return ret;
+}
+
+
+static irqreturn_t rtl8192_interrupt(int irq, void *netdev)
+{
+ struct net_device *dev = (struct net_device *) netdev;
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ unsigned long flags;
+ u32 inta;
+ u32 intb;
+
+ intb = 0;
+
+ if (priv->irq_enabled == 0)
+ goto done;
+
+ spin_lock_irqsave(&priv->irq_th_lock, flags);
+
+ priv->ops->interrupt_recognized(dev, &inta, &intb);
+ priv->stats.shints++;
+
+ if (!inta) {
+ spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+ goto done;
+ }
+
+ if (inta == 0xffff) {
+ spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+ goto done;
+ }
+
+ priv->stats.ints++;
+
+ if (!netif_running(dev)) {
+ spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+ goto done;
+ }
+
+ if (inta & IMR_TBDOK) {
+ RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
+ priv->stats.txbeaconokint++;
+ }
+
+ if (inta & IMR_TBDER) {
+ RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
+ priv->stats.txbeaconerr++;
+ }
+
+ if (inta & IMR_BDOK)
+ RT_TRACE(COMP_INTR, "beacon interrupt!\n");
+
+ if (inta & IMR_MGNTDOK) {
+ RT_TRACE(COMP_INTR, "Manage ok interrupt!\n");
+ priv->stats.txmanageokint++;
+ rtl8192_tx_isr(dev, MGNT_QUEUE);
+ spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+ if (priv->rtllib->ack_tx_to_ieee) {
+ if (rtl8192_is_tx_queue_empty(dev)) {
+ priv->rtllib->ack_tx_to_ieee = 0;
+ rtllib_ps_tx_ack(priv->rtllib, 1);
+ }
+ }
+ spin_lock_irqsave(&priv->irq_th_lock, flags);
+ }
+
+ if (inta & IMR_COMDOK) {
+ priv->stats.txcmdpktokint++;
+ rtl8192_tx_isr(dev, TXCMD_QUEUE);
+ }
+
+ if (inta & IMR_HIGHDOK)
+ rtl8192_tx_isr(dev, HIGH_QUEUE);
+
+ if (inta & IMR_ROK) {
+ priv->stats.rxint++;
+ priv->InterruptLog.nIMR_ROK++;
+ tasklet_schedule(&priv->irq_rx_tasklet);
+ }
+
+ if (inta & IMR_BcnInt) {
+ RT_TRACE(COMP_INTR, "prepare beacon for interrupt!\n");
+ tasklet_schedule(&priv->irq_prepare_beacon_tasklet);
+ }
+
+ if (inta & IMR_RDU) {
+ RT_TRACE(COMP_INTR, "rx descriptor unavailable!\n");
+ priv->stats.rxrdu++;
+ write_nic_dword(dev, INTA_MASK,
+ read_nic_dword(dev, INTA_MASK) & ~IMR_RDU);
+ tasklet_schedule(&priv->irq_rx_tasklet);
+ }
+
+ if (inta & IMR_RXFOVW) {
+ RT_TRACE(COMP_INTR, "rx overflow !\n");
+ priv->stats.rxoverflow++;
+ tasklet_schedule(&priv->irq_rx_tasklet);
+ }
+
+ if (inta & IMR_TXFOVW)
+ priv->stats.txoverflow++;
+
+ if (inta & IMR_BKDOK) {
+ RT_TRACE(COMP_INTR, "BK Tx OK interrupt!\n");
+ priv->stats.txbkokint++;
+ priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++;
+ rtl8192_tx_isr(dev, BK_QUEUE);
+ }
+
+ if (inta & IMR_BEDOK) {
+ RT_TRACE(COMP_INTR, "BE TX OK interrupt!\n");
+ priv->stats.txbeokint++;
+ priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++;
+ rtl8192_tx_isr(dev, BE_QUEUE);
+ }
+
+ if (inta & IMR_VIDOK) {
+ RT_TRACE(COMP_INTR, "VI TX OK interrupt!\n");
+ priv->stats.txviokint++;
+ priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++;
+ rtl8192_tx_isr(dev, VI_QUEUE);
+ }
+
+ if (inta & IMR_VODOK) {
+ priv->stats.txvookint++;
+ RT_TRACE(COMP_INTR, "Vo TX OK interrupt!\n");
+ priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++;
+ rtl8192_tx_isr(dev, VO_QUEUE);
+ }
+
+ spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+
+done:
+
+ return IRQ_HANDLED;
+}
+
+
+
+/****************************************************************************
+ ---------------------------- PCI_STUFF---------------------------
+*****************************************************************************/
+static const struct net_device_ops rtl8192_netdev_ops = {
+ .ndo_open = rtl8192_open,
+ .ndo_stop = rtl8192_close,
+ .ndo_tx_timeout = rtl8192_tx_timeout,
+ .ndo_do_ioctl = rtl8192_ioctl,
+ .ndo_set_rx_mode = r8192_set_multicast,
+ .ndo_set_mac_address = r8192_set_mac_adr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_start_xmit = rtllib_xmit,
+};
+
+static int rtl8192_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ unsigned long ioaddr = 0;
+ struct net_device *dev = NULL;
+ struct r8192_priv *priv = NULL;
+ struct rtl819x_ops *ops = (struct rtl819x_ops *)(id->driver_data);
+ unsigned long pmem_start, pmem_len, pmem_flags;
+ int err = -ENOMEM;
+ bool bdma64 = false;
+ u8 revision_id;
+
+ RT_TRACE(COMP_INIT, "Configuring chip resources");
+
+ if (pci_enable_device(pdev)) {
+ RT_TRACE(COMP_ERR, "Failed to enable PCI device");
+ return -EIO;
+ }
+
+ pci_set_master(pdev);
+
+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
+ dev_info(&pdev->dev,
+ "Unable to obtain 32bit DMA for consistent allocations\n");
+ goto err_pci_disable;
+ }
+ }
+ dev = alloc_rtllib(sizeof(struct r8192_priv));
+ if (!dev)
+ goto err_pci_disable;
+
+ err = -ENODEV;
+ if (bdma64)
+ dev->features |= NETIF_F_HIGHDMA;
+
+ pci_set_drvdata(pdev, dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ priv = rtllib_priv(dev);
+ priv->rtllib = (struct rtllib_device *)netdev_priv_rsl(dev);
+ priv->pdev = pdev;
+ priv->rtllib->pdev = pdev;
+ if ((pdev->subsystem_vendor == PCI_VENDOR_ID_DLINK) &&
+ (pdev->subsystem_device == 0x3304))
+ priv->rtllib->bSupportRemoteWakeUp = 1;
+ else
+ priv->rtllib->bSupportRemoteWakeUp = 0;
+
+ pmem_start = pci_resource_start(pdev, 1);
+ pmem_len = pci_resource_len(pdev, 1);
+ pmem_flags = pci_resource_flags(pdev, 1);
+
+ if (!(pmem_flags & IORESOURCE_MEM)) {
+ RT_TRACE(COMP_ERR, "region #1 not a MMIO resource, aborting");
+ goto err_rel_rtllib;
+ }
+
+ dev_info(&pdev->dev, "Memory mapped space start: 0x%08lx\n",
+ pmem_start);
+ if (!request_mem_region(pmem_start, pmem_len, DRV_NAME)) {
+ RT_TRACE(COMP_ERR, "request_mem_region failed!");
+ goto err_rel_rtllib;
+ }
+
+
+ ioaddr = (unsigned long)ioremap_nocache(pmem_start, pmem_len);
+ if (ioaddr == (unsigned long)NULL) {
+ RT_TRACE(COMP_ERR, "ioremap failed!");
+ goto err_rel_mem;
+ }
+
+ dev->mem_start = ioaddr;
+ dev->mem_end = ioaddr + pci_resource_len(pdev, 0);
+
+ pci_read_config_byte(pdev, 0x08, &revision_id);
+ /* If the revisionid is 0x10, the device uses rtl8192se. */
+ if (pdev->device == 0x8192 && revision_id == 0x10)
+ goto err_rel_mem;
+
+ priv->ops = ops;
+
+ if (rtl8192_pci_findadapter(pdev, dev) == false)
+ goto err_rel_mem;
+
+ dev->irq = pdev->irq;
+ priv->irq = 0;
+
+ dev->netdev_ops = &rtl8192_netdev_ops;
+
+ dev->wireless_handlers = &r8192_wx_handlers_def;
+ dev->ethtool_ops = &rtl819x_ethtool_ops;
+
+ dev->type = ARPHRD_ETHER;
+ dev->watchdog_timeo = HZ * 3;
+
+ if (dev_alloc_name(dev, ifname) < 0) {
+ RT_TRACE(COMP_INIT,
+ "Oops: devname already taken! Trying wlan%%d...\n");
+ dev_alloc_name(dev, ifname);
+ }
+
+ RT_TRACE(COMP_INIT, "Driver probe completed1\n");
+ if (rtl8192_init(dev) != 0) {
+ RT_TRACE(COMP_ERR, "Initialization failed");
+ goto err_free_irq;
+ }
+
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+
+ if (register_netdev(dev))
+ goto err_free_irq;
+ RT_TRACE(COMP_INIT, "dev name: %s\n", dev->name);
+
+ if (priv->polling_timer_on == 0)
+ check_rfctrl_gpio_timer((unsigned long)dev);
+
+ RT_TRACE(COMP_INIT, "Driver probe completed\n");
+ return 0;
+
+err_free_irq:
+ free_irq(dev->irq, dev);
+ priv->irq = 0;
+err_rel_mem:
+ release_mem_region(pmem_start, pmem_len);
+err_rel_rtllib:
+ free_rtllib(dev);
+
+ DMESG("wlan driver load failed\n");
+err_pci_disable:
+ pci_disable_device(pdev);
+ return err;
+}
+
+static void rtl8192_pci_disconnect(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct r8192_priv *priv;
+ u32 i;
+
+ if (dev) {
+ unregister_netdev(dev);
+
+ priv = rtllib_priv(dev);
+
+ del_timer_sync(&priv->gpio_polling_timer);
+ cancel_delayed_work(&priv->gpio_change_rf_wq);
+ priv->polling_timer_on = 0;
+ rtl8192_down(dev, true);
+ deinit_hal_dm(dev);
+ if (priv->pFirmware) {
+ vfree(priv->pFirmware);
+ priv->pFirmware = NULL;
+ }
+ destroy_workqueue(priv->priv_wq);
+ rtl8192_free_rx_ring(dev);
+ for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
+ rtl8192_free_tx_ring(dev, i);
+
+ if (priv->irq) {
+ dev_info(&pdev->dev, "Freeing irq %d\n", dev->irq);
+ free_irq(dev->irq, dev);
+ priv->irq = 0;
+ }
+ free_rtllib(dev);
+
+ kfree(priv->scan_cmd);
+
+ if (dev->mem_start != 0) {
+ iounmap((void __iomem *)dev->mem_start);
+ release_mem_region(pci_resource_start(pdev, 1),
+ pci_resource_len(pdev, 1));
+ }
+ } else {
+ priv = rtllib_priv(dev);
+ }
+
+ pci_disable_device(pdev);
+ RT_TRACE(COMP_DOWN, "wlan driver removed\n");
+}
+
+bool NicIFEnableNIC(struct net_device *dev)
+{
+ bool init_status = true;
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ (&(priv->rtllib->PowerSaveControl));
+
+ if (!priv->up) {
+ RT_TRACE(COMP_ERR, "ERR!!! %s(): Driver is already down!\n",
+ __func__);
+ priv->bdisable_nic = false;
+ return false;
+ }
+
+ RT_TRACE(COMP_PS, "===========>%s()\n", __func__);
+ priv->bfirst_init = true;
+ init_status = priv->ops->initialize_adapter(dev);
+ if (!init_status) {
+ RT_TRACE(COMP_ERR, "ERR!!! %s(): initialization is failed!\n",
+ __func__);
+ priv->bdisable_nic = false;
+ return false;
+ }
+ RT_TRACE(COMP_INIT, "start adapter finished\n");
+ RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+ priv->bfirst_init = false;
+
+ rtl8192_irq_enable(dev);
+ priv->bdisable_nic = false;
+ RT_TRACE(COMP_PS, "<===========%s()\n", __func__);
+ return init_status;
+}
+bool NicIFDisableNIC(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 tmp_state = 0;
+
+ RT_TRACE(COMP_PS, "=========>%s()\n", __func__);
+ priv->bdisable_nic = true;
+ tmp_state = priv->rtllib->state;
+ rtllib_softmac_stop_protocol(priv->rtllib, 0, false);
+ priv->rtllib->state = tmp_state;
+ rtl8192_cancel_deferred_work(priv);
+ rtl8192_irq_disable(dev);
+
+ priv->ops->stop_adapter(dev, false);
+ RT_TRACE(COMP_PS, "<=========%s()\n", __func__);
+
+ return true;
+}
+
+static int __init rtl8192_pci_module_init(void)
+{
+ pr_info("\nLinux kernel driver for RTL8192E WLAN cards\n");
+ pr_info("Copyright (c) 2007-2008, Realsil Wlan Driver\n");
+
+ if (0 != pci_register_driver(&rtl8192_pci_driver)) {
+ DMESG("No device found");
+ /*pci_unregister_driver (&rtl8192_pci_driver);*/
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static void __exit rtl8192_pci_module_exit(void)
+{
+ pci_unregister_driver(&rtl8192_pci_driver);
+
+ RT_TRACE(COMP_DOWN, "Exiting");
+}
+
+void check_rfctrl_gpio_timer(unsigned long data)
+{
+ struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
+
+ priv->polling_timer_on = 1;
+
+ queue_delayed_work_rsl(priv->priv_wq, &priv->gpio_change_rf_wq, 0);
+
+ mod_timer(&priv->gpio_polling_timer, jiffies +
+ msecs_to_jiffies(RTLLIB_WATCH_DOG_TIME));
+}
+
+/***************************************************************************
+ ------------------- module init / exit stubs ----------------
+****************************************************************************/
+module_init(rtl8192_pci_module_init);
+module_exit(rtl8192_pci_module_exit);
+
+MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards");
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+/*(DEBLOBBED)*/
+
+module_param(ifname, charp, S_IRUGO|S_IWUSR);
+module_param(hwwep, int, S_IRUGO|S_IWUSR);
+module_param(channels, int, S_IRUGO|S_IWUSR);
+
+MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default");
+MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support(default use hw. set 0 to use software security)");
+MODULE_PARM_DESC(channels, " Channel bitmask for specific locales. NYI");
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
new file mode 100644
index 000000000..d365af6eb
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
@@ -0,0 +1,1076 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifndef _RTL_CORE_H
+#define _RTL_CORE_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/rtnetlink.h>
+#include <linux/wireless.h>
+#include <linux/timer.h>
+#include <linux/proc_fs.h>
+#include <linux/if_arp.h>
+#include <linux/random.h>
+#include <linux/io.h>
+
+/* Need this defined before including local include files */
+#define DRV_NAME "rtl819xE"
+
+#include "../rtllib.h"
+
+#include "../dot11d.h"
+
+#include "r8192E_firmware.h"
+#include "r8192E_hw.h"
+
+#include "r8190P_def.h"
+#include "r8192E_dev.h"
+
+#include "rtl_eeprom.h"
+#include "rtl_ps.h"
+#include "rtl_pci.h"
+#include "rtl_cam.h"
+
+#define DRV_COPYRIGHT \
+ "Copyright(c) 2008 - 2010 Realsil Semiconductor Corporation"
+#define DRV_AUTHOR "<wlanfae@realtek.com>"
+#define DRV_VERSION "0014.0401.2010"
+
+#define IS_HARDWARE_TYPE_819xP(_priv) \
+ ((((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8190P) || \
+ (((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8192E))
+#define IS_HARDWARE_TYPE_8192SE(_priv) \
+ (((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8192SE)
+#define IS_HARDWARE_TYPE_8192CE(_priv) \
+ (((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8192CE)
+#define IS_HARDWARE_TYPE_8192CU(_priv) \
+ (((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8192CU)
+#define IS_HARDWARE_TYPE_8192DE(_priv) \
+ (((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8192DE)
+#define IS_HARDWARE_TYPE_8192DU(_priv) \
+ (((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8192DU)
+
+#define RTL_PCI_DEVICE(vend, dev, cfg) \
+ .vendor = (vend), .device = (dev), \
+ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID , \
+ .driver_data = (kernel_ulong_t)&(cfg)
+
+#define RTL_MAX_SCAN_SIZE 128
+
+#define RTL_RATE_MAX 30
+
+#define TOTAL_CAM_ENTRY 32
+#define CAM_CONTENT_COUNT 8
+
+#ifndef BIT
+#define BIT(_i) (1<<(_i))
+#endif
+
+#define IS_ADAPTER_SENDS_BEACON(dev) 0
+
+#define HAL_MEMORY_MAPPED_IO_RANGE_8190PCI 0x1000
+#define HAL_HW_PCI_REVISION_ID_8190PCI 0x00
+#define HAL_MEMORY_MAPPED_IO_RANGE_8192PCIE 0x4000
+#define HAL_HW_PCI_REVISION_ID_8192PCIE 0x01
+#define HAL_MEMORY_MAPPED_IO_RANGE_8192SE 0x4000
+#define HAL_HW_PCI_REVISION_ID_8192SE 0x10
+#define HAL_HW_PCI_REVISION_ID_8192CE 0x1
+#define HAL_MEMORY_MAPPED_IO_RANGE_8192CE 0x4000
+#define HAL_HW_PCI_REVISION_ID_8192DE 0x0
+#define HAL_MEMORY_MAPPED_IO_RANGE_8192DE 0x4000
+
+#define HAL_HW_PCI_8180_DEVICE_ID 0x8180
+#define HAL_HW_PCI_8185_DEVICE_ID 0x8185
+#define HAL_HW_PCI_8188_DEVICE_ID 0x8188
+#define HAL_HW_PCI_8198_DEVICE_ID 0x8198
+#define HAL_HW_PCI_8190_DEVICE_ID 0x8190
+#define HAL_HW_PCI_8192_DEVICE_ID 0x8192
+#define HAL_HW_PCI_8192SE_DEVICE_ID 0x8192
+#define HAL_HW_PCI_8174_DEVICE_ID 0x8174
+#define HAL_HW_PCI_8173_DEVICE_ID 0x8173
+#define HAL_HW_PCI_8172_DEVICE_ID 0x8172
+#define HAL_HW_PCI_8171_DEVICE_ID 0x8171
+#define HAL_HW_PCI_0045_DEVICE_ID 0x0045
+#define HAL_HW_PCI_0046_DEVICE_ID 0x0046
+#define HAL_HW_PCI_0044_DEVICE_ID 0x0044
+#define HAL_HW_PCI_0047_DEVICE_ID 0x0047
+#define HAL_HW_PCI_700F_DEVICE_ID 0x700F
+#define HAL_HW_PCI_701F_DEVICE_ID 0x701F
+#define HAL_HW_PCI_DLINK_DEVICE_ID 0x3304
+#define HAL_HW_PCI_8192CET_DEVICE_ID 0x8191
+#define HAL_HW_PCI_8192CE_DEVICE_ID 0x8178
+#define HAL_HW_PCI_8191CE_DEVICE_ID 0x8177
+#define HAL_HW_PCI_8188CE_DEVICE_ID 0x8176
+#define HAL_HW_PCI_8192CU_DEVICE_ID 0x8191
+#define HAL_HW_PCI_8192DE_DEVICE_ID 0x092D
+#define HAL_HW_PCI_8192DU_DEVICE_ID 0x092D
+
+#define RTL819X_DEFAULT_RF_TYPE RF_1T2R
+
+#define RTLLIB_WATCH_DOG_TIME 2000
+
+#define MAX_DEV_ADDR_SIZE 8 /*support till 64 bit bus width OS*/
+#define MAX_FIRMWARE_INFORMATION_SIZE 32
+#define MAX_802_11_HEADER_LENGTH (40 + MAX_FIRMWARE_INFORMATION_SIZE)
+#define ENCRYPTION_MAX_OVERHEAD 128
+#define MAX_FRAGMENT_COUNT 8
+#define MAX_TRANSMIT_BUFFER_SIZE \
+ (1600 + (MAX_802_11_HEADER_LENGTH + ENCRYPTION_MAX_OVERHEAD) * \
+ MAX_FRAGMENT_COUNT)
+
+#define scrclng 4
+
+#define DEFAULT_FRAG_THRESHOLD 2342U
+#define MIN_FRAG_THRESHOLD 256U
+#define DEFAULT_BEACONINTERVAL 0x64U
+
+#define DEFAULT_SSID ""
+#define DEFAULT_RETRY_RTS 7
+#define DEFAULT_RETRY_DATA 7
+#define PRISM_HDR_SIZE 64
+
+#define PHY_RSSI_SLID_WIN_MAX 100
+
+#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30)
+
+#define TxBBGainTableLength 37
+#define CCKTxBBGainTableLength 23
+
+#define CHANNEL_PLAN_LEN 10
+#define sCrcLng 4
+
+#define NIC_SEND_HANG_THRESHOLD_NORMAL 4
+#define NIC_SEND_HANG_THRESHOLD_POWERSAVE 8
+
+#define MAX_TX_QUEUE 9
+
+#define MAX_RX_QUEUE 1
+
+#define MAX_RX_COUNT 64
+#define MAX_TX_QUEUE_COUNT 9
+
+extern int hwwep;
+
+enum RTL819x_PHY_PARAM {
+ RTL819X_PHY_MACPHY_REG = 0,
+ RTL819X_PHY_MACPHY_REG_PG = 1,
+ RTL8188C_PHY_MACREG = 2,
+ RTL8192C_PHY_MACREG = 3,
+ RTL819X_PHY_REG = 4,
+ RTL819X_PHY_REG_1T2R = 5,
+ RTL819X_PHY_REG_to1T1R = 6,
+ RTL819X_PHY_REG_to1T2R = 7,
+ RTL819X_PHY_REG_to2T2R = 8,
+ RTL819X_PHY_REG_PG = 9,
+ RTL819X_AGC_TAB = 10,
+ RTL819X_PHY_RADIO_A = 11,
+ RTL819X_PHY_RADIO_A_1T = 12,
+ RTL819X_PHY_RADIO_A_2T = 13,
+ RTL819X_PHY_RADIO_B = 14,
+ RTL819X_PHY_RADIO_B_GM = 15,
+ RTL819X_PHY_RADIO_C = 16,
+ RTL819X_PHY_RADIO_D = 17,
+ RTL819X_EEPROM_MAP = 18,
+ RTL819X_EFUSE_MAP = 19,
+};
+
+enum nic_t {
+ NIC_UNKNOWN = 0,
+ NIC_8192E = 1,
+ NIC_8190P = 2,
+ NIC_8192SE = 4,
+ NIC_8192CE = 5,
+ NIC_8192CU = 6,
+ NIC_8192DE = 7,
+ NIC_8192DU = 8,
+};
+
+enum rt_eeprom_type {
+ EEPROM_93C46,
+ EEPROM_93C56,
+ EEPROM_BOOT_EFUSE,
+};
+
+enum dcmg_txcmd_op {
+ TXCMD_TXRA_HISTORY_CTRL = 0xFF900000,
+ TXCMD_RESET_TX_PKT_BUFF = 0xFF900001,
+ TXCMD_RESET_RX_PKT_BUFF = 0xFF900002,
+ TXCMD_SET_TX_DURATION = 0xFF900003,
+ TXCMD_SET_RX_RSSI = 0xFF900004,
+ TXCMD_SET_TX_PWR_TRACKING = 0xFF900005,
+ TXCMD_XXXX_CTRL,
+};
+
+enum rt_rf_type_819xu {
+ RF_TYPE_MIN = 0,
+ RF_8225,
+ RF_8256,
+ RF_8258,
+ RF_6052 = 4,
+ RF_PSEUDO_11N = 5,
+};
+
+enum rf_step {
+ RF_STEP_INIT = 0,
+ RF_STEP_NORMAL,
+ RF_STEP_MAX
+};
+
+enum rt_status {
+ RT_STATUS_SUCCESS,
+ RT_STATUS_FAILURE,
+ RT_STATUS_PENDING,
+ RT_STATUS_RESOURCE
+};
+
+enum rt_customer_id {
+ RT_CID_DEFAULT = 0,
+ RT_CID_8187_ALPHA0 = 1,
+ RT_CID_8187_SERCOMM_PS = 2,
+ RT_CID_8187_HW_LED = 3,
+ RT_CID_8187_NETGEAR = 4,
+ RT_CID_WHQL = 5,
+ RT_CID_819x_CAMEO = 6,
+ RT_CID_819x_RUNTOP = 7,
+ RT_CID_819x_Senao = 8,
+ RT_CID_TOSHIBA = 9,
+ RT_CID_819x_Netcore = 10,
+ RT_CID_Nettronix = 11,
+ RT_CID_DLINK = 12,
+ RT_CID_PRONET = 13,
+ RT_CID_COREGA = 14,
+ RT_CID_819x_ALPHA = 15,
+ RT_CID_819x_Sitecom = 16,
+ RT_CID_CCX = 17,
+ RT_CID_819x_Lenovo = 18,
+ RT_CID_819x_QMI = 19,
+ RT_CID_819x_Edimax_Belkin = 20,
+ RT_CID_819x_Sercomm_Belkin = 21,
+ RT_CID_819x_CAMEO1 = 22,
+ RT_CID_819x_MSI = 23,
+ RT_CID_819x_Acer = 24,
+ RT_CID_819x_HP = 27,
+ RT_CID_819x_CLEVO = 28,
+ RT_CID_819x_Arcadyan_Belkin = 29,
+ RT_CID_819x_SAMSUNG = 30,
+ RT_CID_819x_WNC_COREGA = 31,
+};
+
+enum reset_type {
+ RESET_TYPE_NORESET = 0x00,
+ RESET_TYPE_NORMAL = 0x01,
+ RESET_TYPE_SILENT = 0x02
+};
+
+enum ic_inferiority_8192s {
+ IC_INFERIORITY_A = 0,
+ IC_INFERIORITY_B = 1,
+};
+
+enum pci_bridge_vendor {
+ PCI_BRIDGE_VENDOR_INTEL = 0x0,
+ PCI_BRIDGE_VENDOR_ATI,
+ PCI_BRIDGE_VENDOR_AMD,
+ PCI_BRIDGE_VENDOR_SIS ,
+ PCI_BRIDGE_VENDOR_UNKNOWN,
+ PCI_BRIDGE_VENDOR_MAX ,
+};
+
+struct buffer {
+ struct buffer *next;
+ u32 *buf;
+ dma_addr_t dma;
+
+};
+
+struct rtl_reg_debug {
+ unsigned int cmd;
+ struct {
+ unsigned char type;
+ unsigned char addr;
+ unsigned char page;
+ unsigned char length;
+ } head;
+ unsigned char buf[0xff];
+};
+
+struct rt_tx_rahis {
+ u32 cck[4];
+ u32 ofdm[8];
+ u32 ht_mcs[4][16];
+};
+
+struct rt_smooth_data_4rf {
+ char elements[4][100];
+ u32 index;
+ u32 TotalNum;
+ u32 TotalVal[4];
+};
+
+struct rt_stats {
+ unsigned long txrdu;
+ unsigned long rxrdu;
+ unsigned long rxok;
+ unsigned long rxframgment;
+ unsigned long rxurberr;
+ unsigned long rxstaterr;
+ unsigned long rxdatacrcerr;
+ unsigned long rxmgmtcrcerr;
+ unsigned long rxcrcerrmin;
+ unsigned long rxcrcerrmid;
+ unsigned long rxcrcerrmax;
+ unsigned long received_rate_histogram[4][32];
+ unsigned long received_preamble_GI[2][32];
+ unsigned long rx_AMPDUsize_histogram[5];
+ unsigned long rx_AMPDUnum_histogram[5];
+ unsigned long numpacket_matchbssid;
+ unsigned long numpacket_toself;
+ unsigned long num_process_phyinfo;
+ unsigned long numqry_phystatus;
+ unsigned long numqry_phystatusCCK;
+ unsigned long numqry_phystatusHT;
+ unsigned long received_bwtype[5];
+ unsigned long txnperr;
+ unsigned long txnpdrop;
+ unsigned long txresumed;
+ unsigned long rxoverflow;
+ unsigned long rxint;
+ unsigned long txnpokint;
+ unsigned long ints;
+ unsigned long shints;
+ unsigned long txoverflow;
+ unsigned long txlpokint;
+ unsigned long txlpdrop;
+ unsigned long txlperr;
+ unsigned long txbeokint;
+ unsigned long txbedrop;
+ unsigned long txbeerr;
+ unsigned long txbkokint;
+ unsigned long txbkdrop;
+ unsigned long txbkerr;
+ unsigned long txviokint;
+ unsigned long txvidrop;
+ unsigned long txvierr;
+ unsigned long txvookint;
+ unsigned long txvodrop;
+ unsigned long txvoerr;
+ unsigned long txbeaconokint;
+ unsigned long txbeacondrop;
+ unsigned long txbeaconerr;
+ unsigned long txmanageokint;
+ unsigned long txmanagedrop;
+ unsigned long txmanageerr;
+ unsigned long txcmdpktokint;
+ unsigned long txdatapkt;
+ unsigned long txfeedback;
+ unsigned long txfeedbackok;
+ unsigned long txoktotal;
+ unsigned long txokbytestotal;
+ unsigned long txokinperiod;
+ unsigned long txmulticast;
+ unsigned long txbytesmulticast;
+ unsigned long txbroadcast;
+ unsigned long txbytesbroadcast;
+ unsigned long txunicast;
+ unsigned long txbytesunicast;
+ unsigned long rxbytesunicast;
+ unsigned long txfeedbackfail;
+ unsigned long txerrtotal;
+ unsigned long txerrbytestotal;
+ unsigned long txerrmulticast;
+ unsigned long txerrbroadcast;
+ unsigned long txerrunicast;
+ unsigned long txretrycount;
+ unsigned long txfeedbackretry;
+ u8 last_packet_rate;
+ unsigned long slide_signal_strength[100];
+ unsigned long slide_evm[100];
+ unsigned long slide_rssi_total;
+ unsigned long slide_evm_total;
+ long signal_strength;
+ long signal_quality;
+ long last_signal_strength_inpercent;
+ long recv_signal_power;
+ u8 rx_rssi_percentage[4];
+ u8 rx_evm_percentage[2];
+ long rxSNRdB[4];
+ struct rt_tx_rahis txrate;
+ u32 Slide_Beacon_pwdb[100];
+ u32 Slide_Beacon_Total;
+ struct rt_smooth_data_4rf cck_adc_pwdb;
+ u32 CurrentShowTxate;
+};
+
+struct channel_access_setting {
+ u16 SIFS_Timer;
+ u16 DIFS_Timer;
+ u16 SlotTimeTimer;
+ u16 EIFS_Timer;
+ u16 CWminIndex;
+ u16 CWmaxIndex;
+};
+
+enum two_port_status {
+ TWO_PORT_STATUS__DEFAULT_ONLY,
+ TWO_PORT_STATUS__EXTENSION_ONLY,
+ TWO_PORT_STATUS__EXTENSION_FOLLOW_DEFAULT,
+ TWO_PORT_STATUS__DEFAULT_G_EXTENSION_N20,
+ TWO_PORT_STATUS__ADHOC,
+ TWO_PORT_STATUS__WITHOUT_ANY_ASSOCIATE
+};
+
+struct txbbgain_struct {
+ long txbb_iq_amplifygain;
+ u32 txbbgain_value;
+};
+
+struct ccktxbbgain {
+ u8 ccktxbb_valuearray[8];
+};
+
+struct init_gain {
+ u8 xaagccore1;
+ u8 xbagccore1;
+ u8 xcagccore1;
+ u8 xdagccore1;
+ u8 cca;
+
+};
+
+struct tx_ring {
+ u32 *desc;
+ u8 nStuckCount;
+ struct tx_ring *next;
+} __packed;
+
+struct rtl8192_tx_ring {
+ struct tx_desc *desc;
+ dma_addr_t dma;
+ unsigned int idx;
+ unsigned int entries;
+ struct sk_buff_head queue;
+};
+
+
+
+struct rtl819x_ops {
+ enum nic_t nic_type;
+ void (*get_eeprom_size)(struct net_device *dev);
+ void (*init_adapter_variable)(struct net_device *dev);
+ void (*init_before_adapter_start)(struct net_device *dev);
+ bool (*initialize_adapter)(struct net_device *dev);
+ void (*link_change)(struct net_device *dev);
+ void (*tx_fill_descriptor)(struct net_device *dev,
+ struct tx_desc *tx_desc,
+ struct cb_desc *cb_desc,
+ struct sk_buff *skb);
+ void (*tx_fill_cmd_descriptor)(struct net_device *dev,
+ struct tx_desc_cmd *entry,
+ struct cb_desc *cb_desc,
+ struct sk_buff *skb);
+ bool (*rx_query_status_descriptor)(struct net_device *dev,
+ struct rtllib_rx_stats *stats,
+ struct rx_desc *pdesc,
+ struct sk_buff *skb);
+ bool (*rx_command_packet_handler)(struct net_device *dev,
+ struct sk_buff *skb,
+ struct rx_desc *pdesc);
+ void (*stop_adapter)(struct net_device *dev, bool reset);
+ void (*update_ratr_table)(struct net_device *dev);
+ void (*irq_enable)(struct net_device *dev);
+ void (*irq_disable)(struct net_device *dev);
+ void (*irq_clear)(struct net_device *dev);
+ void (*rx_enable)(struct net_device *dev);
+ void (*tx_enable)(struct net_device *dev);
+ void (*interrupt_recognized)(struct net_device *dev,
+ u32 *p_inta, u32 *p_intb);
+ bool (*TxCheckStuckHandler)(struct net_device *dev);
+ bool (*RxCheckStuckHandler)(struct net_device *dev);
+};
+
+struct r8192_priv {
+ struct pci_dev *pdev;
+ struct pci_dev *bridge_pdev;
+
+ bool bfirst_init;
+ bool bfirst_after_down;
+ bool initialized_at_probe;
+ bool being_init_adapter;
+ bool bDriverIsGoingToUnload;
+
+ int irq;
+ short irq_enabled;
+
+ short up;
+ short up_first_time;
+ struct delayed_work update_beacon_wq;
+ struct delayed_work watch_dog_wq;
+ struct delayed_work txpower_tracking_wq;
+ struct delayed_work rfpath_check_wq;
+ struct delayed_work gpio_change_rf_wq;
+ struct delayed_work initialgain_operate_wq;
+ struct delayed_work check_hw_scan_wq;
+ struct delayed_work hw_scan_simu_wq;
+ struct delayed_work start_hw_scan_wq;
+
+ struct workqueue_struct *priv_wq;
+
+ struct channel_access_setting ChannelAccessSetting;
+
+ struct mp_adapter NdisAdapter;
+
+ struct rtl819x_ops *ops;
+ struct rtllib_device *rtllib;
+
+ struct work_struct reset_wq;
+
+ struct log_int_8190 InterruptLog;
+
+ enum rt_customer_id CustomerID;
+
+
+ enum rt_rf_type_819xu rf_chip;
+ enum ic_inferiority_8192s IC_Class;
+ enum ht_channel_width CurrentChannelBW;
+ struct bb_reg_definition PHYRegDef[4];
+ struct rate_adaptive rate_adaptive;
+
+ struct ccktxbbgain cck_txbbgain_table[CCKTxBBGainTableLength];
+ struct ccktxbbgain cck_txbbgain_ch14_table[CCKTxBBGainTableLength];
+
+ struct txbbgain_struct txbbgain_table[TxBBGainTableLength];
+
+ enum acm_method AcmMethod;
+
+ struct rt_firmware *pFirmware;
+ enum rtl819x_loopback LoopbackMode;
+
+ struct timer_list watch_dog_timer;
+ struct timer_list fsync_timer;
+ struct timer_list gpio_polling_timer;
+
+ spinlock_t fw_scan_lock;
+ spinlock_t irq_lock;
+ spinlock_t irq_th_lock;
+ spinlock_t tx_lock;
+ spinlock_t rf_ps_lock;
+ spinlock_t rw_lock;
+ spinlock_t rt_h2c_lock;
+ spinlock_t rf_lock;
+ spinlock_t ps_lock;
+
+ struct sk_buff_head rx_queue;
+ struct sk_buff_head skb_queue;
+
+ struct tasklet_struct irq_rx_tasklet;
+ struct tasklet_struct irq_tx_tasklet;
+ struct tasklet_struct irq_prepare_beacon_tasklet;
+
+ struct semaphore wx_sem;
+ struct semaphore rf_sem;
+ struct mutex mutex;
+
+ struct rt_stats stats;
+ struct iw_statistics wstats;
+ struct proc_dir_entry *dir_dev;
+
+ short (*rf_set_sens)(struct net_device *dev, short sens);
+ u8 (*rf_set_chan)(struct net_device *dev, u8 ch);
+ void (*rf_close)(struct net_device *dev);
+ void (*rf_init)(struct net_device *dev);
+
+ struct rx_desc *rx_ring[MAX_RX_QUEUE];
+ struct sk_buff *rx_buf[MAX_RX_QUEUE][MAX_RX_COUNT];
+ dma_addr_t rx_ring_dma[MAX_RX_QUEUE];
+ unsigned int rx_idx[MAX_RX_QUEUE];
+ int rxringcount;
+ u16 rxbuffersize;
+
+ u64 LastRxDescTSF;
+
+ u16 EarlyRxThreshold;
+ u32 ReceiveConfig;
+ u8 AcmControl;
+ u8 RFProgType;
+ u8 retry_data;
+ u8 retry_rts;
+ u16 rts;
+
+ struct rtl8192_tx_ring tx_ring[MAX_TX_QUEUE_COUNT];
+ int txringcount;
+ int txbuffsize;
+ int txfwbuffersize;
+ atomic_t tx_pending[0x10];
+
+ u16 ShortRetryLimit;
+ u16 LongRetryLimit;
+ u32 TransmitConfig;
+ u8 RegCWinMin;
+ u8 keepAliveLevel;
+
+ bool sw_radio_on;
+ bool bHwRadioOff;
+ bool pwrdown;
+ bool blinked_ingpio;
+ u8 polling_timer_on;
+
+ /**********************************************************/
+
+ enum card_type {
+ PCI, MINIPCI,
+ CARDBUS, USB
+ } card_type;
+
+ struct work_struct qos_activate;
+
+ u8 bIbssCoordinator;
+
+ short promisc;
+ short crcmon;
+
+ int txbeaconcount;
+
+ short chan;
+ short sens;
+ short max_sens;
+ u32 rx_prevlen;
+
+ u8 ScanDelay;
+ bool ps_force;
+
+ u32 irq_mask[2];
+
+ u8 Rf_Mode;
+ enum nic_t card_8192;
+ u8 card_8192_version;
+
+ short enable_gpio0;
+
+ u8 rf_type;
+ u8 IC_Cut;
+ char nick[IW_ESSID_MAX_SIZE + 1];
+
+ u8 RegBcnCtrlVal;
+ bool bHwAntDiv;
+
+ bool bTKIPinNmodeFromReg;
+ bool bWEPinNmodeFromReg;
+
+ bool bLedOpenDrain;
+
+ u8 check_roaming_cnt;
+
+ bool bIgnoreSilentReset;
+ u32 SilentResetRxSoltNum;
+ u32 SilentResetRxSlotIndex;
+ u32 SilentResetRxStuckEvent[MAX_SILENT_RESET_RX_SLOT_NUM];
+
+ void *scan_cmd;
+ u8 hwscan_bw_40;
+
+ u16 nrxAMPDU_size;
+ u8 nrxAMPDU_aggr_num;
+
+ u32 last_rxdesc_tsf_high;
+ u32 last_rxdesc_tsf_low;
+
+ u16 basic_rate;
+ u8 short_preamble;
+ u8 dot11CurrentPreambleMode;
+ u8 slot_time;
+ u16 SifsTime;
+
+ u8 RegWirelessMode;
+
+ u8 firmware_version;
+ u16 FirmwareSubVersion;
+ u16 rf_pathmap;
+ bool AutoloadFailFlag;
+
+ u8 RegPciASPM;
+ u8 RegAMDPciASPM;
+ u8 RegHwSwRfOffD3;
+ u8 RegSupportPciASPM;
+ bool bSupportASPM;
+
+ u32 RfRegChnlVal[2];
+
+ u8 ShowRateMode;
+ u8 RATRTableBitmap;
+
+ u8 EfuseMap[2][HWSET_MAX_SIZE_92S];
+ u16 EfuseUsedBytes;
+ u8 EfuseUsedPercentage;
+
+ short epromtype;
+ u16 eeprom_vid;
+ u16 eeprom_did;
+ u16 eeprom_svid;
+ u16 eeprom_smid;
+ u8 eeprom_CustomerID;
+ u16 eeprom_ChannelPlan;
+ u8 eeprom_version;
+
+ u8 EEPROMRegulatory;
+ u8 EEPROMPwrGroup[2][3];
+ u8 EEPROMOptional;
+
+ u8 EEPROMTxPowerLevelCCK[14];
+ u8 EEPROMTxPowerLevelOFDM24G[14];
+ u8 EEPROMTxPowerLevelOFDM5G[24];
+ u8 EEPROMRfACCKChnl1TxPwLevel[3];
+ u8 EEPROMRfAOfdmChnlTxPwLevel[3];
+ u8 EEPROMRfCCCKChnl1TxPwLevel[3];
+ u8 EEPROMRfCOfdmChnlTxPwLevel[3];
+ u16 EEPROMTxPowerDiff;
+ u16 EEPROMAntPwDiff;
+ u8 EEPROMThermalMeter;
+ u8 EEPROMPwDiff;
+ u8 EEPROMCrystalCap;
+
+ u8 EEPROMBluetoothCoexist;
+ u8 EEPROMBluetoothType;
+ u8 EEPROMBluetoothAntNum;
+ u8 EEPROMBluetoothAntIsolation;
+ u8 EEPROMBluetoothRadioShared;
+
+
+ u8 EEPROMSupportWoWLAN;
+ u8 EEPROMBoardType;
+ u8 EEPROM_Def_Ver;
+ u8 EEPROMHT2T_TxPwr[6];
+ u8 EEPROMTSSI_A;
+ u8 EEPROMTSSI_B;
+ u8 EEPROMTxPowerLevelCCK_V1[3];
+ u8 EEPROMLegacyHTTxPowerDiff;
+
+ u8 BluetoothCoexist;
+
+ u8 CrystalCap;
+ u8 ThermalMeter[2];
+
+ u16 FwCmdIOMap;
+ u32 FwCmdIOParam;
+
+ u8 SwChnlInProgress;
+ u8 SwChnlStage;
+ u8 SwChnlStep;
+ u8 SetBWModeInProgress;
+
+ u8 nCur40MhzPrimeSC;
+
+ u32 RfReg0Value[4];
+ u8 NumTotalRFPath;
+ bool brfpath_rxenable[4];
+
+ bool bTXPowerDataReadFromEEPORM;
+
+ u16 RegChannelPlan;
+ u16 ChannelPlan;
+ bool bChnlPlanFromHW;
+
+ bool RegRfOff;
+ bool isRFOff;
+ bool bInPowerSaveMode;
+ u8 bHwRfOffAction;
+
+ bool aspm_clkreq_enable;
+ u32 pci_bridge_vendor;
+ u8 RegHostPciASPMSetting;
+ u8 RegDevicePciASPMSetting;
+
+ bool RFChangeInProgress;
+ bool SetRFPowerStateInProgress;
+ bool bdisable_nic;
+
+ u8 pwrGroupCnt;
+
+ u8 ThermalValue_LCK;
+ u8 ThermalValue_IQK;
+ bool bRfPiEnable;
+
+ u32 APKoutput[2][2];
+ bool bAPKdone;
+
+ long RegE94;
+ long RegE9C;
+ long RegEB4;
+ long RegEBC;
+
+ u32 RegC04;
+ u32 Reg874;
+ u32 RegC08;
+ u32 ADDA_backup[16];
+ u32 IQK_MAC_backup[3];
+
+ bool SetFwCmdInProgress;
+ u8 CurrentFwCmdIO;
+
+ u8 rssi_level;
+
+ bool bInformFWDriverControlDM;
+ u8 PwrGroupHT20[2][14];
+ u8 PwrGroupHT40[2][14];
+
+ u8 ThermalValue;
+ long EntryMinUndecoratedSmoothedPWDB;
+ long EntryMaxUndecoratedSmoothedPWDB;
+ u8 DynamicTxHighPowerLvl;
+ u8 LastDTPLvl;
+ u32 CurrentRATR0;
+ struct false_alarm_stats FalseAlmCnt;
+
+ u8 DMFlag;
+ u8 DM_Type;
+
+ u8 CckPwEnl;
+ u16 TSSI_13dBm;
+ u32 Pwr_Track;
+ u8 CCKPresentAttentuation_20Mdefault;
+ u8 CCKPresentAttentuation_40Mdefault;
+ char CCKPresentAttentuation_difference;
+ char CCKPresentAttentuation;
+ u8 bCckHighPower;
+ long undecorated_smoothed_pwdb;
+ long undecorated_smoothed_cck_adc_pwdb[4];
+
+ u32 MCSTxPowerLevelOriginalOffset[6];
+ u32 CCKTxPowerLevelOriginalOffset;
+ u8 TxPowerLevelCCK[14];
+ u8 TxPowerLevelCCK_A[14];
+ u8 TxPowerLevelCCK_C[14];
+ u8 TxPowerLevelOFDM24G[14];
+ u8 TxPowerLevelOFDM5G[14];
+ u8 TxPowerLevelOFDM24G_A[14];
+ u8 TxPowerLevelOFDM24G_C[14];
+ u8 LegacyHTTxPowerDiff;
+ u8 TxPowerDiff;
+ s8 RF_C_TxPwDiff;
+ s8 RF_B_TxPwDiff;
+ u8 RfTxPwrLevelCck[2][14];
+ u8 RfTxPwrLevelOfdm1T[2][14];
+ u8 RfTxPwrLevelOfdm2T[2][14];
+ u8 AntennaTxPwDiff[3];
+ u8 TxPwrHt20Diff[2][14];
+ u8 TxPwrLegacyHtDiff[2][14];
+ u8 TxPwrSafetyFlag;
+ u8 HT2T_TxPwr_A[14];
+ u8 HT2T_TxPwr_B[14];
+ u8 CurrentCckTxPwrIdx;
+ u8 CurrentOfdm24GTxPwrIdx;
+
+ bool bdynamic_txpower;
+ bool bDynamicTxHighPower;
+ bool bDynamicTxLowPower;
+ bool bLastDTPFlag_High;
+ bool bLastDTPFlag_Low;
+
+ bool bstore_last_dtpflag;
+ bool bstart_txctrl_bydtp;
+
+ u8 rfa_txpowertrackingindex;
+ u8 rfa_txpowertrackingindex_real;
+ u8 rfa_txpowertracking_default;
+ u8 rfc_txpowertrackingindex;
+ u8 rfc_txpowertrackingindex_real;
+ u8 rfc_txpowertracking_default;
+ bool btxpower_tracking;
+ bool bcck_in_ch14;
+
+ u8 TxPowerTrackControl;
+ u8 txpower_count;
+ bool btxpower_trackingInit;
+
+ u8 OFDM_index[2];
+ u8 CCK_index;
+
+ u8 Record_CCK_20Mindex;
+ u8 Record_CCK_40Mindex;
+
+ struct init_gain initgain_backup;
+ u8 DefaultInitialGain[4];
+ bool bis_any_nonbepkts;
+ bool bcurrent_turbo_EDCA;
+ bool bis_cur_rdlstate;
+
+ bool bCCKinCH14;
+
+ u8 MidHighPwrTHR_L1;
+ u8 MidHighPwrTHR_L2;
+
+ bool bfsync_processing;
+ u32 rate_record;
+ u32 rateCountDiffRecord;
+ u32 ContinueDiffCount;
+ bool bswitch_fsync;
+ u8 framesync;
+ u32 framesyncC34;
+ u8 framesyncMonitor;
+
+ bool bDMInitialGainEnable;
+ bool MutualAuthenticationFail;
+
+ bool bDisableFrameBursting;
+
+ u32 reset_count;
+ bool bpbc_pressed;
+
+ u32 txpower_checkcnt;
+ u32 txpower_tracking_callback_cnt;
+ u8 thermal_read_val[40];
+ u8 thermal_readback_index;
+ u32 ccktxpower_adjustcnt_not_ch14;
+ u32 ccktxpower_adjustcnt_ch14;
+
+ enum reset_type ResetProgress;
+ bool bForcedSilentReset;
+ bool bDisableNormalResetCheck;
+ u16 TxCounter;
+ u16 RxCounter;
+ int IrpPendingCount;
+ bool bResetInProgress;
+ bool force_reset;
+ bool force_lps;
+ u8 InitialGainOperateType;
+
+ bool chan_forced;
+ bool bSingleCarrier;
+ bool RegBoard;
+ bool bCckContTx;
+ bool bOfdmContTx;
+ bool bStartContTx;
+ u8 RegPaModel;
+ u8 btMpCckTxPower;
+ u8 btMpOfdmTxPower;
+
+ u32 MptActType;
+ u32 MptIoOffset;
+ u32 MptIoValue;
+ u32 MptRfPath;
+
+ u32 MptBandWidth;
+ u32 MptRateIndex;
+ u8 MptChannelToSw;
+ u32 MptRCR;
+
+ u8 PwrDomainProtect;
+ u8 H2CTxCmdSeq;
+
+
+};
+
+extern const struct ethtool_ops rtl819x_ethtool_ops;
+
+void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb);
+short rtl8192_tx(struct net_device *dev, struct sk_buff *skb);
+
+u8 read_nic_io_byte(struct net_device *dev, int x);
+u32 read_nic_io_dword(struct net_device *dev, int x);
+u16 read_nic_io_word(struct net_device *dev, int x);
+void write_nic_io_byte(struct net_device *dev, int x, u8 y);
+void write_nic_io_word(struct net_device *dev, int x, u16 y);
+void write_nic_io_dword(struct net_device *dev, int x, u32 y);
+
+u8 read_nic_byte(struct net_device *dev, int x);
+u32 read_nic_dword(struct net_device *dev, int x);
+u16 read_nic_word(struct net_device *dev, int x);
+void write_nic_byte(struct net_device *dev, int x, u8 y);
+void write_nic_word(struct net_device *dev, int x, u16 y);
+void write_nic_dword(struct net_device *dev, int x, u32 y);
+
+void force_pci_posting(struct net_device *dev);
+
+void rtl8192_rx_enable(struct net_device *);
+void rtl8192_tx_enable(struct net_device *);
+
+int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
+void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
+ int rate);
+void rtl8192_data_hard_stop(struct net_device *dev);
+void rtl8192_data_hard_resume(struct net_device *dev);
+void rtl8192_restart(void *data);
+void rtl819x_watchdog_wqcallback(void *data);
+void rtl8192_hw_sleep_wq(void *data);
+void watch_dog_timer_callback(unsigned long data);
+void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
+void rtl8192_irq_tx_tasklet(struct r8192_priv *priv);
+int rtl8192_down(struct net_device *dev, bool shutdownrf);
+int rtl8192_up(struct net_device *dev);
+void rtl8192_commit(struct net_device *dev);
+void rtl8192_set_chan(struct net_device *dev, short ch);
+
+void check_rfctrl_gpio_timer(unsigned long data);
+
+void rtl8192_hw_wakeup_wq(void *data);
+short rtl8192_pci_initdescring(struct net_device *dev);
+
+void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
+
+int _rtl8192_up(struct net_device *dev, bool is_silent_reset);
+
+short rtl8192_is_tx_queue_empty(struct net_device *dev);
+void rtl8192_irq_disable(struct net_device *dev);
+
+void rtl8192_tx_timeout(struct net_device *dev);
+void rtl8192_pci_resetdescring(struct net_device *dev);
+void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode);
+void rtl8192_irq_enable(struct net_device *dev);
+void rtl8192_config_rate(struct net_device *dev, u16 *rate_config);
+void rtl8192_update_cap(struct net_device *dev, u16 cap);
+void rtl8192_irq_disable(struct net_device *dev);
+
+void rtl819x_UpdateRxPktTimeStamp(struct net_device *dev,
+ struct rtllib_rx_stats *stats);
+long rtl819x_translate_todbm(struct r8192_priv *priv, u8 signal_strength_index);
+void rtl819x_update_rxsignalstatistics8190pci(struct r8192_priv *priv,
+ struct rtllib_rx_stats *pprevious_stats);
+u8 rtl819x_evm_dbtopercentage(char value);
+void rtl819x_process_cck_rxpathsel(struct r8192_priv *priv,
+ struct rtllib_rx_stats *pprevious_stats);
+u8 rtl819x_query_rxpwrpercentage(char antpower);
+void rtl8192_record_rxdesc_forlateruse(struct rtllib_rx_stats *psrc_stats,
+ struct rtllib_rx_stats *ptarget_stats);
+bool NicIFEnableNIC(struct net_device *dev);
+bool NicIFDisableNIC(struct net_device *dev);
+
+bool MgntActSet_RF_State(struct net_device *dev,
+ enum rt_rf_power_state StateToSet,
+ RT_RF_CHANGE_SOURCE ChangeSource,
+ bool ProtectOrNot);
+void ActUpdateChannelAccessSetting(struct net_device *dev,
+ enum wireless_mode WirelessMode,
+ struct channel_access_setting *ChnlAccessSetting);
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_crypto.h b/drivers/staging/rtl8192e/rtl8192e/rtl_crypto.h
new file mode 100644
index 000000000..ee57c0f4f
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_crypto.h
@@ -0,0 +1,382 @@
+/*
+ * Scatterlist Cryptographic API.
+ *
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ * Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ *
+ * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
+ * and Nettle, by Niels Mé°ˆler.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ */
+#ifndef _LINUX_CRYPTO_H
+#define _LINUX_CRYPTO_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <asm/page.h>
+#include <linux/errno.h>
+
+#define crypto_register_alg crypto_register_alg_rsl
+#define crypto_unregister_alg crypto_unregister_alg_rsl
+#define crypto_alloc_tfm crypto_alloc_tfm_rsl
+#define crypto_free_tfm crypto_free_tfm_rsl
+#define crypto_alg_available crypto_alg_available_rsl
+
+/*
+ * Algorithm masks and types.
+ */
+#define CRYPTO_ALG_TYPE_MASK 0x000000ff
+#define CRYPTO_ALG_TYPE_CIPHER 0x00000001
+#define CRYPTO_ALG_TYPE_DIGEST 0x00000002
+#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004
+
+/*
+ * Transform masks and values (for crt_flags).
+ */
+#define CRYPTO_TFM_MODE_MASK 0x000000ff
+#define CRYPTO_TFM_REQ_MASK 0x000fff00
+#define CRYPTO_TFM_RES_MASK 0xfff00000
+
+#define CRYPTO_TFM_MODE_ECB 0x00000001
+#define CRYPTO_TFM_MODE_CBC 0x00000002
+#define CRYPTO_TFM_MODE_CFB 0x00000004
+#define CRYPTO_TFM_MODE_CTR 0x00000008
+
+#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100
+#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
+#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
+#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000
+#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000
+#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000
+
+/*
+ * Miscellaneous stuff.
+ */
+#define CRYPTO_UNSPEC 0
+#define CRYPTO_MAX_ALG_NAME 64
+
+struct scatterlist;
+
+/*
+ * Algorithms: modular crypto algorithm implementations, managed
+ * via crypto_register_alg() and crypto_unregister_alg().
+ */
+struct cipher_alg {
+ unsigned int cia_min_keysize;
+ unsigned int cia_max_keysize;
+ int (*cia_setkey)(void *ctx, const u8 *key,
+ unsigned int keylen, u32 *flags);
+ void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src);
+ void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src);
+};
+
+struct digest_alg {
+ unsigned int dia_digestsize;
+ void (*dia_init)(void *ctx);
+ void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
+ void (*dia_final)(void *ctx, u8 *out);
+ int (*dia_setkey)(void *ctx, const u8 *key,
+ unsigned int keylen, u32 *flags);
+};
+
+struct compress_alg {
+ int (*coa_init)(void *ctx);
+ void (*coa_exit)(void *ctx);
+ int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen);
+ int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen);
+};
+
+#define cra_cipher cra_u.cipher
+#define cra_digest cra_u.digest
+#define cra_compress cra_u.compress
+
+struct crypto_alg {
+ struct list_head cra_list;
+ u32 cra_flags;
+ unsigned int cra_blocksize;
+ unsigned int cra_ctxsize;
+ const char cra_name[CRYPTO_MAX_ALG_NAME];
+
+ union {
+ struct cipher_alg cipher;
+ struct digest_alg digest;
+ struct compress_alg compress;
+ } cra_u;
+
+ struct module *cra_module;
+};
+
+/*
+ * Algorithm registration interface.
+ */
+int crypto_register_alg(struct crypto_alg *alg);
+int crypto_unregister_alg(struct crypto_alg *alg);
+
+/*
+ * Algorithm query interface.
+ */
+int crypto_alg_available(const char *name, u32 flags);
+
+/*
+ * Transforms: user-instantiated objects which encapsulate algorithms
+ * and core processing logic. Managed via crypto_alloc_tfm() and
+ * crypto_free_tfm(), as well as the various helpers below.
+ */
+struct crypto_tfm;
+
+struct cipher_tfm {
+ void *cit_iv;
+ unsigned int cit_ivsize;
+ u32 cit_mode;
+ int (*cit_setkey)(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen);
+ int (*cit_encrypt)(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes);
+ int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes, u8 *iv);
+ int (*cit_decrypt)(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes);
+ int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes, u8 *iv);
+ void (*cit_xor_block)(u8 *dst, const u8 *src);
+};
+
+struct digest_tfm {
+ void (*dit_init)(struct crypto_tfm *tfm);
+ void (*dit_update)(struct crypto_tfm *tfm,
+ struct scatterlist *sg, unsigned int nsg);
+ void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
+ void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
+ unsigned int nsg, u8 *out);
+ int (*dit_setkey)(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen);
+};
+
+struct compress_tfm {
+ int (*cot_compress)(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen);
+ int (*cot_decompress)(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen);
+};
+
+#define crt_cipher crt_u.cipher
+#define crt_digest crt_u.digest
+#define crt_compress crt_u.compress
+
+struct crypto_tfm {
+
+ u32 crt_flags;
+
+ union {
+ struct cipher_tfm cipher;
+ struct digest_tfm digest;
+ struct compress_tfm compress;
+ } crt_u;
+
+ struct crypto_alg *__crt_alg;
+};
+
+/*
+ * Transform user interface.
+ */
+
+/*
+ * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm.
+ * If that fails and the kernel supports dynamically loadable modules, it
+ * will then attempt to load a module of the same name or alias. A refcount
+ * is grabbed on the algorithm which is then associated with the new transform.
+ *
+ * crypto_free_tfm() frees up the transform and any associated resources,
+ * then drops the refcount on the associated algorithm.
+ */
+struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags);
+void crypto_free_tfm(struct crypto_tfm *tfm);
+
+/*
+ * Transform helpers which query the underlying algorithm.
+ */
+static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm)
+{
+ return tfm->__crt_alg->cra_name;
+}
+
+static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm)
+{
+ struct crypto_alg *alg = tfm->__crt_alg;
+
+ if (alg->cra_module)
+ return alg->cra_module->name;
+ else
+ return NULL;
+}
+
+static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm)
+{
+ return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK;
+}
+
+static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ return tfm->__crt_alg->cra_cipher.cia_min_keysize;
+}
+
+static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ return tfm->__crt_alg->cra_cipher.cia_max_keysize;
+}
+
+static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ return tfm->crt_cipher.cit_ivsize;
+}
+
+static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm)
+{
+ return tfm->__crt_alg->cra_blocksize;
+}
+
+static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ return tfm->__crt_alg->cra_digest.dia_digestsize;
+}
+
+/*
+ * API wrappers.
+ */
+static inline void crypto_digest_init(struct crypto_tfm *tfm)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ tfm->crt_digest.dit_init(tfm);
+}
+
+static inline void crypto_digest_update(struct crypto_tfm *tfm,
+ struct scatterlist *sg,
+ unsigned int nsg)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ tfm->crt_digest.dit_update(tfm, sg, nsg);
+}
+
+static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ tfm->crt_digest.dit_final(tfm, out);
+}
+
+static inline void crypto_digest_digest(struct crypto_tfm *tfm,
+ struct scatterlist *sg,
+ unsigned int nsg, u8 *out)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
+}
+
+static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
+ if (tfm->crt_digest.dit_setkey == NULL)
+ return -ENOSYS;
+ return tfm->crt_digest.dit_setkey(tfm, key, keylen);
+}
+
+static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,
+ const u8 *key, unsigned int keylen)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ return tfm->crt_cipher.cit_setkey(tfm, key, keylen);
+}
+
+static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
+}
+
+static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes, u8 *iv)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
+ return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv);
+}
+
+static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
+}
+
+static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
+ struct scatterlist *dst,
+ struct scatterlist *src,
+ unsigned int nbytes, u8 *iv)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
+ return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv);
+}
+
+static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int len)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ memcpy(tfm->crt_cipher.cit_iv, src, len);
+}
+
+static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
+ u8 *dst, unsigned int len)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+ memcpy(dst, tfm->crt_cipher.cit_iv, len);
+}
+
+static inline int crypto_comp_compress(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
+ return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen);
+}
+
+static inline int crypto_comp_decompress(struct crypto_tfm *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int *dlen)
+{
+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
+ return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen);
+}
+
+#endif /* _LINUX_CRYPTO_H */
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
new file mode 100644
index 000000000..df4bbcf38
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
@@ -0,0 +1,2995 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtl_core.h"
+#include "rtl_dm.h"
+#include "r8192E_hw.h"
+#include "r8192E_phy.h"
+#include "r8192E_phyreg.h"
+#include "r8190P_rtl8256.h"
+#include "r8192E_cmdpkt.h"
+
+/*---------------------------Define Local Constant---------------------------*/
+static u32 edca_setting_DL[HT_IOT_PEER_MAX] = {
+ 0x5e4322,
+ 0x5e4322,
+ 0x5ea44f,
+ 0x5e4322,
+ 0x604322,
+ 0xa44f,
+ 0x5e4322,
+ 0x5e4332
+};
+
+static u32 edca_setting_DL_GMode[HT_IOT_PEER_MAX] = {
+ 0x5e4322,
+ 0x5e4322,
+ 0x5e4322,
+ 0x5e4322,
+ 0x604322,
+ 0xa44f,
+ 0x5e4322,
+ 0x5e4322
+};
+
+static u32 edca_setting_UL[HT_IOT_PEER_MAX] = {
+ 0x5e4322,
+ 0xa44f,
+ 0x5ea44f,
+ 0x5e4322,
+ 0x604322,
+ 0x5e4322,
+ 0x5e4322,
+ 0x5e4332
+};
+
+#define RTK_UL_EDCA 0xa44f
+#define RTK_DL_EDCA 0x5e4322
+/*---------------------------Define Local Constant---------------------------*/
+
+
+/*------------------------Define global variable-----------------------------*/
+struct dig_t dm_digtable;
+u8 dm_shadow[16][256] = {
+ {0}
+};
+
+struct drx_path_sel DM_RxPathSelTable;
+/*------------------------Define global variable-----------------------------*/
+
+
+/*------------------------Define local variable------------------------------*/
+/*------------------------Define local variable------------------------------*/
+
+
+
+/*---------------------Define local function prototype-----------------------*/
+static void dm_check_rate_adaptive(struct net_device *dev);
+
+static void dm_init_bandwidth_autoswitch(struct net_device *dev);
+static void dm_bandwidth_autoswitch(struct net_device *dev);
+
+
+static void dm_check_txpower_tracking(struct net_device *dev);
+
+
+
+
+
+static void dm_bb_initialgain_restore(struct net_device *dev);
+
+
+static void dm_bb_initialgain_backup(struct net_device *dev);
+
+static void dm_dig_init(struct net_device *dev);
+static void dm_ctrl_initgain_byrssi(struct net_device *dev);
+static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev);
+static void dm_ctrl_initgain_byrssi_by_driverrssi(struct net_device *dev);
+static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct net_device *dev);
+static void dm_initial_gain(struct net_device *dev);
+static void dm_pd_th(struct net_device *dev);
+static void dm_cs_ratio(struct net_device *dev);
+
+static void dm_init_ctstoself(struct net_device *dev);
+static void dm_Init_WA_Broadcom_IOT(struct net_device *dev);
+
+static void dm_check_edca_turbo(struct net_device *dev);
+
+static void dm_check_pbc_gpio(struct net_device *dev);
+
+
+static void dm_check_rx_path_selection(struct net_device *dev);
+static void dm_init_rxpath_selection(struct net_device *dev);
+static void dm_rxpath_sel_byrssi(struct net_device *dev);
+
+
+static void dm_init_fsync(struct net_device *dev);
+static void dm_deInit_fsync(struct net_device *dev);
+
+static void dm_check_txrateandretrycount(struct net_device *dev);
+static void dm_check_ac_dc_power(struct net_device *dev);
+
+/*---------------------Define local function prototype-----------------------*/
+
+static void dm_init_dynamic_txpower(struct net_device *dev);
+static void dm_dynamic_txpower(struct net_device *dev);
+
+
+static void dm_send_rssi_tofw(struct net_device *dev);
+static void dm_ctstoself(struct net_device *dev);
+/*---------------------------Define function prototype------------------------*/
+
+void init_hal_dm(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->DM_Type = DM_Type_ByDriver;
+
+ priv->undecorated_smoothed_pwdb = -1;
+
+ dm_init_dynamic_txpower(dev);
+
+ init_rate_adaptive(dev);
+
+ dm_dig_init(dev);
+ dm_init_edca_turbo(dev);
+ dm_init_bandwidth_autoswitch(dev);
+ dm_init_fsync(dev);
+ dm_init_rxpath_selection(dev);
+ dm_init_ctstoself(dev);
+ if (IS_HARDWARE_TYPE_8192SE(dev))
+ dm_Init_WA_Broadcom_IOT(dev);
+
+ INIT_DELAYED_WORK_RSL(&priv->gpio_change_rf_wq, (void *)dm_CheckRfCtrlGPIO, dev);
+}
+
+void deinit_hal_dm(struct net_device *dev)
+{
+
+ dm_deInit_fsync(dev);
+
+}
+
+void hal_dm_watchdog(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->being_init_adapter)
+ return;
+
+ dm_check_ac_dc_power(dev);
+
+ dm_check_pbc_gpio(dev);
+ dm_check_txrateandretrycount(dev);
+ dm_check_edca_turbo(dev);
+
+ dm_check_rate_adaptive(dev);
+ dm_dynamic_txpower(dev);
+ dm_check_txpower_tracking(dev);
+
+ dm_ctrl_initgain_byrssi(dev);
+ dm_bandwidth_autoswitch(dev);
+
+ dm_check_rx_path_selection(dev);
+ dm_check_fsync(dev);
+
+ dm_send_rssi_tofw(dev);
+ dm_ctstoself(dev);
+}
+
+static void dm_check_ac_dc_power(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ static char *ac_dc_check_script_path = "/etc/acpi/wireless-rtl-ac-dc-power.sh";
+ char *argv[] = {ac_dc_check_script_path, DRV_NAME, NULL};
+ static char *envp[] = {"HOME=/",
+ "TERM=linux",
+ "PATH=/usr/bin:/bin",
+ NULL};
+
+ if (priv->ResetProgress == RESET_TYPE_SILENT) {
+ RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF),
+ "GPIOChangeRFWorkItemCallBack(): Silent Reset!!!!!!!\n");
+ return;
+ }
+
+ if (priv->rtllib->state != RTLLIB_LINKED)
+ return;
+ call_usermodehelper(ac_dc_check_script_path, argv, envp, UMH_WAIT_PROC);
+
+ return;
+};
+
+
+void init_rate_adaptive(struct net_device *dev)
+{
+
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rate_adaptive *pra = (struct rate_adaptive *)&priv->rate_adaptive;
+
+ pra->ratr_state = DM_RATR_STA_MAX;
+ pra->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High;
+ pra->low2high_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M+5;
+ pra->low2high_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M+5;
+
+ pra->high_rssi_thresh_for_ra = RateAdaptiveTH_High+5;
+ pra->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M;
+ pra->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M;
+
+ if (priv->CustomerID == RT_CID_819x_Netcore)
+ pra->ping_rssi_enable = 1;
+ else
+ pra->ping_rssi_enable = 0;
+ pra->ping_rssi_thresh_for_ra = 15;
+
+
+ if (priv->rf_type == RF_2T4R) {
+ pra->upper_rssi_threshold_ratr = 0x8f0f0000;
+ pra->middle_rssi_threshold_ratr = 0x8f0ff000;
+ pra->low_rssi_threshold_ratr = 0x8f0ff001;
+ pra->low_rssi_threshold_ratr_40M = 0x8f0ff005;
+ pra->low_rssi_threshold_ratr_20M = 0x8f0ff001;
+ pra->ping_rssi_ratr = 0x0000000d;
+ } else if (priv->rf_type == RF_1T2R) {
+ pra->upper_rssi_threshold_ratr = 0x000fc000;
+ pra->middle_rssi_threshold_ratr = 0x000ff000;
+ pra->low_rssi_threshold_ratr = 0x000ff001;
+ pra->low_rssi_threshold_ratr_40M = 0x000ff005;
+ pra->low_rssi_threshold_ratr_20M = 0x000ff001;
+ pra->ping_rssi_ratr = 0x0000000d;
+ }
+
+}
+
+
+static void dm_check_rate_adaptive(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_hi_throughput *pHTInfo = priv->rtllib->pHTInfo;
+ struct rate_adaptive *pra = (struct rate_adaptive *)&priv->rate_adaptive;
+ u32 currentRATR, targetRATR = 0;
+ u32 LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0;
+ bool bshort_gi_enabled = false;
+ static u8 ping_rssi_state;
+
+ if (!priv->up) {
+ RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n");
+ return;
+ }
+
+ if (pra->rate_adaptive_disabled)
+ return;
+
+ if (!(priv->rtllib->mode == WIRELESS_MODE_N_24G ||
+ priv->rtllib->mode == WIRELESS_MODE_N_5G))
+ return;
+
+ if (priv->rtllib->state == RTLLIB_LINKED) {
+
+ bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) ||
+ (!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz);
+
+
+ pra->upper_rssi_threshold_ratr =
+ (pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31 : 0);
+
+ pra->middle_rssi_threshold_ratr =
+ (pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31 : 0);
+
+ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) {
+ pra->low_rssi_threshold_ratr =
+ (pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled) ? BIT31 : 0);
+ } else {
+ pra->low_rssi_threshold_ratr =
+ (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled) ? BIT31 : 0);
+ }
+ pra->ping_rssi_ratr =
+ (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled) ? BIT31 : 0);
+
+ if (pra->ratr_state == DM_RATR_STA_HIGH) {
+ HighRSSIThreshForRA = pra->high2low_rssi_thresh_for_ra;
+ LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ?
+ (pra->low_rssi_thresh_for_ra40M) : (pra->low_rssi_thresh_for_ra20M);
+ } else if (pra->ratr_state == DM_RATR_STA_LOW) {
+ HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra;
+ LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ?
+ (pra->low2high_rssi_thresh_for_ra40M) : (pra->low2high_rssi_thresh_for_ra20M);
+ } else {
+ HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra;
+ LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) ?
+ (pra->low_rssi_thresh_for_ra40M) : (pra->low_rssi_thresh_for_ra20M);
+ }
+
+ if (priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA) {
+ pra->ratr_state = DM_RATR_STA_HIGH;
+ targetRATR = pra->upper_rssi_threshold_ratr;
+ } else if (priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA) {
+ pra->ratr_state = DM_RATR_STA_MIDDLE;
+ targetRATR = pra->middle_rssi_threshold_ratr;
+ } else {
+ pra->ratr_state = DM_RATR_STA_LOW;
+ targetRATR = pra->low_rssi_threshold_ratr;
+ }
+
+ if (pra->ping_rssi_enable) {
+ if (priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5)) {
+ if ((priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) ||
+ ping_rssi_state) {
+ pra->ratr_state = DM_RATR_STA_LOW;
+ targetRATR = pra->ping_rssi_ratr;
+ ping_rssi_state = 1;
+ }
+ } else {
+ ping_rssi_state = 0;
+ }
+ }
+
+ if (priv->rtllib->GetHalfNmodeSupportByAPsHandler(dev))
+ targetRATR &= 0xf00fffff;
+
+ currentRATR = read_nic_dword(dev, RATR0);
+ if (targetRATR != currentRATR) {
+ u32 ratr_value;
+
+ ratr_value = targetRATR;
+ RT_TRACE(COMP_RATE,
+ "currentRATR = %x, targetRATR = %x\n",
+ currentRATR, targetRATR);
+ if (priv->rf_type == RF_1T2R)
+ ratr_value &= ~(RATE_ALL_OFDM_2SS);
+ write_nic_dword(dev, RATR0, ratr_value);
+ write_nic_byte(dev, UFWP, 1);
+
+ pra->last_ratr = targetRATR;
+ }
+
+ } else {
+ pra->ratr_state = DM_RATR_STA_MAX;
+ }
+}
+
+static void dm_init_bandwidth_autoswitch(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH;
+ priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW;
+ priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = false;
+ priv->rtllib->bandwidth_auto_switch.bautoswitch_enable = false;
+}
+
+static void dm_bandwidth_autoswitch(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||
+ !priv->rtllib->bandwidth_auto_switch.bautoswitch_enable)
+ return;
+ if (priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz == false) {
+ if (priv->undecorated_smoothed_pwdb <=
+ priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz)
+ priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = true;
+ } else {
+ if (priv->undecorated_smoothed_pwdb >=
+ priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz)
+ priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = false;
+ }
+}
+
+static u32 OFDMSwingTable[OFDM_Table_Length] = {
+ 0x7f8001fe,
+ 0x71c001c7,
+ 0x65400195,
+ 0x5a400169,
+ 0x50800142,
+ 0x47c0011f,
+ 0x40000100,
+ 0x390000e4,
+ 0x32c000cb,
+ 0x2d4000b5,
+ 0x288000a2,
+ 0x24000090,
+ 0x20000080,
+ 0x1c800072,
+ 0x19800066,
+ 0x26c0005b,
+ 0x24400051,
+ 0x12000048,
+ 0x10000040
+};
+
+static u8 CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = {
+ {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
+ {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
+ {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
+ {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
+ {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
+ {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
+ {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
+ {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
+ {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
+ {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
+ {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
+ {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}
+};
+
+static u8 CCKSwingTable_Ch14[CCK_Table_length][8] = {
+ {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
+ {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
+ {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
+ {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
+ {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
+ {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
+ {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
+ {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
+ {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
+ {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
+ {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
+ {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}
+};
+
+#define Pw_Track_Flag 0x11d
+#define Tssi_Mea_Value 0x13c
+#define Tssi_Report_Value1 0x134
+#define Tssi_Report_Value2 0x13e
+#define FW_Busy_Flag 0x13f
+
+static void dm_TXPowerTrackingCallback_TSSI(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ bool bHighpowerstate, viviflag = false;
+ struct dcmd_txcmd tx_cmd;
+ u8 powerlevelOFDM24G;
+ int i = 0, j = 0, k = 0;
+ u8 RF_Type, tmp_report[5] = {0, 0, 0, 0, 0};
+ u32 Value;
+ u8 Pwr_Flag;
+ u16 Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver = 0;
+ u32 delta = 0;
+
+ RT_TRACE(COMP_POWER_TRACKING, "%s()\n", __func__);
+ write_nic_byte(dev, Pw_Track_Flag, 0);
+ write_nic_byte(dev, FW_Busy_Flag, 0);
+ priv->rtllib->bdynamic_txpower_enable = false;
+ bHighpowerstate = priv->bDynamicTxHighPower;
+
+ powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24);
+ RF_Type = priv->rf_type;
+ Value = (RF_Type<<8) | powerlevelOFDM24G;
+
+ RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n",
+ powerlevelOFDM24G);
+
+
+ for (j = 0; j <= 30; j++) {
+
+ tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING;
+ tx_cmd.Length = 4;
+ tx_cmd.Value = Value;
+ cmpk_message_handle_tx(dev, (u8 *)&tx_cmd,
+ DESC_PACKET_TYPE_INIT,
+ sizeof(struct dcmd_txcmd));
+ mdelay(1);
+ for (i = 0; i <= 30; i++) {
+ Pwr_Flag = read_nic_byte(dev, Pw_Track_Flag);
+
+ if (Pwr_Flag == 0) {
+ mdelay(1);
+
+ if (priv->bResetInProgress) {
+ RT_TRACE(COMP_POWER_TRACKING,
+ "we are in silent reset progress, so return\n");
+ write_nic_byte(dev, Pw_Track_Flag, 0);
+ write_nic_byte(dev, FW_Busy_Flag, 0);
+ return;
+ }
+ if (priv->rtllib->eRFPowerState != eRfOn) {
+ RT_TRACE(COMP_POWER_TRACKING,
+ "we are in power save, so return\n");
+ write_nic_byte(dev, Pw_Track_Flag, 0);
+ write_nic_byte(dev, FW_Busy_Flag, 0);
+ return;
+ }
+
+ continue;
+ }
+
+ Avg_TSSI_Meas = read_nic_word(dev, Tssi_Mea_Value);
+
+ if (Avg_TSSI_Meas == 0) {
+ write_nic_byte(dev, Pw_Track_Flag, 0);
+ write_nic_byte(dev, FW_Busy_Flag, 0);
+ return;
+ }
+
+ for (k = 0; k < 5; k++) {
+ if (k != 4)
+ tmp_report[k] = read_nic_byte(dev,
+ Tssi_Report_Value1+k);
+ else
+ tmp_report[k] = read_nic_byte(dev,
+ Tssi_Report_Value2);
+
+ RT_TRACE(COMP_POWER_TRACKING,
+ "TSSI_report_value = %d\n",
+ tmp_report[k]);
+
+ if (tmp_report[k] <= 20) {
+ viviflag = true;
+ break;
+ }
+ }
+
+ if (viviflag) {
+ write_nic_byte(dev, Pw_Track_Flag, 0);
+ viviflag = false;
+ RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n");
+ for (k = 0; k < 5; k++)
+ tmp_report[k] = 0;
+ break;
+ }
+
+ for (k = 0; k < 5; k++)
+ Avg_TSSI_Meas_from_driver += tmp_report[k];
+
+ Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5;
+ RT_TRACE(COMP_POWER_TRACKING,
+ "Avg_TSSI_Meas_from_driver = %d\n",
+ Avg_TSSI_Meas_from_driver);
+ TSSI_13dBm = priv->TSSI_13dBm;
+ RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm);
+
+ if (Avg_TSSI_Meas_from_driver > TSSI_13dBm)
+ delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm;
+ else
+ delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver;
+
+ if (delta <= E_FOR_TX_POWER_TRACK) {
+ priv->rtllib->bdynamic_txpower_enable = true;
+ write_nic_byte(dev, Pw_Track_Flag, 0);
+ write_nic_byte(dev, FW_Busy_Flag, 0);
+ RT_TRACE(COMP_POWER_TRACKING,
+ "tx power track is done\n");
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->rfa_txpowertrackingindex = %d\n",
+ priv->rfa_txpowertrackingindex);
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->rfa_txpowertrackingindex_real = %d\n",
+ priv->rfa_txpowertrackingindex_real);
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->CCKPresentAttentuation_difference = %d\n",
+ priv->CCKPresentAttentuation_difference);
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->CCKPresentAttentuation = %d\n",
+ priv->CCKPresentAttentuation);
+ return;
+ }
+ if (Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) {
+ if (RF_Type == RF_2T4R) {
+
+ if ((priv->rfa_txpowertrackingindex > 0) &&
+ (priv->rfc_txpowertrackingindex > 0)) {
+ priv->rfa_txpowertrackingindex--;
+ if (priv->rfa_txpowertrackingindex_real > 4) {
+ priv->rfa_txpowertrackingindex_real--;
+ rtl8192_setBBreg(dev,
+ rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
+ }
+
+ priv->rfc_txpowertrackingindex--;
+ if (priv->rfc_txpowertrackingindex_real > 4) {
+ priv->rfc_txpowertrackingindex_real--;
+ rtl8192_setBBreg(dev,
+ rOFDM0_XCTxIQImbalance,
+ bMaskDWord,
+ priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+ }
+ } else {
+ rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ priv->txbbgain_table[4].txbbgain_value);
+ rtl8192_setBBreg(dev,
+ rOFDM0_XCTxIQImbalance,
+ bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
+ }
+ } else {
+ if (priv->rfa_txpowertrackingindex > 0) {
+ priv->rfa_txpowertrackingindex--;
+ if (priv->rfa_txpowertrackingindex_real > 4) {
+ priv->rfa_txpowertrackingindex_real--;
+ rtl8192_setBBreg(dev,
+ rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
+ }
+ } else
+ rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
+
+ }
+ } else {
+ if (RF_Type == RF_2T4R) {
+ if ((priv->rfa_txpowertrackingindex <
+ TxBBGainTableLength - 1) &&
+ (priv->rfc_txpowertrackingindex <
+ TxBBGainTableLength - 1)) {
+ priv->rfa_txpowertrackingindex++;
+ priv->rfa_txpowertrackingindex_real++;
+ rtl8192_setBBreg(dev,
+ rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ priv->txbbgain_table
+ [priv->rfa_txpowertrackingindex_real].txbbgain_value);
+ priv->rfc_txpowertrackingindex++;
+ priv->rfc_txpowertrackingindex_real++;
+ rtl8192_setBBreg(dev,
+ rOFDM0_XCTxIQImbalance,
+ bMaskDWord,
+ priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+ } else {
+ rtl8192_setBBreg(dev,
+ rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+ rtl8192_setBBreg(dev,
+ rOFDM0_XCTxIQImbalance,
+ bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+ }
+ } else {
+ if (priv->rfa_txpowertrackingindex < (TxBBGainTableLength - 1)) {
+ priv->rfa_txpowertrackingindex++;
+ priv->rfa_txpowertrackingindex_real++;
+ rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
+ } else
+ rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+ }
+ }
+ if (RF_Type == RF_2T4R) {
+ priv->CCKPresentAttentuation_difference
+ = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default;
+ } else {
+ priv->CCKPresentAttentuation_difference
+ = priv->rfa_txpowertrackingindex_real - priv->rfa_txpowertracking_default;
+ }
+
+ if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
+ priv->CCKPresentAttentuation =
+ priv->CCKPresentAttentuation_20Mdefault +
+ priv->CCKPresentAttentuation_difference;
+ else
+ priv->CCKPresentAttentuation =
+ priv->CCKPresentAttentuation_40Mdefault +
+ priv->CCKPresentAttentuation_difference;
+
+ if (priv->CCKPresentAttentuation > (CCKTxBBGainTableLength-1))
+ priv->CCKPresentAttentuation = CCKTxBBGainTableLength-1;
+ if (priv->CCKPresentAttentuation < 0)
+ priv->CCKPresentAttentuation = 0;
+
+ if (priv->CCKPresentAttentuation > -1 &&
+ priv->CCKPresentAttentuation < CCKTxBBGainTableLength) {
+ if (priv->rtllib->current_network.channel == 14 &&
+ !priv->bcck_in_ch14) {
+ priv->bcck_in_ch14 = true;
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ } else if (priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) {
+ priv->bcck_in_ch14 = false;
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ } else
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ }
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->rfa_txpowertrackingindex = %d\n",
+ priv->rfa_txpowertrackingindex);
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->rfa_txpowertrackingindex_real = %d\n",
+ priv->rfa_txpowertrackingindex_real);
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->CCKPresentAttentuation_difference = %d\n",
+ priv->CCKPresentAttentuation_difference);
+ RT_TRACE(COMP_POWER_TRACKING,
+ "priv->CCKPresentAttentuation = %d\n",
+ priv->CCKPresentAttentuation);
+
+ if (priv->CCKPresentAttentuation_difference <= -12 || priv->CCKPresentAttentuation_difference >= 24) {
+ priv->rtllib->bdynamic_txpower_enable = true;
+ write_nic_byte(dev, Pw_Track_Flag, 0);
+ write_nic_byte(dev, FW_Busy_Flag, 0);
+ RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n");
+ return;
+ }
+
+ write_nic_byte(dev, Pw_Track_Flag, 0);
+ Avg_TSSI_Meas_from_driver = 0;
+ for (k = 0; k < 5; k++)
+ tmp_report[k] = 0;
+ break;
+ }
+ write_nic_byte(dev, FW_Busy_Flag, 0);
+ }
+ priv->rtllib->bdynamic_txpower_enable = true;
+ write_nic_byte(dev, Pw_Track_Flag, 0);
+}
+
+static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
+{
+#define ThermalMeterVal 9
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 tmpRegA, TempCCk;
+ u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval;
+ int i = 0, CCKSwingNeedUpdate = 0;
+
+ if (!priv->btxpower_trackingInit) {
+ tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
+ for (i = 0; i < OFDM_Table_Length; i++) {
+ if (tmpRegA == OFDMSwingTable[i]) {
+ priv->OFDM_index[0] = (u8)i;
+ RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, OFDM_index = 0x%x\n",
+ rOFDM0_XATxIQImbalance, tmpRegA, priv->OFDM_index[0]);
+ }
+ }
+
+ TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
+ for (i = 0; i < CCK_Table_length; i++) {
+ if (TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) {
+ priv->CCK_index = (u8) i;
+ RT_TRACE(COMP_POWER_TRACKING,
+ "Initial reg0x%x = 0x%x, CCK_index = 0x%x\n",
+ rCCK0_TxFilter1, TempCCk,
+ priv->CCK_index);
+ break;
+ }
+ }
+ priv->btxpower_trackingInit = true;
+ return;
+ }
+
+ tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078);
+ RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d\n", tmpRegA);
+ if (tmpRegA < 3 || tmpRegA > 13)
+ return;
+ if (tmpRegA >= 12)
+ tmpRegA = 12;
+ RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d\n", tmpRegA);
+ priv->ThermalMeter[0] = ThermalMeterVal;
+ priv->ThermalMeter[1] = ThermalMeterVal;
+
+ if (priv->ThermalMeter[0] >= (u8)tmpRegA) {
+ tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0] -
+ (u8)tmpRegA);
+ tmpCCK40Mindex = tmpCCK20Mindex - 6;
+ if (tmpOFDMindex >= OFDM_Table_Length)
+ tmpOFDMindex = OFDM_Table_Length-1;
+ if (tmpCCK20Mindex >= CCK_Table_length)
+ tmpCCK20Mindex = CCK_Table_length-1;
+ if (tmpCCK40Mindex >= CCK_Table_length)
+ tmpCCK40Mindex = CCK_Table_length-1;
+ } else {
+ tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]);
+ if (tmpval >= 6)
+ tmpOFDMindex = tmpCCK20Mindex = 0;
+ else
+ tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval;
+ tmpCCK40Mindex = 0;
+ }
+ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+ tmpCCKindex = tmpCCK40Mindex;
+ else
+ tmpCCKindex = tmpCCK20Mindex;
+
+ priv->Record_CCK_20Mindex = tmpCCK20Mindex;
+ priv->Record_CCK_40Mindex = tmpCCK40Mindex;
+ RT_TRACE(COMP_POWER_TRACKING,
+ "Record_CCK_20Mindex / Record_CCK_40Mindex = %d / %d.\n",
+ priv->Record_CCK_20Mindex, priv->Record_CCK_40Mindex);
+
+ if (priv->rtllib->current_network.channel == 14 &&
+ !priv->bcck_in_ch14) {
+ priv->bcck_in_ch14 = true;
+ CCKSwingNeedUpdate = 1;
+ } else if (priv->rtllib->current_network.channel != 14 &&
+ priv->bcck_in_ch14) {
+ priv->bcck_in_ch14 = false;
+ CCKSwingNeedUpdate = 1;
+ }
+
+ if (priv->CCK_index != tmpCCKindex) {
+ priv->CCK_index = tmpCCKindex;
+ CCKSwingNeedUpdate = 1;
+ }
+
+ if (CCKSwingNeedUpdate)
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ if (priv->OFDM_index[0] != tmpOFDMindex) {
+ priv->OFDM_index[0] = tmpOFDMindex;
+ rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
+ OFDMSwingTable[priv->OFDM_index[0]]);
+ RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n",
+ priv->OFDM_index[0],
+ OFDMSwingTable[priv->OFDM_index[0]]);
+ }
+ priv->txpower_count = 0;
+}
+
+void dm_txpower_trackingcallback(void *data)
+{
+ struct r8192_priv *priv = container_of_dwork_rsl(data,
+ struct r8192_priv, txpower_tracking_wq);
+ struct net_device *dev = priv->rtllib->dev;
+
+ if (priv->IC_Cut >= IC_VersionCut_D)
+ dm_TXPowerTrackingCallback_TSSI(dev);
+ else
+ dm_TXPowerTrackingCallback_ThermalMeter(dev);
+}
+
+static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev)
+{
+
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->txbbgain_table[0].txbb_iq_amplifygain = 12;
+ priv->txbbgain_table[0].txbbgain_value = 0x7f8001fe;
+ priv->txbbgain_table[1].txbb_iq_amplifygain = 11;
+ priv->txbbgain_table[1].txbbgain_value = 0x788001e2;
+ priv->txbbgain_table[2].txbb_iq_amplifygain = 10;
+ priv->txbbgain_table[2].txbbgain_value = 0x71c001c7;
+ priv->txbbgain_table[3].txbb_iq_amplifygain = 9;
+ priv->txbbgain_table[3].txbbgain_value = 0x6b8001ae;
+ priv->txbbgain_table[4].txbb_iq_amplifygain = 8;
+ priv->txbbgain_table[4].txbbgain_value = 0x65400195;
+ priv->txbbgain_table[5].txbb_iq_amplifygain = 7;
+ priv->txbbgain_table[5].txbbgain_value = 0x5fc0017f;
+ priv->txbbgain_table[6].txbb_iq_amplifygain = 6;
+ priv->txbbgain_table[6].txbbgain_value = 0x5a400169;
+ priv->txbbgain_table[7].txbb_iq_amplifygain = 5;
+ priv->txbbgain_table[7].txbbgain_value = 0x55400155;
+ priv->txbbgain_table[8].txbb_iq_amplifygain = 4;
+ priv->txbbgain_table[8].txbbgain_value = 0x50800142;
+ priv->txbbgain_table[9].txbb_iq_amplifygain = 3;
+ priv->txbbgain_table[9].txbbgain_value = 0x4c000130;
+ priv->txbbgain_table[10].txbb_iq_amplifygain = 2;
+ priv->txbbgain_table[10].txbbgain_value = 0x47c0011f;
+ priv->txbbgain_table[11].txbb_iq_amplifygain = 1;
+ priv->txbbgain_table[11].txbbgain_value = 0x43c0010f;
+ priv->txbbgain_table[12].txbb_iq_amplifygain = 0;
+ priv->txbbgain_table[12].txbbgain_value = 0x40000100;
+ priv->txbbgain_table[13].txbb_iq_amplifygain = -1;
+ priv->txbbgain_table[13].txbbgain_value = 0x3c8000f2;
+ priv->txbbgain_table[14].txbb_iq_amplifygain = -2;
+ priv->txbbgain_table[14].txbbgain_value = 0x390000e4;
+ priv->txbbgain_table[15].txbb_iq_amplifygain = -3;
+ priv->txbbgain_table[15].txbbgain_value = 0x35c000d7;
+ priv->txbbgain_table[16].txbb_iq_amplifygain = -4;
+ priv->txbbgain_table[16].txbbgain_value = 0x32c000cb;
+ priv->txbbgain_table[17].txbb_iq_amplifygain = -5;
+ priv->txbbgain_table[17].txbbgain_value = 0x300000c0;
+ priv->txbbgain_table[18].txbb_iq_amplifygain = -6;
+ priv->txbbgain_table[18].txbbgain_value = 0x2d4000b5;
+ priv->txbbgain_table[19].txbb_iq_amplifygain = -7;
+ priv->txbbgain_table[19].txbbgain_value = 0x2ac000ab;
+ priv->txbbgain_table[20].txbb_iq_amplifygain = -8;
+ priv->txbbgain_table[20].txbbgain_value = 0x288000a2;
+ priv->txbbgain_table[21].txbb_iq_amplifygain = -9;
+ priv->txbbgain_table[21].txbbgain_value = 0x26000098;
+ priv->txbbgain_table[22].txbb_iq_amplifygain = -10;
+ priv->txbbgain_table[22].txbbgain_value = 0x24000090;
+ priv->txbbgain_table[23].txbb_iq_amplifygain = -11;
+ priv->txbbgain_table[23].txbbgain_value = 0x22000088;
+ priv->txbbgain_table[24].txbb_iq_amplifygain = -12;
+ priv->txbbgain_table[24].txbbgain_value = 0x20000080;
+ priv->txbbgain_table[25].txbb_iq_amplifygain = -13;
+ priv->txbbgain_table[25].txbbgain_value = 0x1a00006c;
+ priv->txbbgain_table[26].txbb_iq_amplifygain = -14;
+ priv->txbbgain_table[26].txbbgain_value = 0x1c800072;
+ priv->txbbgain_table[27].txbb_iq_amplifygain = -15;
+ priv->txbbgain_table[27].txbbgain_value = 0x18000060;
+ priv->txbbgain_table[28].txbb_iq_amplifygain = -16;
+ priv->txbbgain_table[28].txbbgain_value = 0x19800066;
+ priv->txbbgain_table[29].txbb_iq_amplifygain = -17;
+ priv->txbbgain_table[29].txbbgain_value = 0x15800056;
+ priv->txbbgain_table[30].txbb_iq_amplifygain = -18;
+ priv->txbbgain_table[30].txbbgain_value = 0x26c0005b;
+ priv->txbbgain_table[31].txbb_iq_amplifygain = -19;
+ priv->txbbgain_table[31].txbbgain_value = 0x14400051;
+ priv->txbbgain_table[32].txbb_iq_amplifygain = -20;
+ priv->txbbgain_table[32].txbbgain_value = 0x24400051;
+ priv->txbbgain_table[33].txbb_iq_amplifygain = -21;
+ priv->txbbgain_table[33].txbbgain_value = 0x1300004c;
+ priv->txbbgain_table[34].txbb_iq_amplifygain = -22;
+ priv->txbbgain_table[34].txbbgain_value = 0x12000048;
+ priv->txbbgain_table[35].txbb_iq_amplifygain = -23;
+ priv->txbbgain_table[35].txbbgain_value = 0x11000044;
+ priv->txbbgain_table[36].txbb_iq_amplifygain = -24;
+ priv->txbbgain_table[36].txbbgain_value = 0x10000040;
+
+ priv->cck_txbbgain_table[0].ccktxbb_valuearray[0] = 0x36;
+ priv->cck_txbbgain_table[0].ccktxbb_valuearray[1] = 0x35;
+ priv->cck_txbbgain_table[0].ccktxbb_valuearray[2] = 0x2e;
+ priv->cck_txbbgain_table[0].ccktxbb_valuearray[3] = 0x25;
+ priv->cck_txbbgain_table[0].ccktxbb_valuearray[4] = 0x1c;
+ priv->cck_txbbgain_table[0].ccktxbb_valuearray[5] = 0x12;
+ priv->cck_txbbgain_table[0].ccktxbb_valuearray[6] = 0x09;
+ priv->cck_txbbgain_table[0].ccktxbb_valuearray[7] = 0x04;
+
+ priv->cck_txbbgain_table[1].ccktxbb_valuearray[0] = 0x33;
+ priv->cck_txbbgain_table[1].ccktxbb_valuearray[1] = 0x32;
+ priv->cck_txbbgain_table[1].ccktxbb_valuearray[2] = 0x2b;
+ priv->cck_txbbgain_table[1].ccktxbb_valuearray[3] = 0x23;
+ priv->cck_txbbgain_table[1].ccktxbb_valuearray[4] = 0x1a;
+ priv->cck_txbbgain_table[1].ccktxbb_valuearray[5] = 0x11;
+ priv->cck_txbbgain_table[1].ccktxbb_valuearray[6] = 0x08;
+ priv->cck_txbbgain_table[1].ccktxbb_valuearray[7] = 0x04;
+
+ priv->cck_txbbgain_table[2].ccktxbb_valuearray[0] = 0x30;
+ priv->cck_txbbgain_table[2].ccktxbb_valuearray[1] = 0x2f;
+ priv->cck_txbbgain_table[2].ccktxbb_valuearray[2] = 0x29;
+ priv->cck_txbbgain_table[2].ccktxbb_valuearray[3] = 0x21;
+ priv->cck_txbbgain_table[2].ccktxbb_valuearray[4] = 0x19;
+ priv->cck_txbbgain_table[2].ccktxbb_valuearray[5] = 0x10;
+ priv->cck_txbbgain_table[2].ccktxbb_valuearray[6] = 0x08;
+ priv->cck_txbbgain_table[2].ccktxbb_valuearray[7] = 0x03;
+
+ priv->cck_txbbgain_table[3].ccktxbb_valuearray[0] = 0x2d;
+ priv->cck_txbbgain_table[3].ccktxbb_valuearray[1] = 0x2d;
+ priv->cck_txbbgain_table[3].ccktxbb_valuearray[2] = 0x27;
+ priv->cck_txbbgain_table[3].ccktxbb_valuearray[3] = 0x1f;
+ priv->cck_txbbgain_table[3].ccktxbb_valuearray[4] = 0x18;
+ priv->cck_txbbgain_table[3].ccktxbb_valuearray[5] = 0x0f;
+ priv->cck_txbbgain_table[3].ccktxbb_valuearray[6] = 0x08;
+ priv->cck_txbbgain_table[3].ccktxbb_valuearray[7] = 0x03;
+
+ priv->cck_txbbgain_table[4].ccktxbb_valuearray[0] = 0x2b;
+ priv->cck_txbbgain_table[4].ccktxbb_valuearray[1] = 0x2a;
+ priv->cck_txbbgain_table[4].ccktxbb_valuearray[2] = 0x25;
+ priv->cck_txbbgain_table[4].ccktxbb_valuearray[3] = 0x1e;
+ priv->cck_txbbgain_table[4].ccktxbb_valuearray[4] = 0x16;
+ priv->cck_txbbgain_table[4].ccktxbb_valuearray[5] = 0x0e;
+ priv->cck_txbbgain_table[4].ccktxbb_valuearray[6] = 0x07;
+ priv->cck_txbbgain_table[4].ccktxbb_valuearray[7] = 0x03;
+
+ priv->cck_txbbgain_table[5].ccktxbb_valuearray[0] = 0x28;
+ priv->cck_txbbgain_table[5].ccktxbb_valuearray[1] = 0x28;
+ priv->cck_txbbgain_table[5].ccktxbb_valuearray[2] = 0x22;
+ priv->cck_txbbgain_table[5].ccktxbb_valuearray[3] = 0x1c;
+ priv->cck_txbbgain_table[5].ccktxbb_valuearray[4] = 0x15;
+ priv->cck_txbbgain_table[5].ccktxbb_valuearray[5] = 0x0d;
+ priv->cck_txbbgain_table[5].ccktxbb_valuearray[6] = 0x07;
+ priv->cck_txbbgain_table[5].ccktxbb_valuearray[7] = 0x03;
+
+ priv->cck_txbbgain_table[6].ccktxbb_valuearray[0] = 0x26;
+ priv->cck_txbbgain_table[6].ccktxbb_valuearray[1] = 0x25;
+ priv->cck_txbbgain_table[6].ccktxbb_valuearray[2] = 0x21;
+ priv->cck_txbbgain_table[6].ccktxbb_valuearray[3] = 0x1b;
+ priv->cck_txbbgain_table[6].ccktxbb_valuearray[4] = 0x14;
+ priv->cck_txbbgain_table[6].ccktxbb_valuearray[5] = 0x0d;
+ priv->cck_txbbgain_table[6].ccktxbb_valuearray[6] = 0x06;
+ priv->cck_txbbgain_table[6].ccktxbb_valuearray[7] = 0x03;
+
+ priv->cck_txbbgain_table[7].ccktxbb_valuearray[0] = 0x24;
+ priv->cck_txbbgain_table[7].ccktxbb_valuearray[1] = 0x23;
+ priv->cck_txbbgain_table[7].ccktxbb_valuearray[2] = 0x1f;
+ priv->cck_txbbgain_table[7].ccktxbb_valuearray[3] = 0x19;
+ priv->cck_txbbgain_table[7].ccktxbb_valuearray[4] = 0x13;
+ priv->cck_txbbgain_table[7].ccktxbb_valuearray[5] = 0x0c;
+ priv->cck_txbbgain_table[7].ccktxbb_valuearray[6] = 0x06;
+ priv->cck_txbbgain_table[7].ccktxbb_valuearray[7] = 0x03;
+
+ priv->cck_txbbgain_table[8].ccktxbb_valuearray[0] = 0x22;
+ priv->cck_txbbgain_table[8].ccktxbb_valuearray[1] = 0x21;
+ priv->cck_txbbgain_table[8].ccktxbb_valuearray[2] = 0x1d;
+ priv->cck_txbbgain_table[8].ccktxbb_valuearray[3] = 0x18;
+ priv->cck_txbbgain_table[8].ccktxbb_valuearray[4] = 0x11;
+ priv->cck_txbbgain_table[8].ccktxbb_valuearray[5] = 0x0b;
+ priv->cck_txbbgain_table[8].ccktxbb_valuearray[6] = 0x06;
+ priv->cck_txbbgain_table[8].ccktxbb_valuearray[7] = 0x02;
+
+ priv->cck_txbbgain_table[9].ccktxbb_valuearray[0] = 0x20;
+ priv->cck_txbbgain_table[9].ccktxbb_valuearray[1] = 0x20;
+ priv->cck_txbbgain_table[9].ccktxbb_valuearray[2] = 0x1b;
+ priv->cck_txbbgain_table[9].ccktxbb_valuearray[3] = 0x16;
+ priv->cck_txbbgain_table[9].ccktxbb_valuearray[4] = 0x11;
+ priv->cck_txbbgain_table[9].ccktxbb_valuearray[5] = 0x08;
+ priv->cck_txbbgain_table[9].ccktxbb_valuearray[6] = 0x05;
+ priv->cck_txbbgain_table[9].ccktxbb_valuearray[7] = 0x02;
+
+ priv->cck_txbbgain_table[10].ccktxbb_valuearray[0] = 0x1f;
+ priv->cck_txbbgain_table[10].ccktxbb_valuearray[1] = 0x1e;
+ priv->cck_txbbgain_table[10].ccktxbb_valuearray[2] = 0x1a;
+ priv->cck_txbbgain_table[10].ccktxbb_valuearray[3] = 0x15;
+ priv->cck_txbbgain_table[10].ccktxbb_valuearray[4] = 0x10;
+ priv->cck_txbbgain_table[10].ccktxbb_valuearray[5] = 0x0a;
+ priv->cck_txbbgain_table[10].ccktxbb_valuearray[6] = 0x05;
+ priv->cck_txbbgain_table[10].ccktxbb_valuearray[7] = 0x02;
+
+ priv->cck_txbbgain_table[11].ccktxbb_valuearray[0] = 0x1d;
+ priv->cck_txbbgain_table[11].ccktxbb_valuearray[1] = 0x1c;
+ priv->cck_txbbgain_table[11].ccktxbb_valuearray[2] = 0x18;
+ priv->cck_txbbgain_table[11].ccktxbb_valuearray[3] = 0x14;
+ priv->cck_txbbgain_table[11].ccktxbb_valuearray[4] = 0x0f;
+ priv->cck_txbbgain_table[11].ccktxbb_valuearray[5] = 0x0a;
+ priv->cck_txbbgain_table[11].ccktxbb_valuearray[6] = 0x05;
+ priv->cck_txbbgain_table[11].ccktxbb_valuearray[7] = 0x02;
+
+ priv->cck_txbbgain_table[12].ccktxbb_valuearray[0] = 0x1b;
+ priv->cck_txbbgain_table[12].ccktxbb_valuearray[1] = 0x1a;
+ priv->cck_txbbgain_table[12].ccktxbb_valuearray[2] = 0x17;
+ priv->cck_txbbgain_table[12].ccktxbb_valuearray[3] = 0x13;
+ priv->cck_txbbgain_table[12].ccktxbb_valuearray[4] = 0x0e;
+ priv->cck_txbbgain_table[12].ccktxbb_valuearray[5] = 0x09;
+ priv->cck_txbbgain_table[12].ccktxbb_valuearray[6] = 0x04;
+ priv->cck_txbbgain_table[12].ccktxbb_valuearray[7] = 0x02;
+
+ priv->cck_txbbgain_table[13].ccktxbb_valuearray[0] = 0x1a;
+ priv->cck_txbbgain_table[13].ccktxbb_valuearray[1] = 0x19;
+ priv->cck_txbbgain_table[13].ccktxbb_valuearray[2] = 0x16;
+ priv->cck_txbbgain_table[13].ccktxbb_valuearray[3] = 0x12;
+ priv->cck_txbbgain_table[13].ccktxbb_valuearray[4] = 0x0d;
+ priv->cck_txbbgain_table[13].ccktxbb_valuearray[5] = 0x09;
+ priv->cck_txbbgain_table[13].ccktxbb_valuearray[6] = 0x04;
+ priv->cck_txbbgain_table[13].ccktxbb_valuearray[7] = 0x02;
+
+ priv->cck_txbbgain_table[14].ccktxbb_valuearray[0] = 0x18;
+ priv->cck_txbbgain_table[14].ccktxbb_valuearray[1] = 0x17;
+ priv->cck_txbbgain_table[14].ccktxbb_valuearray[2] = 0x15;
+ priv->cck_txbbgain_table[14].ccktxbb_valuearray[3] = 0x11;
+ priv->cck_txbbgain_table[14].ccktxbb_valuearray[4] = 0x0c;
+ priv->cck_txbbgain_table[14].ccktxbb_valuearray[5] = 0x08;
+ priv->cck_txbbgain_table[14].ccktxbb_valuearray[6] = 0x04;
+ priv->cck_txbbgain_table[14].ccktxbb_valuearray[7] = 0x02;
+
+ priv->cck_txbbgain_table[15].ccktxbb_valuearray[0] = 0x17;
+ priv->cck_txbbgain_table[15].ccktxbb_valuearray[1] = 0x16;
+ priv->cck_txbbgain_table[15].ccktxbb_valuearray[2] = 0x13;
+ priv->cck_txbbgain_table[15].ccktxbb_valuearray[3] = 0x10;
+ priv->cck_txbbgain_table[15].ccktxbb_valuearray[4] = 0x0c;
+ priv->cck_txbbgain_table[15].ccktxbb_valuearray[5] = 0x08;
+ priv->cck_txbbgain_table[15].ccktxbb_valuearray[6] = 0x04;
+ priv->cck_txbbgain_table[15].ccktxbb_valuearray[7] = 0x02;
+
+ priv->cck_txbbgain_table[16].ccktxbb_valuearray[0] = 0x16;
+ priv->cck_txbbgain_table[16].ccktxbb_valuearray[1] = 0x15;
+ priv->cck_txbbgain_table[16].ccktxbb_valuearray[2] = 0x12;
+ priv->cck_txbbgain_table[16].ccktxbb_valuearray[3] = 0x0f;
+ priv->cck_txbbgain_table[16].ccktxbb_valuearray[4] = 0x0b;
+ priv->cck_txbbgain_table[16].ccktxbb_valuearray[5] = 0x07;
+ priv->cck_txbbgain_table[16].ccktxbb_valuearray[6] = 0x04;
+ priv->cck_txbbgain_table[16].ccktxbb_valuearray[7] = 0x01;
+
+ priv->cck_txbbgain_table[17].ccktxbb_valuearray[0] = 0x14;
+ priv->cck_txbbgain_table[17].ccktxbb_valuearray[1] = 0x14;
+ priv->cck_txbbgain_table[17].ccktxbb_valuearray[2] = 0x11;
+ priv->cck_txbbgain_table[17].ccktxbb_valuearray[3] = 0x0e;
+ priv->cck_txbbgain_table[17].ccktxbb_valuearray[4] = 0x0b;
+ priv->cck_txbbgain_table[17].ccktxbb_valuearray[5] = 0x07;
+ priv->cck_txbbgain_table[17].ccktxbb_valuearray[6] = 0x03;
+ priv->cck_txbbgain_table[17].ccktxbb_valuearray[7] = 0x02;
+
+ priv->cck_txbbgain_table[18].ccktxbb_valuearray[0] = 0x13;
+ priv->cck_txbbgain_table[18].ccktxbb_valuearray[1] = 0x13;
+ priv->cck_txbbgain_table[18].ccktxbb_valuearray[2] = 0x10;
+ priv->cck_txbbgain_table[18].ccktxbb_valuearray[3] = 0x0d;
+ priv->cck_txbbgain_table[18].ccktxbb_valuearray[4] = 0x0a;
+ priv->cck_txbbgain_table[18].ccktxbb_valuearray[5] = 0x06;
+ priv->cck_txbbgain_table[18].ccktxbb_valuearray[6] = 0x03;
+ priv->cck_txbbgain_table[18].ccktxbb_valuearray[7] = 0x01;
+
+ priv->cck_txbbgain_table[19].ccktxbb_valuearray[0] = 0x12;
+ priv->cck_txbbgain_table[19].ccktxbb_valuearray[1] = 0x12;
+ priv->cck_txbbgain_table[19].ccktxbb_valuearray[2] = 0x0f;
+ priv->cck_txbbgain_table[19].ccktxbb_valuearray[3] = 0x0c;
+ priv->cck_txbbgain_table[19].ccktxbb_valuearray[4] = 0x09;
+ priv->cck_txbbgain_table[19].ccktxbb_valuearray[5] = 0x06;
+ priv->cck_txbbgain_table[19].ccktxbb_valuearray[6] = 0x03;
+ priv->cck_txbbgain_table[19].ccktxbb_valuearray[7] = 0x01;
+
+ priv->cck_txbbgain_table[20].ccktxbb_valuearray[0] = 0x11;
+ priv->cck_txbbgain_table[20].ccktxbb_valuearray[1] = 0x11;
+ priv->cck_txbbgain_table[20].ccktxbb_valuearray[2] = 0x0f;
+ priv->cck_txbbgain_table[20].ccktxbb_valuearray[3] = 0x0c;
+ priv->cck_txbbgain_table[20].ccktxbb_valuearray[4] = 0x09;
+ priv->cck_txbbgain_table[20].ccktxbb_valuearray[5] = 0x06;
+ priv->cck_txbbgain_table[20].ccktxbb_valuearray[6] = 0x03;
+ priv->cck_txbbgain_table[20].ccktxbb_valuearray[7] = 0x01;
+
+ priv->cck_txbbgain_table[21].ccktxbb_valuearray[0] = 0x10;
+ priv->cck_txbbgain_table[21].ccktxbb_valuearray[1] = 0x10;
+ priv->cck_txbbgain_table[21].ccktxbb_valuearray[2] = 0x0e;
+ priv->cck_txbbgain_table[21].ccktxbb_valuearray[3] = 0x0b;
+ priv->cck_txbbgain_table[21].ccktxbb_valuearray[4] = 0x08;
+ priv->cck_txbbgain_table[21].ccktxbb_valuearray[5] = 0x05;
+ priv->cck_txbbgain_table[21].ccktxbb_valuearray[6] = 0x03;
+ priv->cck_txbbgain_table[21].ccktxbb_valuearray[7] = 0x01;
+
+ priv->cck_txbbgain_table[22].ccktxbb_valuearray[0] = 0x0f;
+ priv->cck_txbbgain_table[22].ccktxbb_valuearray[1] = 0x0f;
+ priv->cck_txbbgain_table[22].ccktxbb_valuearray[2] = 0x0d;
+ priv->cck_txbbgain_table[22].ccktxbb_valuearray[3] = 0x0b;
+ priv->cck_txbbgain_table[22].ccktxbb_valuearray[4] = 0x08;
+ priv->cck_txbbgain_table[22].ccktxbb_valuearray[5] = 0x05;
+ priv->cck_txbbgain_table[22].ccktxbb_valuearray[6] = 0x03;
+ priv->cck_txbbgain_table[22].ccktxbb_valuearray[7] = 0x01;
+
+ priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[0] = 0x36;
+ priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[1] = 0x35;
+ priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[2] = 0x2e;
+ priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[3] = 0x1b;
+ priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[0] = 0x33;
+ priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[1] = 0x32;
+ priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[2] = 0x2b;
+ priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[3] = 0x19;
+ priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[0] = 0x30;
+ priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[1] = 0x2f;
+ priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[2] = 0x29;
+ priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[3] = 0x18;
+ priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[0] = 0x2d;
+ priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[1] = 0x2d;
+ priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[2] = 0x27;
+ priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[3] = 0x17;
+ priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[0] = 0x2b;
+ priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[1] = 0x2a;
+ priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[2] = 0x25;
+ priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[3] = 0x15;
+ priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[0] = 0x28;
+ priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[1] = 0x28;
+ priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[2] = 0x22;
+ priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[3] = 0x14;
+ priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[0] = 0x26;
+ priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[1] = 0x25;
+ priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[2] = 0x21;
+ priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[3] = 0x13;
+ priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[0] = 0x24;
+ priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[1] = 0x23;
+ priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[2] = 0x1f;
+ priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[3] = 0x12;
+ priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[0] = 0x22;
+ priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[1] = 0x21;
+ priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[2] = 0x1d;
+ priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[3] = 0x11;
+ priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[0] = 0x20;
+ priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[1] = 0x20;
+ priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[2] = 0x1b;
+ priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[3] = 0x10;
+ priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[0] = 0x1f;
+ priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[1] = 0x1e;
+ priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[2] = 0x1a;
+ priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[3] = 0x0f;
+ priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[0] = 0x1d;
+ priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[1] = 0x1c;
+ priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[2] = 0x18;
+ priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[3] = 0x0e;
+ priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[0] = 0x1b;
+ priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[1] = 0x1a;
+ priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[2] = 0x17;
+ priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[3] = 0x0e;
+ priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[0] = 0x1a;
+ priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[1] = 0x19;
+ priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[2] = 0x16;
+ priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[3] = 0x0d;
+ priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[0] = 0x18;
+ priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[1] = 0x17;
+ priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[2] = 0x15;
+ priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[3] = 0x0c;
+ priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[0] = 0x17;
+ priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[1] = 0x16;
+ priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[2] = 0x13;
+ priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[3] = 0x0b;
+ priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[0] = 0x16;
+ priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[1] = 0x15;
+ priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[2] = 0x12;
+ priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[3] = 0x0b;
+ priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[0] = 0x14;
+ priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[1] = 0x14;
+ priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[2] = 0x11;
+ priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[3] = 0x0a;
+ priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[0] = 0x13;
+ priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[1] = 0x13;
+ priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[2] = 0x10;
+ priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[3] = 0x0a;
+ priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[0] = 0x12;
+ priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[1] = 0x12;
+ priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[2] = 0x0f;
+ priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[3] = 0x09;
+ priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[0] = 0x11;
+ priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[1] = 0x11;
+ priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[2] = 0x0f;
+ priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[3] = 0x09;
+ priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[0] = 0x10;
+ priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[1] = 0x10;
+ priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[2] = 0x0e;
+ priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[3] = 0x08;
+ priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[7] = 0x00;
+
+ priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[0] = 0x0f;
+ priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[1] = 0x0f;
+ priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[2] = 0x0d;
+ priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[3] = 0x08;
+ priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[4] = 0x00;
+ priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[5] = 0x00;
+ priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[6] = 0x00;
+ priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[7] = 0x00;
+
+ priv->btxpower_tracking = true;
+ priv->txpower_count = 0;
+ priv->btxpower_trackingInit = false;
+
+}
+
+static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+
+ if (priv->rtllib->FwRWRF)
+ priv->btxpower_tracking = true;
+ else
+ priv->btxpower_tracking = false;
+ priv->txpower_count = 0;
+ priv->btxpower_trackingInit = false;
+ RT_TRACE(COMP_POWER_TRACKING, "pMgntInfo->bTXPowerTracking = %d\n",
+ priv->btxpower_tracking);
+}
+
+void dm_initialize_txpower_tracking(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->IC_Cut >= IC_VersionCut_D)
+ dm_InitializeTXPowerTracking_TSSI(dev);
+ else
+ dm_InitializeTXPowerTracking_ThermalMeter(dev);
+}
+
+static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ static u32 tx_power_track_counter;
+
+ RT_TRACE(COMP_POWER_TRACKING, "%s()\n", __func__);
+ if (read_nic_byte(dev, 0x11e) == 1)
+ return;
+ if (!priv->btxpower_tracking)
+ return;
+ tx_power_track_counter++;
+
+
+ if (tx_power_track_counter >= 180) {
+ queue_delayed_work_rsl(priv->priv_wq, &priv->txpower_tracking_wq, 0);
+ tx_power_track_counter = 0;
+ }
+
+}
+static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ static u8 TM_Trigger;
+ u8 TxPowerCheckCnt = 0;
+
+ if (IS_HARDWARE_TYPE_8192SE(dev))
+ TxPowerCheckCnt = 5;
+ else
+ TxPowerCheckCnt = 2;
+ if (!priv->btxpower_tracking)
+ return;
+
+ if (priv->txpower_count <= TxPowerCheckCnt) {
+ priv->txpower_count++;
+ return;
+ }
+
+ if (!TM_Trigger) {
+ {
+ rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+ rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+ rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+ rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+ }
+ TM_Trigger = 1;
+ return;
+ }
+ netdev_info(dev, "===============>Schedule TxPowerTrackingWorkItem\n");
+ queue_delayed_work_rsl(priv->priv_wq, &priv->txpower_tracking_wq, 0);
+ TM_Trigger = 0;
+
+}
+
+static void dm_check_txpower_tracking(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->IC_Cut >= IC_VersionCut_D)
+ dm_CheckTXPowerTracking_TSSI(dev);
+ else
+ dm_CheckTXPowerTracking_ThermalMeter(dev);
+}
+
+static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool bInCH14)
+{
+ u32 TempVal;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ TempVal = 0;
+ if (!bInCH14) {
+ TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
+ (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8));
+
+ rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+ TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
+ (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
+ (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16)+
+ (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
+ rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+ TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
+ (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8));
+
+ rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+ } else {
+ TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
+ (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8));
+
+ rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+ TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
+ (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
+ (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16)+
+ (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
+ rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+ TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
+ (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8));
+
+ rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+ }
+
+
+}
+
+static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH14)
+{
+ u32 TempVal;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ TempVal = 0;
+ if (!bInCH14) {
+ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] +
+ (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8);
+ rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+ RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
+ rCCK0_TxFilter1, TempVal);
+ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][2] +
+ (CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) +
+ (CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16)+
+ (CCKSwingTable_Ch1_Ch13[priv->CCK_index][5]<<24);
+ rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+ RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
+ rCCK0_TxFilter2, TempVal);
+ TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] +
+ (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8);
+
+ rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+ RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
+ rCCK0_DebugPort, TempVal);
+ } else {
+ TempVal = CCKSwingTable_Ch14[priv->CCK_index][0] +
+ (CCKSwingTable_Ch14[priv->CCK_index][1]<<8);
+
+ rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+ RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
+ rCCK0_TxFilter1, TempVal);
+ TempVal = CCKSwingTable_Ch14[priv->CCK_index][2] +
+ (CCKSwingTable_Ch14[priv->CCK_index][3]<<8) +
+ (CCKSwingTable_Ch14[priv->CCK_index][4]<<16)+
+ (CCKSwingTable_Ch14[priv->CCK_index][5]<<24);
+ rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+ RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
+ rCCK0_TxFilter2, TempVal);
+ TempVal = CCKSwingTable_Ch14[priv->CCK_index][6] +
+ (CCKSwingTable_Ch14[priv->CCK_index][7]<<8);
+
+ rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+ RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
+ rCCK0_DebugPort, TempVal);
+ }
+ }
+
+void dm_cck_txpower_adjust(struct net_device *dev, bool binch14)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->IC_Cut >= IC_VersionCut_D)
+ dm_CCKTxPowerAdjust_TSSI(dev, binch14);
+ else
+ dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14);
+}
+
+static void dm_txpower_reset_recovery(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n");
+ rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
+ priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value);
+ RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n",
+ priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value);
+ RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFA_txPowerTrackingIndex is %x\n",
+ priv->rfa_txpowertrackingindex);
+ RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF A I/Q Amplify Gain is %ld\n",
+ priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbb_iq_amplifygain);
+ RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n",
+ priv->CCKPresentAttentuation);
+ dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+
+ rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord,
+ priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value);
+ RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n",
+ priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value);
+ RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n",
+ priv->rfc_txpowertrackingindex);
+ RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n",
+ priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain);
+
+}
+
+void dm_restore_dynamic_mechanism_state(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 reg_ratr = priv->rate_adaptive.last_ratr;
+ u32 ratr_value;
+
+ if (!priv->up) {
+ RT_TRACE(COMP_RATE, "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n");
+ return;
+ }
+
+ if (priv->rate_adaptive.rate_adaptive_disabled)
+ return;
+ if (!(priv->rtllib->mode == WIRELESS_MODE_N_24G ||
+ priv->rtllib->mode == WIRELESS_MODE_N_5G))
+ return;
+ ratr_value = reg_ratr;
+ if (priv->rf_type == RF_1T2R)
+ ratr_value &= ~(RATE_ALL_OFDM_2SS);
+ write_nic_dword(dev, RATR0, ratr_value);
+ write_nic_byte(dev, UFWP, 1);
+ if (priv->btxpower_trackingInit && priv->btxpower_tracking)
+ dm_txpower_reset_recovery(dev);
+
+ dm_bb_initialgain_restore(dev);
+
+}
+
+static void dm_bb_initialgain_restore(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 bit_mask = 0x7f;
+
+ if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
+ return;
+
+ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+ rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask, (u32)priv->initgain_backup.xaagccore1);
+ rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask, (u32)priv->initgain_backup.xbagccore1);
+ rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask, (u32)priv->initgain_backup.xcagccore1);
+ rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, bit_mask, (u32)priv->initgain_backup.xdagccore1);
+ bit_mask = bMaskByte2;
+ rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask, (u32)priv->initgain_backup.cca);
+
+ RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n", priv->initgain_backup.xaagccore1);
+ RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc58 is %x\n", priv->initgain_backup.xbagccore1);
+ RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n", priv->initgain_backup.xcagccore1);
+ RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n", priv->initgain_backup.xdagccore1);
+ RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n", priv->initgain_backup.cca);
+ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+
+}
+
+
+void dm_backup_dynamic_mechanism_state(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->bswitch_fsync = false;
+ priv->bfsync_processing = false;
+ dm_bb_initialgain_backup(dev);
+
+}
+
+
+static void dm_bb_initialgain_backup(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 bit_mask = bMaskByte0;
+
+ if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
+ return;
+
+ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+ priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask);
+ priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask);
+ priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask);
+ priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bit_mask);
+ bit_mask = bMaskByte2;
+ priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask);
+
+ RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n", priv->initgain_backup.xaagccore1);
+ RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc58 is %x\n", priv->initgain_backup.xbagccore1);
+ RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc60 is %x\n", priv->initgain_backup.xcagccore1);
+ RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n", priv->initgain_backup.xdagccore1);
+ RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n", priv->initgain_backup.cca);
+
+}
+
+void dm_change_dynamic_initgain_thresh(struct net_device *dev,
+ u32 dm_type, u32 dm_value)
+{
+ if (dm_type == DIG_TYPE_THRESH_HIGH) {
+ dm_digtable.rssi_high_thresh = dm_value;
+ } else if (dm_type == DIG_TYPE_THRESH_LOW) {
+ dm_digtable.rssi_low_thresh = dm_value;
+ } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) {
+ dm_digtable.rssi_high_power_highthresh = dm_value;
+ } else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_LOW) {
+ dm_digtable.rssi_high_power_lowthresh = dm_value;
+ } else if (dm_type == DIG_TYPE_ENABLE) {
+ dm_digtable.dig_state = DM_STA_DIG_MAX;
+ dm_digtable.dig_enable_flag = true;
+ } else if (dm_type == DIG_TYPE_DISABLE) {
+ dm_digtable.dig_state = DM_STA_DIG_MAX;
+ dm_digtable.dig_enable_flag = false;
+ } else if (dm_type == DIG_TYPE_DBG_MODE) {
+ if (dm_value >= DM_DBG_MAX)
+ dm_value = DM_DBG_OFF;
+ dm_digtable.dbg_mode = (u8)dm_value;
+ } else if (dm_type == DIG_TYPE_RSSI) {
+ if (dm_value > 100)
+ dm_value = 30;
+ dm_digtable.rssi_val = (long)dm_value;
+ } else if (dm_type == DIG_TYPE_ALGORITHM) {
+ if (dm_value >= DIG_ALGO_MAX)
+ dm_value = DIG_ALGO_BY_FALSE_ALARM;
+ if (dm_digtable.dig_algorithm != (u8)dm_value)
+ dm_digtable.dig_algorithm_switch = 1;
+ dm_digtable.dig_algorithm = (u8)dm_value;
+ } else if (dm_type == DIG_TYPE_BACKOFF) {
+ if (dm_value > 30)
+ dm_value = 30;
+ dm_digtable.backoff_val = (u8)dm_value;
+ } else if (dm_type == DIG_TYPE_RX_GAIN_MIN) {
+ if (dm_value == 0)
+ dm_value = 0x1;
+ dm_digtable.rx_gain_range_min = (u8)dm_value;
+ } else if (dm_type == DIG_TYPE_RX_GAIN_MAX) {
+ if (dm_value > 0x50)
+ dm_value = 0x50;
+ dm_digtable.rx_gain_range_max = (u8)dm_value;
+ }
+}
+
+static void dm_dig_init(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ dm_digtable.dig_enable_flag = true;
+ dm_digtable.Backoff_Enable_Flag = true;
+
+ dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI;
+
+ dm_digtable.Dig_TwoPort_Algorithm = DIG_TWO_PORT_ALGO_RSSI;
+ dm_digtable.Dig_Ext_Port_Stage = DIG_EXT_PORT_STAGE_MAX;
+ dm_digtable.dbg_mode = DM_DBG_OFF;
+ dm_digtable.dig_algorithm_switch = 0;
+
+ dm_digtable.dig_state = DM_STA_DIG_MAX;
+ dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
+ dm_digtable.CurSTAConnectState = dm_digtable.PreSTAConnectState = DIG_STA_DISCONNECT;
+ dm_digtable.CurAPConnectState = dm_digtable.PreAPConnectState = DIG_AP_DISCONNECT;
+ dm_digtable.initialgain_lowerbound_state = false;
+
+ dm_digtable.rssi_low_thresh = DM_DIG_THRESH_LOW;
+ dm_digtable.rssi_high_thresh = DM_DIG_THRESH_HIGH;
+
+ dm_digtable.FALowThresh = DM_FALSEALARM_THRESH_LOW;
+ dm_digtable.FAHighThresh = DM_FALSEALARM_THRESH_HIGH;
+
+ dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
+ dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
+
+ dm_digtable.rssi_val = 50;
+ dm_digtable.backoff_val = DM_DIG_BACKOFF;
+ dm_digtable.rx_gain_range_max = DM_DIG_MAX;
+ if (priv->CustomerID == RT_CID_819x_Netcore)
+ dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore;
+ else
+ dm_digtable.rx_gain_range_min = DM_DIG_MIN;
+
+ dm_digtable.BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
+ dm_digtable.BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
+}
+
+static void dm_ctrl_initgain_byrssi(struct net_device *dev)
+{
+
+ if (dm_digtable.dig_enable_flag == false)
+ return;
+
+ if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
+ dm_ctrl_initgain_byrssi_by_fwfalse_alarm(dev);
+ else if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
+ dm_ctrl_initgain_byrssi_by_driverrssi(dev);
+ else
+ return;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function: dm_CtrlInitGainBeforeConnectByRssiAndFalseAlarm()
+ *
+ * Overview: Driver monitor RSSI and False Alarm to change initial gain.
+ Only change initial gain during link in progress.
+ *
+ * Input: IN PADAPTER pAdapter
+ *
+ * Output: NONE
+ *
+ * Return: NONE
+ *
+ * Revised History:
+ * When Who Remark
+ * 03/04/2009 hpfan Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+
+static void dm_ctrl_initgain_byrssi_by_driverrssi(
+ struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 i;
+ static u8 fw_dig;
+
+ if (dm_digtable.dig_enable_flag == false)
+ return;
+
+ if (dm_digtable.dig_algorithm_switch)
+ fw_dig = 0;
+ if (fw_dig <= 3) {
+ for (i = 0; i < 3; i++)
+ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+ fw_dig++;
+ dm_digtable.dig_state = DM_STA_DIG_OFF;
+ }
+
+ if (priv->rtllib->state == RTLLIB_LINKED)
+ dm_digtable.CurSTAConnectState = DIG_STA_CONNECT;
+ else
+ dm_digtable.CurSTAConnectState = DIG_STA_DISCONNECT;
+
+
+ if (dm_digtable.dbg_mode == DM_DBG_OFF)
+ dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb;
+ dm_initial_gain(dev);
+ dm_pd_th(dev);
+ dm_cs_ratio(dev);
+ if (dm_digtable.dig_algorithm_switch)
+ dm_digtable.dig_algorithm_switch = 0;
+ dm_digtable.PreSTAConnectState = dm_digtable.CurSTAConnectState;
+
+}
+
+static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
+ struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ static u32 reset_cnt;
+ u8 i;
+
+ if (dm_digtable.dig_enable_flag == false)
+ return;
+
+ if (dm_digtable.dig_algorithm_switch) {
+ dm_digtable.dig_state = DM_STA_DIG_MAX;
+ for (i = 0; i < 3; i++)
+ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+ dm_digtable.dig_algorithm_switch = 0;
+ }
+
+ if (priv->rtllib->state != RTLLIB_LINKED)
+ return;
+
+ if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) &&
+ (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh))
+ return;
+ if (priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh) {
+ if (dm_digtable.dig_state == DM_STA_DIG_OFF &&
+ (priv->reset_count == reset_cnt))
+ return;
+ reset_cnt = priv->reset_count;
+
+ dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
+ dm_digtable.dig_state = DM_STA_DIG_OFF;
+
+ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+
+ write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17);
+ write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17);
+ write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17);
+ write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17);
+
+ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
+ else
+ write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+
+ write_nic_byte(dev, 0xa0a, 0x08);
+
+ return;
+ }
+
+ if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) {
+ u8 reset_flag = 0;
+
+ if (dm_digtable.dig_state == DM_STA_DIG_ON &&
+ (priv->reset_count == reset_cnt)) {
+ dm_ctrl_initgain_byrssi_highpwr(dev);
+ return;
+ }
+ if (priv->reset_count != reset_cnt)
+ reset_flag = 1;
+
+ reset_cnt = priv->reset_count;
+
+ dm_digtable.dig_state = DM_STA_DIG_ON;
+
+ if (reset_flag == 1) {
+ write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c);
+ write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c);
+ write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c);
+ write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c);
+ } else {
+ write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20);
+ write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20);
+ write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20);
+ write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20);
+ }
+
+ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+ else
+ write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+
+ write_nic_byte(dev, 0xa0a, 0xcd);
+
+ rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+ }
+ dm_ctrl_initgain_byrssi_highpwr(dev);
+}
+
+
+static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ static u32 reset_cnt_highpwr;
+
+ if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) &&
+ (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh))
+ return;
+
+ if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) {
+ if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON &&
+ (priv->reset_count == reset_cnt_highpwr))
+ return;
+ dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
+
+ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
+ else
+ write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
+ } else {
+ if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF &&
+ (priv->reset_count == reset_cnt_highpwr))
+ return;
+ dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF;
+
+ if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh &&
+ priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) {
+ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+ else
+ write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+ }
+ }
+ reset_cnt_highpwr = priv->reset_count;
+}
+
+static void dm_initial_gain(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 initial_gain = 0;
+ static u8 initialized, force_write;
+ static u32 reset_cnt;
+
+ if (dm_digtable.dig_algorithm_switch) {
+ initialized = 0;
+ reset_cnt = 0;
+ }
+
+ if (rtllib_act_scanning(priv->rtllib, true) == true) {
+ force_write = 1;
+ return;
+ }
+
+ if (dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState) {
+ if (dm_digtable.CurSTAConnectState == DIG_STA_CONNECT) {
+ if ((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max)
+ dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max;
+ else if ((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
+ dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min;
+ else
+ dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val;
+ } else {
+ if (dm_digtable.cur_ig_value == 0)
+ dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
+ else
+ dm_digtable.cur_ig_value = dm_digtable.pre_ig_value;
+ }
+ } else {
+ dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
+ dm_digtable.pre_ig_value = 0;
+ }
+
+ if (priv->reset_count != reset_cnt) {
+ force_write = 1;
+ reset_cnt = priv->reset_count;
+ }
+
+ if (dm_digtable.pre_ig_value != read_nic_byte(dev, rOFDM0_XAAGCCore1))
+ force_write = 1;
+
+ if ((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value)
+ || !initialized || force_write) {
+ initial_gain = (u8)dm_digtable.cur_ig_value;
+ write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain);
+ write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain);
+ write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain);
+ write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain);
+ dm_digtable.pre_ig_value = dm_digtable.cur_ig_value;
+ initialized = 1;
+ force_write = 0;
+ }
+}
+
+static void dm_pd_th(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ static u8 initialized, force_write;
+ static u32 reset_cnt;
+
+ if (dm_digtable.dig_algorithm_switch) {
+ initialized = 0;
+ reset_cnt = 0;
+ }
+
+ if (dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState) {
+ if (dm_digtable.CurSTAConnectState == DIG_STA_CONNECT) {
+ if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh)
+ dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER;
+ else if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)
+ dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
+ else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) &&
+ (dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh))
+ dm_digtable.curpd_thstate = DIG_PD_AT_NORMAL_POWER;
+ else
+ dm_digtable.curpd_thstate = dm_digtable.prepd_thstate;
+ } else {
+ dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
+ }
+ } else {
+ dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
+ }
+
+ if (priv->reset_count != reset_cnt) {
+ force_write = 1;
+ reset_cnt = priv->reset_count;
+ }
+
+ if ((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) ||
+ (initialized <= 3) || force_write) {
+ if (dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) {
+ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
+ else
+ write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+ } else if (dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) {
+ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+ else
+ write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+ } else if (dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) {
+ if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
+ write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
+ else
+ write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
+ }
+ dm_digtable.prepd_thstate = dm_digtable.curpd_thstate;
+ if (initialized <= 3)
+ initialized++;
+ force_write = 0;
+ }
+}
+
+static void dm_cs_ratio(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ static u8 initialized, force_write;
+ static u32 reset_cnt;
+
+ if (dm_digtable.dig_algorithm_switch) {
+ initialized = 0;
+ reset_cnt = 0;
+ }
+
+ if (dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState) {
+ if (dm_digtable.CurSTAConnectState == DIG_STA_CONNECT) {
+ if (dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)
+ dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
+ else if (dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh)
+ dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER;
+ else
+ dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state;
+ } else {
+ dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
+ }
+ } else {
+ dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
+ }
+
+ if (priv->reset_count != reset_cnt) {
+ force_write = 1;
+ reset_cnt = priv->reset_count;
+ }
+
+
+ if ((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) ||
+ !initialized || force_write) {
+ if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER)
+ write_nic_byte(dev, 0xa0a, 0x08);
+ else if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER)
+ write_nic_byte(dev, 0xa0a, 0xcd);
+ dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state;
+ initialized = 1;
+ force_write = 0;
+ }
+}
+
+void dm_init_edca_turbo(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->bcurrent_turbo_EDCA = false;
+ priv->rtllib->bis_any_nonbepkts = false;
+ priv->bis_cur_rdlstate = false;
+}
+
+static void dm_check_edca_turbo(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_hi_throughput *pHTInfo = priv->rtllib->pHTInfo;
+
+ static unsigned long lastTxOkCnt;
+ static unsigned long lastRxOkCnt;
+ unsigned long curTxOkCnt = 0;
+ unsigned long curRxOkCnt = 0;
+
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC)
+ goto dm_CheckEdcaTurbo_EXIT;
+ if (priv->rtllib->state != RTLLIB_LINKED)
+ goto dm_CheckEdcaTurbo_EXIT;
+ if (priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO)
+ goto dm_CheckEdcaTurbo_EXIT;
+
+ {
+ u8 *peername[11] = {
+ "unknown", "realtek_90", "realtek_92se", "broadcom",
+ "ralink", "atheros", "cisco", "marvell", "92u_softap",
+ "self_softap"
+ };
+ static int wb_tmp;
+
+ if (wb_tmp == 0) {
+ netdev_info(dev,
+ "%s():iot peer is %s, bssid: %pM\n",
+ __func__, peername[pHTInfo->IOTPeer],
+ priv->rtllib->current_network.bssid);
+ wb_tmp = 1;
+ }
+ }
+ if (!priv->rtllib->bis_any_nonbepkts) {
+ curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
+ curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
+ if (pHTInfo->IOTAction & HT_IOT_ACT_EDCA_BIAS_ON_RX) {
+ if (curTxOkCnt > 4*curRxOkCnt) {
+ if (priv->bis_cur_rdlstate ||
+ !priv->bcurrent_turbo_EDCA) {
+ write_nic_dword(dev, EDCAPARA_BE,
+ edca_setting_UL[pHTInfo->IOTPeer]);
+ priv->bis_cur_rdlstate = false;
+ }
+ } else {
+ if (!priv->bis_cur_rdlstate ||
+ !priv->bcurrent_turbo_EDCA) {
+ if (priv->rtllib->mode == WIRELESS_MODE_G)
+ write_nic_dword(dev, EDCAPARA_BE,
+ edca_setting_DL_GMode[pHTInfo->IOTPeer]);
+ else
+ write_nic_dword(dev, EDCAPARA_BE,
+ edca_setting_DL[pHTInfo->IOTPeer]);
+ priv->bis_cur_rdlstate = true;
+ }
+ }
+ priv->bcurrent_turbo_EDCA = true;
+ } else {
+ if (curRxOkCnt > 4*curTxOkCnt) {
+ if (!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) {
+ if (priv->rtllib->mode == WIRELESS_MODE_G)
+ write_nic_dword(dev, EDCAPARA_BE,
+ edca_setting_DL_GMode[pHTInfo->IOTPeer]);
+ else
+ write_nic_dword(dev, EDCAPARA_BE,
+ edca_setting_DL[pHTInfo->IOTPeer]);
+ priv->bis_cur_rdlstate = true;
+ }
+ } else {
+ if (priv->bis_cur_rdlstate ||
+ !priv->bcurrent_turbo_EDCA) {
+ write_nic_dword(dev, EDCAPARA_BE,
+ edca_setting_UL[pHTInfo->IOTPeer]);
+ priv->bis_cur_rdlstate = false;
+ }
+
+ }
+
+ priv->bcurrent_turbo_EDCA = true;
+ }
+ } else {
+ if (priv->bcurrent_turbo_EDCA) {
+ u8 tmp = AC0_BE;
+
+ priv->rtllib->SetHwRegHandler(dev, HW_VAR_AC_PARAM, (u8 *)(&tmp));
+ priv->bcurrent_turbo_EDCA = false;
+ }
+ }
+
+
+dm_CheckEdcaTurbo_EXIT:
+ priv->rtllib->bis_any_nonbepkts = false;
+ lastTxOkCnt = priv->stats.txbytesunicast;
+ lastRxOkCnt = priv->stats.rxbytesunicast;
+}
+
+static void dm_init_ctstoself(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv((struct net_device *)dev);
+
+ priv->rtllib->bCTSToSelfEnable = true;
+ priv->rtllib->CTSToSelfTH = CTSToSelfTHVal;
+}
+
+static void dm_ctstoself(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv((struct net_device *)dev);
+ struct rt_hi_throughput *pHTInfo = priv->rtllib->pHTInfo;
+ static unsigned long lastTxOkCnt;
+ static unsigned long lastRxOkCnt;
+ unsigned long curTxOkCnt = 0;
+ unsigned long curRxOkCnt = 0;
+
+ if (priv->rtllib->bCTSToSelfEnable != true) {
+ pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
+ return;
+ }
+ if (pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) {
+ curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
+ curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
+ if (curRxOkCnt > 4*curTxOkCnt)
+ pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
+ else
+ pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
+
+ lastTxOkCnt = priv->stats.txbytesunicast;
+ lastRxOkCnt = priv->stats.rxbytesunicast;
+ }
+}
+
+
+static void dm_Init_WA_Broadcom_IOT(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv((struct net_device *)dev);
+ struct rt_hi_throughput *pHTInfo = priv->rtllib->pHTInfo;
+
+ pHTInfo->bWAIotBroadcom = false;
+ pHTInfo->WAIotTH = WAIotTHVal;
+}
+
+static void dm_check_pbc_gpio(struct net_device *dev)
+{
+}
+
+void dm_CheckRfCtrlGPIO(void *data)
+{
+ struct r8192_priv *priv = container_of_dwork_rsl(data,
+ struct r8192_priv, gpio_change_rf_wq);
+ struct net_device *dev = priv->rtllib->dev;
+ u8 tmp1byte;
+ enum rt_rf_power_state eRfPowerStateToSet;
+ bool bActuallySet = false;
+ char *argv[3];
+ static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh";
+ static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL};
+
+ bActuallySet = false;
+
+ if ((priv->up_first_time == 1) || (priv->being_init_adapter))
+ return;
+
+ if (priv->bfirst_after_down) {
+ priv->bfirst_after_down = true;
+ return;
+ }
+
+ tmp1byte = read_nic_byte(dev, GPI);
+
+ eRfPowerStateToSet = (tmp1byte&BIT1) ? eRfOn : eRfOff;
+
+ if (priv->bHwRadioOff && (eRfPowerStateToSet == eRfOn)) {
+ RT_TRACE(COMP_RF, "gpiochangeRF - HW Radio ON\n");
+ netdev_info(dev, "gpiochangeRF - HW Radio ON\n");
+ priv->bHwRadioOff = false;
+ bActuallySet = true;
+ } else if (!priv->bHwRadioOff && (eRfPowerStateToSet == eRfOff)) {
+ RT_TRACE(COMP_RF, "gpiochangeRF - HW Radio OFF\n");
+ netdev_info(dev, "gpiochangeRF - HW Radio OFF\n");
+ priv->bHwRadioOff = true;
+ bActuallySet = true;
+ }
+
+ if (bActuallySet) {
+ mdelay(1000);
+ priv->bHwRfOffAction = 1;
+ MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW, true);
+ if (priv->bHwRadioOff)
+ argv[1] = "RFOFF";
+ else
+ argv[1] = "RFON";
+
+ argv[0] = RadioPowerPath;
+ argv[2] = NULL;
+ call_usermodehelper(RadioPowerPath, argv, envp, UMH_WAIT_PROC);
+ }
+}
+
+void dm_rf_pathcheck_workitemcallback(void *data)
+{
+ struct r8192_priv *priv = container_of_dwork_rsl(data,
+ struct r8192_priv,
+ rfpath_check_wq);
+ struct net_device *dev = priv->rtllib->dev;
+ u8 rfpath = 0, i;
+
+ rfpath = read_nic_byte(dev, 0xc04);
+
+ for (i = 0; i < RF90_PATH_MAX; i++) {
+ if (rfpath & (0x01<<i))
+ priv->brfpath_rxenable[i] = true;
+ else
+ priv->brfpath_rxenable[i] = false;
+ }
+ if (!DM_RxPathSelTable.Enable)
+ return;
+
+ dm_rxpath_sel_byrssi(dev);
+}
+
+static void dm_init_rxpath_selection(struct net_device *dev)
+{
+ u8 i;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ DM_RxPathSelTable.Enable = 1;
+ DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low;
+ DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH;
+ if (priv->CustomerID == RT_CID_819x_Netcore)
+ DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;
+ else
+ DM_RxPathSelTable.cck_method = CCK_Rx_Version_1;
+ DM_RxPathSelTable.DbgMode = DM_DBG_OFF;
+ DM_RxPathSelTable.disabledRF = 0;
+ for (i = 0; i < 4; i++) {
+ DM_RxPathSelTable.rf_rssi[i] = 50;
+ DM_RxPathSelTable.cck_pwdb_sta[i] = -64;
+ DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
+ }
+}
+
+#define PWDB_IN_RANGE ((cur_cck_pwdb < tmp_cck_max_pwdb) && \
+ (cur_cck_pwdb > tmp_cck_sec_pwdb))
+
+static void dm_rxpath_sel_byrssi(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 i, max_rssi_index = 0, min_rssi_index = 0;
+ u8 sec_rssi_index = 0, rf_num = 0;
+ u8 tmp_max_rssi = 0, tmp_min_rssi = 0, tmp_sec_rssi = 0;
+ u8 cck_default_Rx = 0x2;
+ u8 cck_optional_Rx = 0x3;
+ long tmp_cck_max_pwdb = 0, tmp_cck_min_pwdb = 0, tmp_cck_sec_pwdb = 0;
+ u8 cck_rx_ver2_max_index = 0, cck_rx_ver2_min_index = 0;
+ u8 cck_rx_ver2_sec_index = 0;
+ u8 cur_rf_rssi;
+ long cur_cck_pwdb;
+ static u8 disabled_rf_cnt, cck_Rx_Path_initialized;
+ u8 update_cck_rx_path;
+
+ if (priv->rf_type != RF_2T4R)
+ return;
+
+ if (!cck_Rx_Path_initialized) {
+ DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(dev, 0xa07)&0xf);
+ cck_Rx_Path_initialized = 1;
+ }
+
+ DM_RxPathSelTable.disabledRF = 0xf;
+ DM_RxPathSelTable.disabledRF &= ~(read_nic_byte(dev, 0xc04));
+
+ if (priv->rtllib->mode == WIRELESS_MODE_B)
+ DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;
+
+ for (i = 0; i < RF90_PATH_MAX; i++) {
+ if (!DM_RxPathSelTable.DbgMode)
+ DM_RxPathSelTable.rf_rssi[i] = priv->stats.rx_rssi_percentage[i];
+
+ if (priv->brfpath_rxenable[i]) {
+ rf_num++;
+ cur_rf_rssi = DM_RxPathSelTable.rf_rssi[i];
+
+ if (rf_num == 1) {
+ max_rssi_index = min_rssi_index = sec_rssi_index = i;
+ tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi;
+ } else if (rf_num == 2) {
+ if (cur_rf_rssi >= tmp_max_rssi) {
+ tmp_max_rssi = cur_rf_rssi;
+ max_rssi_index = i;
+ } else {
+ tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi;
+ sec_rssi_index = min_rssi_index = i;
+ }
+ } else {
+ if (cur_rf_rssi > tmp_max_rssi) {
+ tmp_sec_rssi = tmp_max_rssi;
+ sec_rssi_index = max_rssi_index;
+ tmp_max_rssi = cur_rf_rssi;
+ max_rssi_index = i;
+ } else if (cur_rf_rssi == tmp_max_rssi) {
+ tmp_sec_rssi = cur_rf_rssi;
+ sec_rssi_index = i;
+ } else if ((cur_rf_rssi < tmp_max_rssi) &&
+ (cur_rf_rssi > tmp_sec_rssi)) {
+ tmp_sec_rssi = cur_rf_rssi;
+ sec_rssi_index = i;
+ } else if (cur_rf_rssi == tmp_sec_rssi) {
+ if (tmp_sec_rssi == tmp_min_rssi) {
+ tmp_sec_rssi = cur_rf_rssi;
+ sec_rssi_index = i;
+ }
+ } else if ((cur_rf_rssi < tmp_sec_rssi) &&
+ (cur_rf_rssi > tmp_min_rssi)) {
+ ;
+ } else if (cur_rf_rssi == tmp_min_rssi) {
+ if (tmp_sec_rssi == tmp_min_rssi) {
+ tmp_min_rssi = cur_rf_rssi;
+ min_rssi_index = i;
+ }
+ } else if (cur_rf_rssi < tmp_min_rssi) {
+ tmp_min_rssi = cur_rf_rssi;
+ min_rssi_index = i;
+ }
+ }
+ }
+ }
+
+ rf_num = 0;
+ if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) {
+ for (i = 0; i < RF90_PATH_MAX; i++) {
+ if (priv->brfpath_rxenable[i]) {
+ rf_num++;
+ cur_cck_pwdb =
+ DM_RxPathSelTable.cck_pwdb_sta[i];
+
+ if (rf_num == 1) {
+ cck_rx_ver2_max_index = i;
+ cck_rx_ver2_min_index = i;
+ cck_rx_ver2_sec_index = i;
+ tmp_cck_max_pwdb = cur_cck_pwdb;
+ tmp_cck_min_pwdb = cur_cck_pwdb;
+ tmp_cck_sec_pwdb = cur_cck_pwdb;
+ } else if (rf_num == 2) {
+ if (cur_cck_pwdb >= tmp_cck_max_pwdb) {
+ tmp_cck_max_pwdb = cur_cck_pwdb;
+ cck_rx_ver2_max_index = i;
+ } else {
+ tmp_cck_sec_pwdb = cur_cck_pwdb;
+ tmp_cck_min_pwdb = cur_cck_pwdb;
+ cck_rx_ver2_sec_index = i;
+ cck_rx_ver2_min_index = i;
+ }
+ } else {
+ if (cur_cck_pwdb > tmp_cck_max_pwdb) {
+ tmp_cck_sec_pwdb =
+ tmp_cck_max_pwdb;
+ cck_rx_ver2_sec_index =
+ cck_rx_ver2_max_index;
+ tmp_cck_max_pwdb = cur_cck_pwdb;
+ cck_rx_ver2_max_index = i;
+ } else if (cur_cck_pwdb ==
+ tmp_cck_max_pwdb) {
+ tmp_cck_sec_pwdb = cur_cck_pwdb;
+ cck_rx_ver2_sec_index = i;
+ } else if (PWDB_IN_RANGE) {
+ tmp_cck_sec_pwdb = cur_cck_pwdb;
+ cck_rx_ver2_sec_index = i;
+ } else if (cur_cck_pwdb ==
+ tmp_cck_sec_pwdb) {
+ if (tmp_cck_sec_pwdb ==
+ tmp_cck_min_pwdb) {
+ tmp_cck_sec_pwdb =
+ cur_cck_pwdb;
+ cck_rx_ver2_sec_index =
+ i;
+ }
+ } else if ((cur_cck_pwdb < tmp_cck_sec_pwdb) &&
+ (cur_cck_pwdb > tmp_cck_min_pwdb)) {
+ ;
+ } else if (cur_cck_pwdb == tmp_cck_min_pwdb) {
+ if (tmp_cck_sec_pwdb == tmp_cck_min_pwdb) {
+ tmp_cck_min_pwdb = cur_cck_pwdb;
+ cck_rx_ver2_min_index = i;
+ }
+ } else if (cur_cck_pwdb < tmp_cck_min_pwdb) {
+ tmp_cck_min_pwdb = cur_cck_pwdb;
+ cck_rx_ver2_min_index = i;
+ }
+ }
+
+ }
+ }
+ }
+
+ update_cck_rx_path = 0;
+ if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) {
+ cck_default_Rx = cck_rx_ver2_max_index;
+ cck_optional_Rx = cck_rx_ver2_sec_index;
+ if (tmp_cck_max_pwdb != -64)
+ update_cck_rx_path = 1;
+ }
+
+ if (tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2) {
+ if ((tmp_max_rssi - tmp_min_rssi) >=
+ DM_RxPathSelTable.diff_TH) {
+ DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] =
+ tmp_max_rssi+5;
+ rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable,
+ 0x1<<min_rssi_index, 0x0);
+ rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable,
+ 0x1<<min_rssi_index, 0x0);
+ disabled_rf_cnt++;
+ }
+ if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_1) {
+ cck_default_Rx = max_rssi_index;
+ cck_optional_Rx = sec_rssi_index;
+ if (tmp_max_rssi)
+ update_cck_rx_path = 1;
+ }
+ }
+
+ if (update_cck_rx_path) {
+ DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2) |
+ (cck_optional_Rx);
+ rtl8192_setBBreg(dev, rCCK0_AFESetting, 0x0f000000,
+ DM_RxPathSelTable.cck_Rx_path);
+ }
+
+ if (DM_RxPathSelTable.disabledRF) {
+ for (i = 0; i < 4; i++) {
+ if ((DM_RxPathSelTable.disabledRF>>i) & 0x1) {
+ if (tmp_max_rssi >=
+ DM_RxPathSelTable.rf_enable_rssi_th[i]) {
+ rtl8192_setBBreg(dev,
+ rOFDM0_TRxPathEnable, 0x1 << i,
+ 0x1);
+ rtl8192_setBBreg(dev,
+ rOFDM1_TRxPathEnable,
+ 0x1 << i, 0x1);
+ DM_RxPathSelTable.rf_enable_rssi_th[i]
+ = 100;
+ disabled_rf_cnt--;
+ }
+ }
+ }
+ }
+}
+
+static void dm_check_rx_path_selection(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ queue_delayed_work_rsl(priv->priv_wq, &priv->rfpath_check_wq, 0);
+}
+
+
+static void dm_init_fsync(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->rtllib->fsync_time_interval = 500;
+ priv->rtllib->fsync_rate_bitmap = 0x0f000800;
+ priv->rtllib->fsync_rssi_threshold = 30;
+ priv->rtllib->bfsync_enable = false;
+ priv->rtllib->fsync_multiple_timeinterval = 3;
+ priv->rtllib->fsync_firstdiff_ratethreshold = 100;
+ priv->rtllib->fsync_seconddiff_ratethreshold = 200;
+ priv->rtllib->fsync_state = Default_Fsync;
+ priv->framesyncMonitor = 1;
+
+ init_timer(&priv->fsync_timer);
+ setup_timer(&priv->fsync_timer, dm_fsync_timer_callback,
+ (unsigned long) dev);
+}
+
+
+static void dm_deInit_fsync(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ del_timer_sync(&priv->fsync_timer);
+}
+
+void dm_fsync_timer_callback(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
+ u32 rate_index, rate_count = 0, rate_count_diff = 0;
+ bool bSwitchFromCountDiff = false;
+ bool bDoubleTimeInterval = false;
+
+ if (priv->rtllib->state == RTLLIB_LINKED &&
+ priv->rtllib->bfsync_enable &&
+ (priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) {
+ u32 rate_bitmap;
+
+ for (rate_index = 0; rate_index <= 27; rate_index++) {
+ rate_bitmap = 1 << rate_index;
+ if (priv->rtllib->fsync_rate_bitmap & rate_bitmap)
+ rate_count +=
+ priv->stats.received_rate_histogram[1]
+ [rate_index];
+ }
+
+ if (rate_count < priv->rate_record)
+ rate_count_diff = 0xffffffff - rate_count +
+ priv->rate_record;
+ else
+ rate_count_diff = rate_count - priv->rate_record;
+ if (rate_count_diff < priv->rateCountDiffRecord) {
+
+ u32 DiffNum = priv->rateCountDiffRecord -
+ rate_count_diff;
+ if (DiffNum >=
+ priv->rtllib->fsync_seconddiff_ratethreshold)
+ priv->ContinueDiffCount++;
+ else
+ priv->ContinueDiffCount = 0;
+
+ if (priv->ContinueDiffCount >= 2) {
+ bSwitchFromCountDiff = true;
+ priv->ContinueDiffCount = 0;
+ }
+ } else {
+ priv->ContinueDiffCount = 0;
+ }
+
+ if (rate_count_diff <=
+ priv->rtllib->fsync_firstdiff_ratethreshold) {
+ bSwitchFromCountDiff = true;
+ priv->ContinueDiffCount = 0;
+ }
+ priv->rate_record = rate_count;
+ priv->rateCountDiffRecord = rate_count_diff;
+ RT_TRACE(COMP_HALDM,
+ "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n",
+ priv->rate_record, rate_count, rate_count_diff,
+ priv->bswitch_fsync);
+ if (priv->undecorated_smoothed_pwdb >
+ priv->rtllib->fsync_rssi_threshold &&
+ bSwitchFromCountDiff) {
+ bDoubleTimeInterval = true;
+ priv->bswitch_fsync = !priv->bswitch_fsync;
+ if (priv->bswitch_fsync) {
+ write_nic_byte(dev, 0xC36, 0x1c);
+ write_nic_byte(dev, 0xC3e, 0x90);
+ } else {
+ write_nic_byte(dev, 0xC36, 0x5c);
+ write_nic_byte(dev, 0xC3e, 0x96);
+ }
+ } else if (priv->undecorated_smoothed_pwdb <=
+ priv->rtllib->fsync_rssi_threshold) {
+ if (priv->bswitch_fsync) {
+ priv->bswitch_fsync = false;
+ write_nic_byte(dev, 0xC36, 0x5c);
+ write_nic_byte(dev, 0xC3e, 0x96);
+ }
+ }
+ if (bDoubleTimeInterval) {
+ if (timer_pending(&priv->fsync_timer))
+ del_timer_sync(&priv->fsync_timer);
+ priv->fsync_timer.expires = jiffies +
+ msecs_to_jiffies(priv->rtllib->fsync_time_interval *
+ priv->rtllib->fsync_multiple_timeinterval);
+ add_timer(&priv->fsync_timer);
+ } else {
+ if (timer_pending(&priv->fsync_timer))
+ del_timer_sync(&priv->fsync_timer);
+ priv->fsync_timer.expires = jiffies +
+ msecs_to_jiffies(priv->rtllib->fsync_time_interval);
+ add_timer(&priv->fsync_timer);
+ }
+ } else {
+ if (priv->bswitch_fsync) {
+ priv->bswitch_fsync = false;
+ write_nic_byte(dev, 0xC36, 0x5c);
+ write_nic_byte(dev, 0xC3e, 0x96);
+ }
+ priv->ContinueDiffCount = 0;
+ write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+ }
+ RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount);
+ RT_TRACE(COMP_HALDM,
+ "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n",
+ priv->rate_record, rate_count, rate_count_diff,
+ priv->bswitch_fsync);
+}
+
+static void dm_StartHWFsync(struct net_device *dev)
+{
+ u8 rf_timing = 0x77;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ RT_TRACE(COMP_HALDM, "%s\n", __func__);
+ write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cf);
+ priv->rtllib->SetHwRegHandler(dev, HW_VAR_RF_TIMING,
+ (u8 *)(&rf_timing));
+ write_nic_byte(dev, 0xc3b, 0x41);
+}
+
+static void dm_EndHWFsync(struct net_device *dev)
+{
+ u8 rf_timing = 0xaa;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ RT_TRACE(COMP_HALDM, "%s\n", __func__);
+ write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+ priv->rtllib->SetHwRegHandler(dev, HW_VAR_RF_TIMING, (u8 *)
+ (&rf_timing));
+ write_nic_byte(dev, 0xc3b, 0x49);
+}
+
+static void dm_EndSWFsync(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ RT_TRACE(COMP_HALDM, "%s\n", __func__);
+ del_timer_sync(&(priv->fsync_timer));
+
+ if (priv->bswitch_fsync) {
+ priv->bswitch_fsync = false;
+
+ write_nic_byte(dev, 0xC36, 0x5c);
+
+ write_nic_byte(dev, 0xC3e, 0x96);
+ }
+
+ priv->ContinueDiffCount = 0;
+ write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+}
+
+static void dm_StartSWFsync(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 rateIndex;
+ u32 rateBitmap;
+
+ RT_TRACE(COMP_HALDM, "%s\n", __func__);
+ priv->rate_record = 0;
+ priv->ContinueDiffCount = 0;
+ priv->rateCountDiffRecord = 0;
+ priv->bswitch_fsync = false;
+
+ if (priv->rtllib->mode == WIRELESS_MODE_N_24G) {
+ priv->rtllib->fsync_firstdiff_ratethreshold = 600;
+ priv->rtllib->fsync_seconddiff_ratethreshold = 0xffff;
+ } else {
+ priv->rtllib->fsync_firstdiff_ratethreshold = 200;
+ priv->rtllib->fsync_seconddiff_ratethreshold = 200;
+ }
+ for (rateIndex = 0; rateIndex <= 27; rateIndex++) {
+ rateBitmap = 1 << rateIndex;
+ if (priv->rtllib->fsync_rate_bitmap & rateBitmap)
+ priv->rate_record +=
+ priv->stats.received_rate_histogram[1]
+ [rateIndex];
+ }
+ if (timer_pending(&priv->fsync_timer))
+ del_timer_sync(&priv->fsync_timer);
+ priv->fsync_timer.expires = jiffies +
+ msecs_to_jiffies(priv->rtllib->fsync_time_interval);
+ add_timer(&priv->fsync_timer);
+
+ write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd);
+
+}
+
+void dm_check_fsync(struct net_device *dev)
+{
+#define RegC38_Default 0
+#define RegC38_NonFsync_Other_AP 1
+#define RegC38_Fsync_AP_BCM 2
+ struct r8192_priv *priv = rtllib_priv(dev);
+ static u8 reg_c38_State = RegC38_Default;
+ static u32 reset_cnt;
+
+ RT_TRACE(COMP_HALDM,
+ "RSSI %d TimeInterval %d MultipleTimeInterval %d\n",
+ priv->rtllib->fsync_rssi_threshold,
+ priv->rtllib->fsync_time_interval,
+ priv->rtllib->fsync_multiple_timeinterval);
+ RT_TRACE(COMP_HALDM,
+ "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n",
+ priv->rtllib->fsync_rate_bitmap,
+ priv->rtllib->fsync_firstdiff_ratethreshold,
+ priv->rtllib->fsync_seconddiff_ratethreshold);
+
+ if (priv->rtllib->state == RTLLIB_LINKED &&
+ priv->rtllib->pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) {
+ if (priv->rtllib->bfsync_enable == 0) {
+ switch (priv->rtllib->fsync_state) {
+ case Default_Fsync:
+ dm_StartHWFsync(dev);
+ priv->rtllib->fsync_state = HW_Fsync;
+ break;
+ case SW_Fsync:
+ dm_EndSWFsync(dev);
+ dm_StartHWFsync(dev);
+ priv->rtllib->fsync_state = HW_Fsync;
+ break;
+ case HW_Fsync:
+ default:
+ break;
+ }
+ } else {
+ switch (priv->rtllib->fsync_state) {
+ case Default_Fsync:
+ dm_StartSWFsync(dev);
+ priv->rtllib->fsync_state = SW_Fsync;
+ break;
+ case HW_Fsync:
+ dm_EndHWFsync(dev);
+ dm_StartSWFsync(dev);
+ priv->rtllib->fsync_state = SW_Fsync;
+ break;
+ case SW_Fsync:
+ default:
+ break;
+
+ }
+ }
+ if (priv->framesyncMonitor) {
+ if (reg_c38_State != RegC38_Fsync_AP_BCM) {
+ write_nic_byte(dev, rOFDM0_RxDetector3, 0x95);
+
+ reg_c38_State = RegC38_Fsync_AP_BCM;
+ }
+ }
+ } else {
+ switch (priv->rtllib->fsync_state) {
+ case HW_Fsync:
+ dm_EndHWFsync(dev);
+ priv->rtllib->fsync_state = Default_Fsync;
+ break;
+ case SW_Fsync:
+ dm_EndSWFsync(dev);
+ priv->rtllib->fsync_state = Default_Fsync;
+ break;
+ case Default_Fsync:
+ default:
+ break;
+ }
+
+ if (priv->framesyncMonitor) {
+ if (priv->rtllib->state == RTLLIB_LINKED) {
+ if (priv->undecorated_smoothed_pwdb <=
+ RegC38_TH) {
+ if (reg_c38_State !=
+ RegC38_NonFsync_Other_AP) {
+ write_nic_byte(dev,
+ rOFDM0_RxDetector3,
+ 0x90);
+
+ reg_c38_State =
+ RegC38_NonFsync_Other_AP;
+ }
+ } else if (priv->undecorated_smoothed_pwdb >=
+ (RegC38_TH+5)) {
+ if (reg_c38_State) {
+ write_nic_byte(dev,
+ rOFDM0_RxDetector3,
+ priv->framesync);
+ reg_c38_State = RegC38_Default;
+ }
+ }
+ } else {
+ if (reg_c38_State) {
+ write_nic_byte(dev, rOFDM0_RxDetector3,
+ priv->framesync);
+ reg_c38_State = RegC38_Default;
+ }
+ }
+ }
+ }
+ if (priv->framesyncMonitor) {
+ if (priv->reset_count != reset_cnt) {
+ write_nic_byte(dev, rOFDM0_RxDetector3,
+ priv->framesync);
+ reg_c38_State = RegC38_Default;
+ reset_cnt = priv->reset_count;
+ }
+ } else {
+ if (reg_c38_State) {
+ write_nic_byte(dev, rOFDM0_RxDetector3,
+ priv->framesync);
+ reg_c38_State = RegC38_Default;
+ }
+ }
+}
+
+void dm_shadow_init(struct net_device *dev)
+{
+ u8 page;
+ u16 offset;
+
+ for (page = 0; page < 5; page++)
+ for (offset = 0; offset < 256; offset++)
+ dm_shadow[page][offset] = read_nic_byte(dev,
+ offset+page * 256);
+
+ for (page = 8; page < 11; page++)
+ for (offset = 0; offset < 256; offset++)
+ dm_shadow[page][offset] = read_nic_byte(dev,
+ offset+page * 256);
+
+ for (page = 12; page < 15; page++)
+ for (offset = 0; offset < 256; offset++)
+ dm_shadow[page][offset] = read_nic_byte(dev,
+ offset+page*256);
+
+}
+
+/*---------------------------Define function prototype------------------------*/
+static void dm_init_dynamic_txpower(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ priv->rtllib->bdynamic_txpower_enable = true;
+ priv->bLastDTPFlag_High = false;
+ priv->bLastDTPFlag_Low = false;
+ priv->bDynamicTxHighPower = false;
+ priv->bDynamicTxLowPower = false;
+}
+
+static void dm_dynamic_txpower(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ unsigned int txhipower_threshhold = 0;
+ unsigned int txlowpower_threshold = 0;
+
+ if (priv->rtllib->bdynamic_txpower_enable != true) {
+ priv->bDynamicTxHighPower = false;
+ priv->bDynamicTxLowPower = false;
+ return;
+ }
+ if ((priv->rtllib->pHTInfo->IOTPeer == HT_IOT_PEER_ATHEROS) &&
+ (priv->rtllib->mode == IEEE_G)) {
+ txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH;
+ txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW;
+ } else {
+ txhipower_threshhold = TX_POWER_NEAR_FIELD_THRESH_HIGH;
+ txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW;
+ }
+
+ RT_TRACE(COMP_TXAGC, "priv->undecorated_smoothed_pwdb = %ld\n",
+ priv->undecorated_smoothed_pwdb);
+
+ if (priv->rtllib->state == RTLLIB_LINKED) {
+ if (priv->undecorated_smoothed_pwdb >= txhipower_threshhold) {
+ priv->bDynamicTxHighPower = true;
+ priv->bDynamicTxLowPower = false;
+ } else {
+ if (priv->undecorated_smoothed_pwdb <
+ txlowpower_threshold && priv->bDynamicTxHighPower)
+ priv->bDynamicTxHighPower = false;
+ if (priv->undecorated_smoothed_pwdb < 35)
+ priv->bDynamicTxLowPower = true;
+ else if (priv->undecorated_smoothed_pwdb >= 40)
+ priv->bDynamicTxLowPower = false;
+ }
+ } else {
+ priv->bDynamicTxHighPower = false;
+ priv->bDynamicTxLowPower = false;
+ }
+
+ if ((priv->bDynamicTxHighPower != priv->bLastDTPFlag_High) ||
+ (priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low)) {
+ RT_TRACE(COMP_TXAGC, "SetTxPowerLevel8190() channel = %d\n",
+ priv->rtllib->current_network.channel);
+
+ rtl8192_phy_setTxPower(dev,
+ priv->rtllib->current_network.channel);
+ }
+ priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
+ priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower;
+
+}
+
+static void dm_check_txrateandretrycount(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ ieee->softmac_stats.CurrentShowTxate = read_nic_byte(dev,
+ Current_Tx_Rate_Reg);
+
+ ieee->softmac_stats.last_packet_rate = read_nic_byte(dev,
+ Initial_Tx_Rate_Reg);
+
+ ieee->softmac_stats.txretrycount = read_nic_dword(dev,
+ Tx_Retry_Count_Reg);
+}
+
+static void dm_send_rssi_tofw(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
+}
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h
new file mode 100644
index 000000000..3f02e11cf
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h
@@ -0,0 +1,316 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __R8192UDM_H__
+#define __R8192UDM_H__
+
+
+/*--------------------------Define Parameters-------------------------------*/
+#define OFDM_Table_Length 19
+#define CCK_Table_length 12
+
+#define DM_DIG_THRESH_HIGH 40
+#define DM_DIG_THRESH_LOW 35
+
+#define DM_FALSEALARM_THRESH_LOW 40
+#define DM_FALSEALARM_THRESH_HIGH 1000
+
+#define DM_DIG_HIGH_PWR_THRESH_HIGH 75
+#define DM_DIG_HIGH_PWR_THRESH_LOW 70
+
+#define BW_AUTO_SWITCH_HIGH_LOW 25
+#define BW_AUTO_SWITCH_LOW_HIGH 30
+
+#define DM_check_fsync_time_interval 500
+
+
+#define DM_DIG_BACKOFF 12
+#define DM_DIG_MAX 0x36
+#define DM_DIG_MIN 0x1c
+#define DM_DIG_MIN_Netcore 0x12
+
+#define DM_DIG_BACKOFF_MAX 12
+#define DM_DIG_BACKOFF_MIN -4
+
+#define RxPathSelection_SS_TH_low 30
+#define RxPathSelection_diff_TH 18
+
+#define RateAdaptiveTH_High 50
+#define RateAdaptiveTH_Low_20M 30
+#define RateAdaptiveTH_Low_40M 10
+#define VeryLowRSSI 15
+
+#define CTSToSelfTHVal 35
+
+#define WAIotTHVal 25
+
+#define E_FOR_TX_POWER_TRACK 300
+#define TX_POWER_NEAR_FIELD_THRESH_HIGH 68
+#define TX_POWER_NEAR_FIELD_THRESH_LOW 62
+#define TX_POWER_ATHEROAP_THRESH_HIGH 78
+#define TX_POWER_ATHEROAP_THRESH_LOW 72
+
+#define Current_Tx_Rate_Reg 0x1e0
+#define Initial_Tx_Rate_Reg 0x1e1
+#define Tx_Retry_Count_Reg 0x1ac
+#define RegC38_TH 20
+
+#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74
+#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67
+
+#define TxHighPwrLevel_Normal 0
+#define TxHighPwrLevel_Level1 1
+#define TxHighPwrLevel_Level2 2
+
+#define DM_Type_ByFW 0
+#define DM_Type_ByDriver 1
+
+/*--------------------------Define Parameters-------------------------------*/
+
+
+/*------------------------------Define structure----------------------------*/
+struct dig_t {
+ u8 dig_enable_flag;
+ u8 dig_algorithm;
+ u8 Dig_TwoPort_Algorithm;
+ u8 Dig_Ext_Port_Stage;
+ u8 dbg_mode;
+ u8 dig_algorithm_switch;
+
+ long rssi_low_thresh;
+ long rssi_high_thresh;
+
+ u32 FALowThresh;
+ u32 FAHighThresh;
+
+ long rssi_high_power_lowthresh;
+ long rssi_high_power_highthresh;
+
+ u8 dig_state;
+ u8 dig_highpwr_state;
+ u8 CurSTAConnectState;
+ u8 PreSTAConnectState;
+ u8 CurAPConnectState;
+ u8 PreAPConnectState;
+
+ u8 curpd_thstate;
+ u8 prepd_thstate;
+ u8 curcs_ratio_state;
+ u8 precs_ratio_state;
+
+ u32 pre_ig_value;
+ u32 cur_ig_value;
+
+ u8 Backoff_Enable_Flag;
+ u8 backoff_val;
+ char BackoffVal_range_max;
+ char BackoffVal_range_min;
+ u8 rx_gain_range_max;
+ u8 rx_gain_range_min;
+ bool initialgain_lowerbound_state;
+
+ long rssi_val;
+};
+
+enum dm_dig_sta {
+ DM_STA_DIG_OFF = 0,
+ DM_STA_DIG_ON,
+ DM_STA_DIG_MAX
+};
+
+
+enum dm_ratr_sta {
+ DM_RATR_STA_HIGH = 0,
+ DM_RATR_STA_MIDDLE = 1,
+ DM_RATR_STA_LOW = 2,
+ DM_RATR_STA_MAX
+};
+
+enum dm_dig_op_sta {
+ DIG_TYPE_THRESH_HIGH = 0,
+ DIG_TYPE_THRESH_LOW = 1,
+ DIG_TYPE_THRESH_HIGHPWR_HIGH = 2,
+ DIG_TYPE_THRESH_HIGHPWR_LOW = 3,
+ DIG_TYPE_DBG_MODE = 4,
+ DIG_TYPE_RSSI = 5,
+ DIG_TYPE_ALGORITHM = 6,
+ DIG_TYPE_BACKOFF = 7,
+ DIG_TYPE_PWDB_FACTOR = 8,
+ DIG_TYPE_RX_GAIN_MIN = 9,
+ DIG_TYPE_RX_GAIN_MAX = 10,
+ DIG_TYPE_ENABLE = 20,
+ DIG_TYPE_DISABLE = 30,
+ DIG_OP_TYPE_MAX
+};
+
+enum dm_dig_alg {
+ DIG_ALGO_BY_FALSE_ALARM = 0,
+ DIG_ALGO_BY_RSSI = 1,
+ DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM = 2,
+ DIG_ALGO_BY_TOW_PORT = 3,
+ DIG_ALGO_MAX
+};
+
+enum dm_dig_two_port_alg {
+ DIG_TWO_PORT_ALGO_RSSI = 0,
+ DIG_TWO_PORT_ALGO_FALSE_ALARM = 1,
+};
+
+
+enum dm_dig_ext_port_alg {
+ DIG_EXT_PORT_STAGE_0 = 0,
+ DIG_EXT_PORT_STAGE_1 = 1,
+ DIG_EXT_PORT_STAGE_2 = 2,
+ DIG_EXT_PORT_STAGE_3 = 3,
+ DIG_EXT_PORT_STAGE_MAX = 4,
+};
+
+enum dm_dig_dbg {
+ DIG_DBG_OFF = 0,
+ DIG_DBG_ON = 1,
+ DIG_DBG_MAX
+};
+
+enum dm_dig_connect {
+ DIG_STA_DISCONNECT = 0,
+ DIG_STA_CONNECT = 1,
+ DIG_STA_BEFORE_CONNECT = 2,
+ DIG_AP_DISCONNECT = 3,
+ DIG_AP_CONNECT = 4,
+ DIG_AP_ADD_STATION = 5,
+ DIG_CONNECT_MAX
+};
+
+enum dm_dig_pd_th {
+ DIG_PD_AT_LOW_POWER = 0,
+ DIG_PD_AT_NORMAL_POWER = 1,
+ DIG_PD_AT_HIGH_POWER = 2,
+ DIG_PD_MAX
+};
+
+enum dm_dig_cs_ratio {
+ DIG_CS_RATIO_LOWER = 0,
+ DIG_CS_RATIO_HIGHER = 1,
+ DIG_CS_MAX
+};
+
+struct drx_path_sel {
+ u8 Enable;
+ u8 DbgMode;
+ u8 cck_method;
+ u8 cck_Rx_path;
+
+ u8 SS_TH_low;
+ u8 diff_TH;
+ u8 disabledRF;
+ u8 reserved;
+
+ u8 rf_rssi[4];
+ u8 rf_enable_rssi_th[4];
+ long cck_pwdb_sta[4];
+};
+
+enum dm_cck_rx_path_method {
+ CCK_Rx_Version_1 = 0,
+ CCK_Rx_Version_2 = 1,
+ CCK_Rx_Version_MAX
+};
+
+
+enum dm_dbg {
+ DM_DBG_OFF = 0,
+ DM_DBG_ON = 1,
+ DM_DBG_MAX
+};
+
+struct dcmd_txcmd {
+ u32 Op;
+ u32 Length;
+ u32 Value;
+};
+/*------------------------------Define structure----------------------------*/
+
+
+/*------------------------Export global variable----------------------------*/
+extern struct dig_t dm_digtable;
+extern u8 dm_shadow[16][256];
+extern struct drx_path_sel DM_RxPathSelTable;
+
+extern u8 test_flag;
+/*------------------------Export global variable----------------------------*/
+
+
+/*--------------------------Exported Function prototype---------------------*/
+/*--------------------------Exported Function prototype---------------------*/
+extern void init_hal_dm(struct net_device *dev);
+extern void deinit_hal_dm(struct net_device *dev);
+
+extern void hal_dm_watchdog(struct net_device *dev);
+
+
+extern void init_rate_adaptive(struct net_device *dev);
+extern void dm_txpower_trackingcallback(void *data);
+
+extern void dm_cck_txpower_adjust(struct net_device *dev, bool binch14);
+
+extern void dm_restore_dynamic_mechanism_state(struct net_device *dev);
+extern void dm_backup_dynamic_mechanism_state(struct net_device *dev);
+extern void dm_change_dynamic_initgain_thresh(struct net_device *dev,
+ u32 dm_type,
+ u32 dm_value);
+extern void DM_ChangeFsyncSetting(struct net_device *dev,
+ s32 DM_Type,
+ s32 DM_Value);
+extern void dm_force_tx_fw_info(struct net_device *dev,
+ u32 force_type,
+ u32 force_value);
+extern void dm_init_edca_turbo(struct net_device *dev);
+extern void dm_rf_operation_test_callback(unsigned long data);
+extern void dm_rf_pathcheck_workitemcallback(void *data);
+extern void dm_fsync_timer_callback(unsigned long data);
+extern void dm_check_fsync(struct net_device *dev);
+extern void dm_shadow_init(struct net_device *dev);
+extern void dm_initialize_txpower_tracking(struct net_device *dev);
+extern void dm_CheckRfCtrlGPIO(void *data);
+extern void dm_InitRateAdaptiveMask(struct net_device *dev);
+extern void init_hal_dm(struct net_device *dev);
+extern void deinit_hal_dm(struct net_device *dev);
+extern void hal_dm_watchdog(struct net_device *dev);
+extern void init_rate_adaptive(struct net_device *dev);
+extern void dm_txpower_trackingcallback(void *data);
+extern void dm_restore_dynamic_mechanism_state(struct net_device *dev);
+extern void dm_backup_dynamic_mechanism_state(struct net_device *dev);
+extern void dm_change_dynamic_initgain_thresh(struct net_device *dev,
+ u32 dm_type,
+ u32 dm_value);
+extern void DM_ChangeFsyncSetting(struct net_device *dev,
+ s32 DM_Type,
+ s32 DM_Value);
+extern void dm_force_tx_fw_info(struct net_device *dev,
+ u32 force_type,
+ u32 force_value);
+extern void dm_init_edca_turbo(struct net_device *dev);
+extern void dm_rf_operation_test_callback(unsigned long data);
+extern void dm_rf_pathcheck_workitemcallback(void *data);
+extern void dm_fsync_timer_callback(unsigned long data);
+extern void dm_check_fsync(struct net_device *dev);
+extern void dm_shadow_init(struct net_device *dev);
+extern void dm_initialize_txpower_tracking(struct net_device *dev);
+extern void dm_CheckRfCtrlGPIO(void *data);
+
+#endif /*__R8192UDM_H__ */
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c
new file mode 100644
index 000000000..a6778e085
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c
@@ -0,0 +1,139 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtl_core.h"
+#include "rtl_eeprom.h"
+
+static void eprom_cs(struct net_device *dev, short bit)
+{
+ if (bit)
+ write_nic_byte(dev, EPROM_CMD,
+ (1 << EPROM_CS_SHIFT) |
+ read_nic_byte(dev, EPROM_CMD));
+ else
+ write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)
+ & ~(1<<EPROM_CS_SHIFT));
+
+ udelay(EPROM_DELAY);
+}
+
+
+static void eprom_ck_cycle(struct net_device *dev)
+{
+ write_nic_byte(dev, EPROM_CMD,
+ (1<<EPROM_CK_SHIFT) | read_nic_byte(dev, EPROM_CMD));
+ udelay(EPROM_DELAY);
+ write_nic_byte(dev, EPROM_CMD,
+ read_nic_byte(dev, EPROM_CMD) & ~(1<<EPROM_CK_SHIFT));
+ udelay(EPROM_DELAY);
+}
+
+
+static void eprom_w(struct net_device *dev, short bit)
+{
+ if (bit)
+ write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) |
+ read_nic_byte(dev, EPROM_CMD));
+ else
+ write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)
+ & ~(1<<EPROM_W_SHIFT));
+
+ udelay(EPROM_DELAY);
+}
+
+
+static short eprom_r(struct net_device *dev)
+{
+ short bit;
+
+ bit = (read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT));
+ udelay(EPROM_DELAY);
+
+ if (bit)
+ return 1;
+ return 0;
+}
+
+static void eprom_send_bits_string(struct net_device *dev, short b[], int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ eprom_w(dev, b[i]);
+ eprom_ck_cycle(dev);
+ }
+}
+
+u32 eprom_read(struct net_device *dev, u32 addr)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ short read_cmd[] = {1, 1, 0};
+ short addr_str[8];
+ int i;
+ int addr_len;
+ u32 ret;
+
+ ret = 0;
+ write_nic_byte(dev, EPROM_CMD,
+ (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT));
+ udelay(EPROM_DELAY);
+
+ if (priv->epromtype == EEPROM_93C56) {
+ addr_str[7] = addr & 1;
+ addr_str[6] = addr & (1<<1);
+ addr_str[5] = addr & (1<<2);
+ addr_str[4] = addr & (1<<3);
+ addr_str[3] = addr & (1<<4);
+ addr_str[2] = addr & (1<<5);
+ addr_str[1] = addr & (1<<6);
+ addr_str[0] = addr & (1<<7);
+ addr_len = 8;
+ } else {
+ addr_str[5] = addr & 1;
+ addr_str[4] = addr & (1<<1);
+ addr_str[3] = addr & (1<<2);
+ addr_str[2] = addr & (1<<3);
+ addr_str[1] = addr & (1<<4);
+ addr_str[0] = addr & (1<<5);
+ addr_len = 6;
+ }
+ eprom_cs(dev, 1);
+ eprom_ck_cycle(dev);
+ eprom_send_bits_string(dev, read_cmd, 3);
+ eprom_send_bits_string(dev, addr_str, addr_len);
+
+ eprom_w(dev, 0);
+
+ for (i = 0; i < 16; i++) {
+ eprom_ck_cycle(dev);
+ ret |= (eprom_r(dev)<<(15-i));
+ }
+
+ eprom_cs(dev, 0);
+ eprom_ck_cycle(dev);
+
+ write_nic_byte(dev, EPROM_CMD,
+ (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
+ return ret;
+}
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h
new file mode 100644
index 000000000..adea2b4c7
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h
@@ -0,0 +1,29 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+
+#define EPROM_DELAY 10
+
+u32 eprom_read(struct net_device *dev, u32 addr);
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c
new file mode 100644
index 000000000..529ea54d1
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ethtool.c
@@ -0,0 +1,53 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ *****************************************************************************
+ */
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+
+#include "rtl_core.h"
+
+static void rtl819x_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+ strlcpy(info->bus_info, pci_name(priv->pdev), sizeof(info->bus_info));
+}
+
+static u32 rtl819x_ethtool_get_link(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ return ((priv->rtllib->state == RTLLIB_LINKED) ||
+ (priv->rtllib->state == RTLLIB_LINKED_SCANNING));
+}
+
+const struct ethtool_ops rtl819x_ethtool_ops = {
+ .get_drvinfo = rtl819x_ethtool_get_drvinfo,
+ .get_link = rtl819x_ethtool_get_link,
+};
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c
new file mode 100644
index 000000000..51f53be2d
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c
@@ -0,0 +1,100 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ *****************************************************************************/
+#include "rtl_pci.h"
+#include "rtl_core.h"
+
+static void rtl8192_parse_pci_configuration(struct pci_dev *pdev,
+ struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ u8 tmp;
+ u16 LinkCtrlReg;
+
+ pcie_capability_read_word(priv->pdev, PCI_EXP_LNKCTL, &LinkCtrlReg);
+ priv->NdisAdapter.LinkCtrlReg = (u8)LinkCtrlReg;
+
+ RT_TRACE(COMP_INIT, "Link Control Register =%x\n",
+ priv->NdisAdapter.LinkCtrlReg);
+
+ pci_read_config_byte(pdev, 0x98, &tmp);
+ tmp |= BIT4;
+ pci_write_config_byte(pdev, 0x98, tmp);
+
+ tmp = 0x17;
+ pci_write_config_byte(pdev, 0x70f, tmp);
+}
+
+bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ u16 VenderID;
+ u16 DeviceID;
+ u8 RevisionID;
+ u16 IrqLine;
+
+ VenderID = pdev->vendor;
+ DeviceID = pdev->device;
+ RevisionID = pdev->revision;
+ pci_read_config_word(pdev, 0x3C, &IrqLine);
+
+ priv->card_8192 = priv->ops->nic_type;
+
+ if (DeviceID == 0x8172) {
+ switch (RevisionID) {
+ case HAL_HW_PCI_REVISION_ID_8192PCIE:
+ dev_info(&pdev->dev,
+ "Adapter(8192 PCI-E) is found - DeviceID=%x\n",
+ DeviceID);
+ priv->card_8192 = NIC_8192E;
+ break;
+ case HAL_HW_PCI_REVISION_ID_8192SE:
+ dev_info(&pdev->dev,
+ "Adapter(8192SE) is found - DeviceID=%x\n",
+ DeviceID);
+ priv->card_8192 = NIC_8192SE;
+ break;
+ default:
+ dev_info(&pdev->dev,
+ "UNKNOWN nic type(%4x:%4x)\n",
+ pdev->vendor, pdev->device);
+ priv->card_8192 = NIC_UNKNOWN;
+ return false;
+ }
+ }
+
+ if (priv->ops->nic_type != priv->card_8192) {
+ dev_info(&pdev->dev,
+ "Detect info(%x) and hardware info(%x) not match!\n",
+ priv->ops->nic_type, priv->card_8192);
+ dev_info(&pdev->dev,
+ "Please select proper driver before install!!!!\n");
+ return false;
+ }
+
+ rtl8192_parse_pci_configuration(pdev, dev);
+
+ return true;
+}
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
new file mode 100644
index 000000000..4b94653c5
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
@@ -0,0 +1,51 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ ******************************************************************************/
+#ifndef _RTL_PCI_H
+#define _RTL_PCI_H
+
+#include <linux/types.h>
+#include <linux/pci.h>
+
+struct mp_adapter {
+ u8 LinkCtrlReg;
+
+ u8 BusNumber;
+ u8 DevNumber;
+ u8 FuncNumber;
+
+ u8 PciBridgeBusNum;
+ u8 PciBridgeDevNum;
+ u8 PciBridgeFuncNum;
+ u8 PciBridgeVendor;
+ u16 PciBridgeVendorId;
+ u16 PciBridgeDeviceId;
+ u8 PciBridgePCIeHdrOffset;
+ u8 PciBridgeLinkCtrlReg;
+};
+
+struct net_device;
+bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev);
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
new file mode 100644
index 000000000..ca6ecfc82
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
@@ -0,0 +1,119 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#include "rtl_core.h"
+#include "r8192E_hw.h"
+#include "r8190P_rtl8256.h"
+#include "rtl_pm.h"
+
+
+int rtl8192E_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u32 ulRegRead;
+
+ netdev_info(dev, "============> r8192E suspend call.\n");
+ del_timer_sync(&priv->gpio_polling_timer);
+ cancel_delayed_work(&priv->gpio_change_rf_wq);
+ priv->polling_timer_on = 0;
+
+ if (!netif_running(dev)) {
+ netdev_info(dev,
+ "RTL819XE:UI is open out of suspend function\n");
+ goto out_pci_suspend;
+ }
+
+ if (dev->netdev_ops->ndo_stop)
+ dev->netdev_ops->ndo_stop(dev);
+ netif_device_detach(dev);
+
+ if (!priv->rtllib->bSupportRemoteWakeUp) {
+ MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT, true);
+ ulRegRead = read_nic_dword(dev, CPU_GEN);
+ ulRegRead |= CPU_GEN_SYSTEM_RESET;
+ write_nic_dword(dev, CPU_GEN, ulRegRead);
+ } else {
+ write_nic_dword(dev, WFCRC0, 0xffffffff);
+ write_nic_dword(dev, WFCRC1, 0xffffffff);
+ write_nic_dword(dev, WFCRC2, 0xffffffff);
+ write_nic_byte(dev, PMR, 0x5);
+ write_nic_byte(dev, MacBlkCtrl, 0xa);
+ }
+out_pci_suspend:
+ netdev_info(dev, "r8192E support WOL call??????????????????????\n");
+ if (priv->rtllib->bSupportRemoteWakeUp)
+ RT_TRACE(COMP_POWER,
+ "r8192E support WOL call!!!!!!!!!!!!!!!!!!.\n");
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state),
+ priv->rtllib->bSupportRemoteWakeUp ? 1 : 0);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ mdelay(20);
+
+ return 0;
+}
+
+int rtl8192E_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int err;
+ u32 val;
+
+ netdev_info(dev, "================>r8192E resume call.\n");
+
+ pci_set_power_state(pdev, PCI_D0);
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ netdev_err(dev, "pci_enable_device failed on resume\n");
+ return err;
+ }
+ pci_restore_state(pdev);
+
+ pci_read_config_dword(pdev, 0x40, &val);
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+ pci_enable_wake(pdev, PCI_D0, 0);
+
+ if (priv->polling_timer_on == 0)
+ check_rfctrl_gpio_timer((unsigned long)dev);
+
+ if (!netif_running(dev)) {
+ netdev_info(dev,
+ "RTL819XE:UI is open out of resume function\n");
+ goto out;
+ }
+
+ netif_device_attach(dev);
+ if (dev->netdev_ops->ndo_open)
+ dev->netdev_ops->ndo_open(dev);
+
+ if (!priv->rtllib->bSupportRemoteWakeUp)
+ MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_INIT, true);
+
+out:
+ RT_TRACE(COMP_POWER, "<================r8192E resume call.\n");
+ return 0;
+}
+
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h
new file mode 100644
index 000000000..7bfe44817
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h
@@ -0,0 +1,29 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifndef R8192E_PM_H
+#define R8192E_PM_H
+
+#include <linux/types.h>
+#include <linux/pci.h>
+
+int rtl8192E_suspend(struct pci_dev *dev, pm_message_t state);
+int rtl8192E_resume(struct pci_dev *dev);
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
new file mode 100644
index 000000000..0bbffec0c
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
@@ -0,0 +1,316 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ *****************************************************************************/
+#include "rtl_ps.h"
+#include "rtl_core.h"
+#include "r8192E_phy.h"
+#include "r8192E_phyreg.h"
+#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
+#include "r8192E_cmdpkt.h"
+
+static void rtl8192_hw_sleep_down(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&priv->rf_ps_lock, flags);
+ if (priv->RFChangeInProgress) {
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
+ RT_TRACE(COMP_DBG,
+ "rtl8192_hw_sleep_down(): RF Change in progress!\n");
+ return;
+ }
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
+ RT_TRACE(COMP_DBG, "%s()============>come to sleep down\n", __func__);
+
+ MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS, false);
+}
+
+void rtl8192_hw_sleep_wq(void *data)
+{
+ struct rtllib_device *ieee = container_of_dwork_rsl(data,
+ struct rtllib_device, hw_sleep_wq);
+ struct net_device *dev = ieee->dev;
+
+ rtl8192_hw_sleep_down(dev);
+}
+
+void rtl8192_hw_wakeup(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&priv->rf_ps_lock, flags);
+ if (priv->RFChangeInProgress) {
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
+ RT_TRACE(COMP_DBG,
+ "rtl8192_hw_wakeup(): RF Change in progress!\n");
+ queue_delayed_work_rsl(priv->rtllib->wq,
+ &priv->rtllib->hw_wakeup_wq,
+ msecs_to_jiffies(10));
+ return;
+ }
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
+ RT_TRACE(COMP_PS, "%s()============>come to wake up\n", __func__);
+ MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS, false);
+}
+
+void rtl8192_hw_wakeup_wq(void *data)
+{
+ struct rtllib_device *ieee = container_of_dwork_rsl(data,
+ struct rtllib_device, hw_wakeup_wq);
+ struct net_device *dev = ieee->dev;
+
+ rtl8192_hw_wakeup(dev);
+}
+
+#define MIN_SLEEP_TIME 50
+#define MAX_SLEEP_TIME 10000
+void rtl8192_hw_to_sleep(struct net_device *dev, u64 time)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ u32 tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->ps_lock, flags);
+
+ time -= msecs_to_jiffies(8 + 16 + 7);
+
+ if ((time - jiffies) <= msecs_to_jiffies(MIN_SLEEP_TIME)) {
+ spin_unlock_irqrestore(&priv->ps_lock, flags);
+ netdev_info(dev, "too short to sleep::%lld < %ld\n",
+ time - jiffies, msecs_to_jiffies(MIN_SLEEP_TIME));
+ return;
+ }
+
+ if ((time - jiffies) > msecs_to_jiffies(MAX_SLEEP_TIME)) {
+ netdev_info(dev, "========>too long to sleep:%lld > %ld\n",
+ time - jiffies, msecs_to_jiffies(MAX_SLEEP_TIME));
+ spin_unlock_irqrestore(&priv->ps_lock, flags);
+ return;
+ }
+ tmp = time - jiffies;
+ queue_delayed_work_rsl(priv->rtllib->wq,
+ &priv->rtllib->hw_wakeup_wq, tmp);
+ queue_delayed_work_rsl(priv->rtllib->wq,
+ (void *)&priv->rtllib->hw_sleep_wq, 0);
+ spin_unlock_irqrestore(&priv->ps_lock, flags);
+}
+
+static void InactivePsWorkItemCallback(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ &(priv->rtllib->PowerSaveControl);
+
+ RT_TRACE(COMP_PS, "InactivePsWorkItemCallback() --------->\n");
+ pPSC->bSwRfProcessing = true;
+
+ RT_TRACE(COMP_PS, "InactivePsWorkItemCallback(): Set RF to %s.\n",
+ pPSC->eInactivePowerState == eRfOff ? "OFF" : "ON");
+ MgntActSet_RF_State(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS,
+ false);
+
+ pPSC->bSwRfProcessing = false;
+ RT_TRACE(COMP_PS, "InactivePsWorkItemCallback() <---------\n");
+}
+
+void IPSEnter(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ &(priv->rtllib->PowerSaveControl);
+ enum rt_rf_power_state rtState;
+
+ if (pPSC->bInactivePs) {
+ rtState = priv->rtllib->eRFPowerState;
+ if (rtState == eRfOn && !pPSC->bSwRfProcessing &&
+ (priv->rtllib->state != RTLLIB_LINKED) &&
+ (priv->rtllib->iw_mode != IW_MODE_MASTER)) {
+ RT_TRACE(COMP_PS, "IPSEnter(): Turn off RF.\n");
+ pPSC->eInactivePowerState = eRfOff;
+ priv->isRFOff = true;
+ priv->bInPowerSaveMode = true;
+ InactivePsWorkItemCallback(dev);
+ }
+ }
+}
+
+void IPSLeave(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ &(priv->rtllib->PowerSaveControl);
+ enum rt_rf_power_state rtState;
+
+ if (pPSC->bInactivePs) {
+ rtState = priv->rtllib->eRFPowerState;
+ if (rtState != eRfOn && !pPSC->bSwRfProcessing &&
+ priv->rtllib->RfOffReason <= RF_CHANGE_BY_IPS) {
+ RT_TRACE(COMP_PS, "IPSLeave(): Turn on RF.\n");
+ pPSC->eInactivePowerState = eRfOn;
+ priv->bInPowerSaveMode = false;
+ InactivePsWorkItemCallback(dev);
+ }
+ }
+}
+
+void IPSLeave_wq(void *data)
+{
+ struct rtllib_device *ieee = container_of_work_rsl(data,
+ struct rtllib_device, ips_leave_wq);
+ struct net_device *dev = ieee->dev;
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ down(&priv->rtllib->ips_sem);
+ IPSLeave(dev);
+ up(&priv->rtllib->ips_sem);
+}
+
+void rtllib_ips_leave_wq(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+ enum rt_rf_power_state rtState;
+
+ rtState = priv->rtllib->eRFPowerState;
+
+ if (priv->rtllib->PowerSaveControl.bInactivePs) {
+ if (rtState == eRfOff) {
+ if (priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) {
+ RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",
+ __func__);
+ return;
+ }
+ netdev_info(dev, "=========>%s(): IPSLeave\n",
+ __func__);
+ queue_work_rsl(priv->rtllib->wq,
+ &priv->rtllib->ips_leave_wq);
+ }
+ }
+}
+
+void rtllib_ips_leave(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
+
+ down(&priv->rtllib->ips_sem);
+ IPSLeave(dev);
+ up(&priv->rtllib->ips_sem);
+}
+
+static bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev,
+ u8 rtPsMode)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->rtllib->iw_mode == IW_MODE_ADHOC)
+ return false;
+
+ RT_TRACE(COMP_LPS, "%s(): set ieee->ps = %x\n", __func__, rtPsMode);
+ if (!priv->ps_force)
+ priv->rtllib->ps = rtPsMode;
+ if (priv->rtllib->sta_sleep != LPS_IS_WAKE &&
+ rtPsMode == RTLLIB_PS_DISABLED) {
+ unsigned long flags;
+
+ rtl8192_hw_wakeup(dev);
+ priv->rtllib->sta_sleep = LPS_IS_WAKE;
+
+ spin_lock_irqsave(&(priv->rtllib->mgmt_tx_lock), flags);
+ RT_TRACE(COMP_DBG,
+ "LPS leave: notify AP we are awaked ++++++++++ SendNullFunctionData\n");
+ rtllib_sta_ps_send_null_frame(priv->rtllib, 0);
+ spin_unlock_irqrestore(&(priv->rtllib->mgmt_tx_lock), flags);
+ }
+
+ return true;
+}
+
+void LeisurePSEnter(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ &(priv->rtllib->PowerSaveControl);
+
+ RT_TRACE(COMP_PS, "LeisurePSEnter()...\n");
+ RT_TRACE(COMP_PS,
+ "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n",
+ pPSC->bLeisurePs, priv->rtllib->ps, pPSC->LpsIdleCount,
+ RT_CHECK_FOR_HANG_PERIOD);
+
+ if (!((priv->rtllib->iw_mode == IW_MODE_INFRA) &&
+ (priv->rtllib->state == RTLLIB_LINKED))
+ || (priv->rtllib->iw_mode == IW_MODE_ADHOC) ||
+ (priv->rtllib->iw_mode == IW_MODE_MASTER))
+ return;
+
+ if (pPSC->bLeisurePs) {
+ if (pPSC->LpsIdleCount >= RT_CHECK_FOR_HANG_PERIOD) {
+
+ if (priv->rtllib->ps == RTLLIB_PS_DISABLED) {
+
+ RT_TRACE(COMP_LPS,
+ "LeisurePSEnter(): Enter 802.11 power save mode...\n");
+
+ if (!pPSC->bFwCtrlLPS) {
+ if (priv->rtllib->SetFwCmdHandler)
+ priv->rtllib->SetFwCmdHandler(
+ dev, FW_CMD_LPS_ENTER);
+ }
+ MgntActSet_802_11_PowerSaveMode(dev,
+ RTLLIB_PS_MBCAST |
+ RTLLIB_PS_UNICAST);
+ }
+ } else
+ pPSC->LpsIdleCount++;
+ }
+}
+
+void LeisurePSLeave(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ &(priv->rtllib->PowerSaveControl);
+
+
+ RT_TRACE(COMP_PS, "LeisurePSLeave()...\n");
+ RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d\n",
+ pPSC->bLeisurePs, priv->rtllib->ps);
+
+ if (pPSC->bLeisurePs) {
+ if (priv->rtllib->ps != RTLLIB_PS_DISABLED) {
+ RT_TRACE(COMP_LPS,
+ "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n");
+ MgntActSet_802_11_PowerSaveMode(dev,
+ RTLLIB_PS_DISABLED);
+
+ if (!pPSC->bFwCtrlLPS) {
+ if (priv->rtllib->SetFwCmdHandler)
+ priv->rtllib->SetFwCmdHandler(dev,
+ FW_CMD_LPS_LEAVE);
+ }
+ }
+ }
+}
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h
new file mode 100644
index 000000000..962f2e5b8
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h
@@ -0,0 +1,47 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ ******************************************************************************/
+#ifndef _RTL_PS_H
+#define _RTL_PS_H
+
+#include <linux/types.h>
+
+struct net_device;
+
+#define RT_CHECK_FOR_HANG_PERIOD 2
+#define INIT_DEFAULT_CHAN 1
+
+void rtl8192_hw_wakeup(struct net_device *dev);
+void rtl8192_hw_to_sleep(struct net_device *dev, u64 time);
+void rtllib_ips_leave_wq(struct net_device *dev);
+void rtllib_ips_leave(struct net_device *dev);
+void IPSLeave_wq(void *data);
+
+void IPSEnter(struct net_device *dev);
+void IPSLeave(struct net_device *dev);
+
+void LeisurePSEnter(struct net_device *dev);
+void LeisurePSLeave(struct net_device *dev);
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
new file mode 100644
index 000000000..8d6a109e0
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
@@ -0,0 +1,1341 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#include <linux/string.h>
+#include "rtl_core.h"
+#include "rtl_wx.h"
+
+#define RATE_COUNT 12
+static u32 rtl8192_rates[] = {
+ 1000000, 2000000, 5500000, 11000000, 6000000, 9000000, 12000000,
+ 18000000, 24000000, 36000000, 48000000, 54000000
+};
+
+#ifndef ENETDOWN
+#define ENETDOWN 1
+#endif
+
+static int r8192_wx_get_freq(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ return rtllib_wx_get_freq(priv->rtllib, a, wrqu, b);
+}
+
+
+static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ return rtllib_wx_get_mode(priv->rtllib, a, wrqu, b);
+}
+
+static int r8192_wx_get_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ return rtllib_wx_get_rate(priv->rtllib, info, wrqu, extra);
+}
+
+
+
+static int r8192_wx_set_rate(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+
+ ret = rtllib_wx_set_rate(priv->rtllib, info, wrqu, extra);
+
+ up(&priv->wx_sem);
+
+ return ret;
+}
+
+
+static int r8192_wx_set_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+
+ ret = rtllib_wx_set_rts(priv->rtllib, info, wrqu, extra);
+
+ up(&priv->wx_sem);
+
+ return ret;
+}
+
+static int r8192_wx_get_rts(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ return rtllib_wx_get_rts(priv->rtllib, info, wrqu, extra);
+}
+
+static int r8192_wx_set_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->bHwRadioOff) {
+ RT_TRACE(COMP_ERR,
+ "%s():Hw is Radio Off, we can't set Power,return\n",
+ __func__);
+ return 0;
+ }
+ down(&priv->wx_sem);
+
+ ret = rtllib_wx_set_power(priv->rtllib, info, wrqu, extra);
+
+ up(&priv->wx_sem);
+
+ return ret;
+}
+
+static int r8192_wx_get_power(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ return rtllib_wx_get_power(priv->rtllib, info, wrqu, extra);
+}
+
+static int r8192_wx_set_rawtx(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int ret;
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+
+ ret = rtllib_wx_set_rawtx(priv->rtllib, info, wrqu, extra);
+
+ up(&priv->wx_sem);
+
+ return ret;
+
+}
+
+static int r8192_wx_force_reset(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ down(&priv->wx_sem);
+
+ RT_TRACE(COMP_DBG, "%s(): force reset ! extra is %d\n",
+ __func__, *extra);
+ priv->force_reset = *extra;
+ up(&priv->wx_sem);
+ return 0;
+
+}
+
+static int r8192_wx_force_mic_error(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ down(&priv->wx_sem);
+
+ RT_TRACE(COMP_DBG, "%s(): force mic error !\n", __func__);
+ ieee->force_mic_error = true;
+ up(&priv->wx_sem);
+ return 0;
+
+}
+
+#define MAX_ADHOC_PEER_NUM 64
+struct adhoc_peer_entry {
+ unsigned char MacAddr[ETH_ALEN];
+ unsigned char WirelessMode;
+ unsigned char bCurTxBW40MHz;
+};
+struct adhoc_peers_info {
+ struct adhoc_peer_entry Entry[MAX_ADHOC_PEER_NUM];
+ unsigned char num;
+};
+
+static int r8192_wx_get_adhoc_peers(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ return 0;
+}
+
+
+static int r8191se_wx_get_firm_version(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *wrqu, char *extra)
+{
+ return 0;
+}
+
+static int r8192_wx_adapter_power_status(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ (&(priv->rtllib->PowerSaveControl));
+ struct rtllib_device *ieee = priv->rtllib;
+
+ down(&priv->wx_sem);
+
+ RT_TRACE(COMP_POWER, "%s(): %s\n", __func__, (*extra == 6) ?
+ "DC power" : "AC power");
+ if (*extra || priv->force_lps) {
+ priv->ps_force = false;
+ pPSC->bLeisurePs = true;
+ } else {
+ if (priv->rtllib->state == RTLLIB_LINKED)
+ LeisurePSLeave(dev);
+
+ priv->ps_force = true;
+ pPSC->bLeisurePs = false;
+ ieee->ps = *extra;
+ }
+
+ up(&priv->wx_sem);
+
+ return 0;
+}
+
+static int r8192se_wx_set_radio(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ down(&priv->wx_sem);
+
+ netdev_info(dev, "%s(): set radio ! extra is %d\n", __func__, *extra);
+ if ((*extra != 0) && (*extra != 1)) {
+ RT_TRACE(COMP_ERR,
+ "%s(): set radio an err value,must 0(radio off) or 1(radio on)\n",
+ __func__);
+ up(&priv->wx_sem);
+ return -1;
+ }
+ priv->sw_radio_on = *extra;
+ up(&priv->wx_sem);
+ return 0;
+
+}
+
+static int r8192se_wx_set_lps_awake_interval(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ (&(priv->rtllib->PowerSaveControl));
+
+ down(&priv->wx_sem);
+
+ netdev_info(dev, "%s(): set lps awake interval ! extra is %d\n",
+ __func__, *extra);
+
+ pPSC->RegMaxLPSAwakeIntvl = *extra;
+ up(&priv->wx_sem);
+ return 0;
+}
+
+static int r8192se_wx_set_force_lps(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ down(&priv->wx_sem);
+
+ netdev_info(dev,
+ "%s(): force LPS ! extra is %d (1 is open 0 is close)\n",
+ __func__, *extra);
+ priv->force_lps = *extra;
+ up(&priv->wx_sem);
+ return 0;
+
+}
+
+static int r8192_wx_set_debugflag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u8 c = *extra;
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ netdev_info(dev, "=====>%s(), *extra:%x, debugflag:%x\n", __func__,
+ *extra, rt_global_debug_component);
+ if (c > 0)
+ rt_global_debug_component |= (1<<c);
+ else
+ rt_global_debug_component &= BIT31;
+ return 0;
+}
+
+static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = netdev_priv_rsl(dev);
+
+ enum rt_rf_power_state rtState;
+ int ret;
+
+ if (priv->bHwRadioOff)
+ return 0;
+ rtState = priv->rtllib->eRFPowerState;
+ down(&priv->wx_sem);
+ if (wrqu->mode == IW_MODE_ADHOC || wrqu->mode == IW_MODE_MONITOR ||
+ ieee->bNetPromiscuousMode) {
+ if (priv->rtllib->PowerSaveControl.bInactivePs) {
+ if (rtState == eRfOff) {
+ if (priv->rtllib->RfOffReason >
+ RF_CHANGE_BY_IPS) {
+ RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",
+ __func__);
+ up(&priv->wx_sem);
+ return -1;
+ }
+ netdev_info(dev, "=========>%s(): IPSLeave\n",
+ __func__);
+ down(&priv->rtllib->ips_sem);
+ IPSLeave(dev);
+ up(&priv->rtllib->ips_sem);
+ }
+ }
+ }
+ ret = rtllib_wx_set_mode(priv->rtllib, a, wrqu, b);
+
+ up(&priv->wx_sem);
+ return ret;
+}
+
+struct iw_range_with_scan_capa {
+ /* Informative stuff (to choose between different interface) */
+ __u32 throughput; /* To give an idea... */
+ /* In theory this value should be the maximum benchmarked
+ * TCP/IP throughput, because with most of these devices the
+ * bit rate is meaningless (overhead an co) to estimate how
+ * fast the connection will go and pick the fastest one.
+ * I suggest people to play with Netperf or any benchmark...
+ */
+
+ /* NWID (or domain id) */
+ __u32 min_nwid; /* Minimal NWID we are able to set */
+ __u32 max_nwid; /* Maximal NWID we are able to set */
+
+ /* Old Frequency (backward compat - moved lower ) */
+ __u16 old_num_channels;
+ __u8 old_num_frequency;
+
+ /* Scan capabilities */
+ __u8 scan_capa;
+};
+
+static int rtl8192_wx_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct iw_range *range = (struct iw_range *)extra;
+ struct r8192_priv *priv = rtllib_priv(dev);
+ u16 val;
+ int i;
+
+ wrqu->data.length = sizeof(*range);
+ memset(range, 0, sizeof(*range));
+
+ /* ~130 Mb/s real (802.11n) */
+ range->throughput = 130 * 1000 * 1000;
+
+ if (priv->rf_set_sens != NULL) {
+ /* signal level threshold range */
+ range->sensitivity = priv->max_sens;
+ }
+
+ range->max_qual.qual = 100;
+ range->max_qual.level = 0;
+ range->max_qual.noise = 0;
+ range->max_qual.updated = 7; /* Updated all three */
+
+ range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */
+ range->avg_qual.level = 0;
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = 7; /* Updated all three */
+
+ range->num_bitrates = min(RATE_COUNT, IW_MAX_BITRATES);
+
+ for (i = 0; i < range->num_bitrates; i++)
+ range->bitrate[i] = rtl8192_rates[i];
+
+ range->max_rts = DEFAULT_RTS_THRESHOLD;
+ range->min_frag = MIN_FRAG_THRESHOLD;
+ range->max_frag = MAX_FRAG_THRESHOLD;
+
+ range->min_pmp = 0;
+ range->max_pmp = 5000000;
+ range->min_pmt = 0;
+ range->max_pmt = 65535*1000;
+ range->pmp_flags = IW_POWER_PERIOD;
+ range->pmt_flags = IW_POWER_TIMEOUT;
+ range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
+ range->we_version_compiled = WIRELESS_EXT;
+ range->we_version_source = 18;
+
+ for (i = 0, val = 0; i < 14; i++) {
+ if ((priv->rtllib->active_channel_map)[i+1]) {
+ range->freq[val].i = i + 1;
+ range->freq[val].m = rtllib_wlan_frequencies[i] *
+ 100000;
+ range->freq[val].e = 1;
+ val++;
+ }
+
+ if (val == IW_MAX_FREQUENCIES)
+ break;
+ }
+ range->num_frequency = val;
+ range->num_channels = val;
+ range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
+ IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
+ range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE;
+
+ /* Event capability (kernel + driver) */
+
+ return 0;
+}
+
+static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+ enum rt_rf_power_state rtState;
+ int ret;
+
+ if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) {
+ if ((ieee->state >= RTLLIB_ASSOCIATING) &&
+ (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED))
+ return 0;
+ if ((priv->rtllib->state == RTLLIB_LINKED) &&
+ (priv->rtllib->CntAfterLink < 2))
+ return 0;
+ }
+
+ if (priv->bHwRadioOff) {
+ netdev_info(dev, "================>%s(): hwradio off\n",
+ __func__);
+ return 0;
+ }
+ rtState = priv->rtllib->eRFPowerState;
+ if (!priv->up)
+ return -ENETDOWN;
+ if (priv->rtllib->LinkDetectInfo.bBusyTraffic == true)
+ return -EAGAIN;
+
+ if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+ struct iw_scan_req *req = (struct iw_scan_req *)b;
+
+ if (req->essid_len) {
+ ieee->current_network.ssid_len = req->essid_len;
+ memcpy(ieee->current_network.ssid, req->essid,
+ req->essid_len);
+ }
+ }
+
+ down(&priv->wx_sem);
+
+ priv->rtllib->FirstIe_InScan = true;
+
+ if (priv->rtllib->state != RTLLIB_LINKED) {
+ if (priv->rtllib->PowerSaveControl.bInactivePs) {
+ if (rtState == eRfOff) {
+ if (priv->rtllib->RfOffReason >
+ RF_CHANGE_BY_IPS) {
+ RT_TRACE(COMP_ERR,
+ "%s(): RF is OFF.\n",
+ __func__);
+ up(&priv->wx_sem);
+ return -1;
+ }
+ RT_TRACE(COMP_PS, "=========>%s(): IPSLeave\n",
+ __func__);
+ down(&priv->rtllib->ips_sem);
+ IPSLeave(dev);
+ up(&priv->rtllib->ips_sem);
+ }
+ }
+ rtllib_stop_scan(priv->rtllib);
+ if (priv->rtllib->LedControlHandler)
+ priv->rtllib->LedControlHandler(dev,
+ LED_CTL_SITE_SURVEY);
+
+ if (priv->rtllib->eRFPowerState != eRfOff) {
+ priv->rtllib->actscanning = true;
+
+ if (ieee->ScanOperationBackupHandler)
+ ieee->ScanOperationBackupHandler(ieee->dev,
+ SCAN_OPT_BACKUP);
+
+ rtllib_start_scan_syncro(priv->rtllib, 0);
+
+ if (ieee->ScanOperationBackupHandler)
+ ieee->ScanOperationBackupHandler(ieee->dev,
+ SCAN_OPT_RESTORE);
+ }
+ ret = 0;
+ } else {
+ priv->rtllib->actscanning = true;
+ ret = rtllib_wx_set_scan(priv->rtllib, a, wrqu, b);
+ }
+
+ up(&priv->wx_sem);
+ return ret;
+}
+
+
+static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+
+ int ret;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (!priv->up)
+ return -ENETDOWN;
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+
+ down(&priv->wx_sem);
+
+ ret = rtllib_wx_get_scan(priv->rtllib, a, wrqu, b);
+
+ up(&priv->wx_sem);
+
+ return ret;
+}
+
+static int r8192_wx_set_essid(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int ret;
+
+ if (priv->bHwRadioOff) {
+ netdev_info(dev,
+ "=========>%s():hw radio off,or Rf state is eRfOff, return\n",
+ __func__);
+ return 0;
+ }
+ down(&priv->wx_sem);
+ ret = rtllib_wx_set_essid(priv->rtllib, a, wrqu, b);
+
+ up(&priv->wx_sem);
+
+ return ret;
+}
+
+static int r8192_wx_get_essid(struct net_device *dev,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ int ret;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ down(&priv->wx_sem);
+
+ ret = rtllib_wx_get_essid(priv->rtllib, a, wrqu, b);
+
+ up(&priv->wx_sem);
+
+ return ret;
+}
+
+static int r8192_wx_set_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (wrqu->data.length > IW_ESSID_MAX_SIZE)
+ return -E2BIG;
+ down(&priv->wx_sem);
+ wrqu->data.length = min_t(size_t, wrqu->data.length, sizeof(priv->nick));
+ memset(priv->nick, 0, sizeof(priv->nick));
+ memcpy(priv->nick, extra, wrqu->data.length);
+ up(&priv->wx_sem);
+ return 0;
+
+}
+
+static int r8192_wx_get_nick(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ down(&priv->wx_sem);
+ wrqu->data.length = strlen(priv->nick);
+ memcpy(extra, priv->nick, wrqu->data.length);
+ wrqu->data.flags = 1; /* active */
+ up(&priv->wx_sem);
+ return 0;
+}
+
+static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ int ret;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+
+ ret = rtllib_wx_set_freq(priv->rtllib, a, wrqu, b);
+
+ up(&priv->wx_sem);
+ return ret;
+}
+
+static int r8192_wx_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ return rtllib_wx_get_name(priv->rtllib, info, wrqu, extra);
+}
+
+
+static int r8192_wx_set_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ if (wrqu->frag.disabled)
+ priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD;
+ else {
+ if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
+ wrqu->frag.value > MAX_FRAG_THRESHOLD)
+ return -EINVAL;
+
+ priv->rtllib->fts = wrqu->frag.value & ~0x1;
+ }
+
+ return 0;
+}
+
+
+static int r8192_wx_get_frag(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ wrqu->frag.value = priv->rtllib->fts;
+ wrqu->frag.fixed = 0; /* no auto select */
+ wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
+
+ return 0;
+}
+
+
+static int r8192_wx_set_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *awrq,
+ char *extra)
+{
+ int ret;
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+
+ ret = rtllib_wx_set_wap(priv->rtllib, info, awrq, extra);
+
+ up(&priv->wx_sem);
+
+ return ret;
+
+}
+
+
+static int r8192_wx_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ return rtllib_wx_get_wap(priv->rtllib, info, wrqu, extra);
+}
+
+
+static int r8192_wx_get_enc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ return rtllib_wx_get_encode(priv->rtllib, info, wrqu, key);
+}
+
+static int r8192_wx_set_enc(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int ret;
+
+ struct rtllib_device *ieee = priv->rtllib;
+ u32 hwkey[4] = {0, 0, 0, 0};
+ u8 mask = 0xff;
+ u32 key_idx = 0;
+ u8 zero_addr[4][6] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
+ int i;
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ if (!priv->up)
+ return -ENETDOWN;
+
+ priv->rtllib->wx_set_enc = 1;
+ down(&priv->rtllib->ips_sem);
+ IPSLeave(dev);
+ up(&priv->rtllib->ips_sem);
+ down(&priv->wx_sem);
+
+ RT_TRACE(COMP_SEC, "Setting SW wep key");
+ ret = rtllib_wx_set_encode(priv->rtllib, info, wrqu, key);
+ up(&priv->wx_sem);
+
+
+ if (wrqu->encoding.flags & IW_ENCODE_DISABLED) {
+ ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
+ CamResetAllEntry(dev);
+ memset(priv->rtllib->swcamtable, 0,
+ sizeof(struct sw_cam_table) * 32);
+ goto end_hw_sec;
+ }
+ if (wrqu->encoding.length != 0) {
+
+ for (i = 0; i < 4; i++) {
+ hwkey[i] |= key[4*i+0]&mask;
+ if (i == 1 && (4 * i + 1) == wrqu->encoding.length)
+ mask = 0x00;
+ if (i == 3 && (4 * i + 1) == wrqu->encoding.length)
+ mask = 0x00;
+ hwkey[i] |= (key[4 * i + 1] & mask) << 8;
+ hwkey[i] |= (key[4 * i + 2] & mask) << 16;
+ hwkey[i] |= (key[4 * i + 3] & mask) << 24;
+ }
+
+ #define CONF_WEP40 0x4
+ #define CONF_WEP104 0x14
+
+ switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
+ case 0:
+ key_idx = ieee->crypt_info.tx_keyidx;
+ break;
+ case 1:
+ key_idx = 0;
+ break;
+ case 2:
+ key_idx = 1;
+ break;
+ case 3:
+ key_idx = 2;
+ break;
+ case 4:
+ key_idx = 3;
+ break;
+ default:
+ break;
+ }
+ if (wrqu->encoding.length == 0x5) {
+ ieee->pairwise_key_type = KEY_TYPE_WEP40;
+ EnableHWSecurityConfig8192(dev);
+ }
+
+ else if (wrqu->encoding.length == 0xd) {
+ ieee->pairwise_key_type = KEY_TYPE_WEP104;
+ EnableHWSecurityConfig8192(dev);
+ setKey(dev, key_idx, key_idx, KEY_TYPE_WEP104,
+ zero_addr[key_idx], 0, hwkey);
+ set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104,
+ zero_addr[key_idx], 0, hwkey, 0);
+ } else {
+ netdev_info(dev,
+ "wrong type in WEP, not WEP40 and WEP104\n");
+ }
+ }
+
+end_hw_sec:
+ priv->rtllib->wx_set_enc = 0;
+ return ret;
+}
+
+static int r8192_wx_set_scan_type(struct net_device *dev,
+ struct iw_request_info *aa,
+ union iwreq_data *wrqu, char *p)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int *parms = (int *)p;
+ int mode = parms[0];
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ priv->rtllib->active_scan = mode;
+
+ return 1;
+}
+
+
+
+#define R8192_MAX_RETRY 255
+static int r8192_wx_set_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ int err = 0;
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+
+ if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
+ wrqu->retry.disabled) {
+ err = -EINVAL;
+ goto exit;
+ }
+ if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
+ err = -EINVAL;
+ goto exit;
+ }
+
+ if (wrqu->retry.value > R8192_MAX_RETRY) {
+ err = -EINVAL;
+ goto exit;
+ }
+ if (wrqu->retry.flags & IW_RETRY_MAX) {
+ priv->retry_rts = wrqu->retry.value;
+ DMESG("Setting retry for RTS/CTS data to %d",
+ wrqu->retry.value);
+
+ } else {
+ priv->retry_data = wrqu->retry.value;
+ DMESG("Setting retry for non RTS/CTS data to %d",
+ wrqu->retry.value);
+ }
+
+
+ rtl8192_commit(dev);
+exit:
+ up(&priv->wx_sem);
+
+ return err;
+}
+
+static int r8192_wx_get_retry(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+
+ wrqu->retry.disabled = 0; /* can't be disabled */
+
+ if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
+ IW_RETRY_LIFETIME)
+ return -EINVAL;
+
+ if (wrqu->retry.flags & IW_RETRY_MAX) {
+ wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+ wrqu->retry.value = priv->retry_rts;
+ } else {
+ wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+ wrqu->retry.value = priv->retry_data;
+ }
+ return 0;
+}
+
+static int r8192_wx_get_sens(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->rf_set_sens == NULL)
+ return -1; /* we have not this support for this radio */
+ wrqu->sens.value = priv->sens;
+ return 0;
+}
+
+
+static int r8192_wx_set_sens(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ short err = 0;
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+ if (priv->rf_set_sens == NULL) {
+ err = -1; /* we have not this support for this radio */
+ goto exit;
+ }
+ if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
+ priv->sens = wrqu->sens.value;
+ else
+ err = -EINVAL;
+
+exit:
+ up(&priv->wx_sem);
+
+ return err;
+}
+
+static int r8192_wx_set_enc_ext(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+
+ priv->rtllib->wx_set_enc = 1;
+ down(&priv->rtllib->ips_sem);
+ IPSLeave(dev);
+ up(&priv->rtllib->ips_sem);
+
+ ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra);
+ {
+ u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ u8 zero[6] = {0};
+ u32 key[4] = {0};
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ struct iw_point *encoding = &wrqu->encoding;
+ u8 idx = 0, alg = 0, group = 0;
+
+ if ((encoding->flags & IW_ENCODE_DISABLED) ||
+ ext->alg == IW_ENCODE_ALG_NONE) {
+ ieee->pairwise_key_type = ieee->group_key_type
+ = KEY_TYPE_NA;
+ CamResetAllEntry(dev);
+ memset(priv->rtllib->swcamtable, 0,
+ sizeof(struct sw_cam_table) * 32);
+ goto end_hw_sec;
+ }
+ alg = (ext->alg == IW_ENCODE_ALG_CCMP) ? KEY_TYPE_CCMP :
+ ext->alg;
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx)
+ idx--;
+ group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
+
+ if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) ||
+ (alg == KEY_TYPE_WEP40)) {
+ if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
+ alg = KEY_TYPE_WEP104;
+ ieee->pairwise_key_type = alg;
+ EnableHWSecurityConfig8192(dev);
+ }
+ memcpy((u8 *)key, ext->key, 16);
+
+ if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
+ if (ext->key_len == 13)
+ ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
+ setKey(dev, idx, idx, alg, zero, 0, key);
+ set_swcam(dev, idx, idx, alg, zero, 0, key, 0);
+ } else if (group) {
+ ieee->group_key_type = alg;
+ setKey(dev, idx, idx, alg, broadcast_addr, 0, key);
+ set_swcam(dev, idx, idx, alg, broadcast_addr, 0,
+ key, 0);
+ } else {
+ if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) &&
+ ieee->pHTInfo->bCurrentHTSupport)
+ write_nic_byte(dev, 0x173, 1);
+ setKey(dev, 4, idx, alg, (u8 *)ieee->ap_mac_addr,
+ 0, key);
+ set_swcam(dev, 4, idx, alg, (u8 *)ieee->ap_mac_addr,
+ 0, key, 0);
+ }
+
+
+ }
+
+end_hw_sec:
+ priv->rtllib->wx_set_enc = 0;
+ up(&priv->wx_sem);
+ return ret;
+
+}
+static int r8192_wx_set_auth(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *data, char *extra)
+{
+ int ret = 0;
+
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+ ret = rtllib_wx_set_auth(priv->rtllib, info, &(data->param), extra);
+ up(&priv->wx_sem);
+ return ret;
+}
+
+static int r8192_wx_set_mlme(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ int ret = 0;
+
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+ ret = rtllib_wx_set_mlme(priv->rtllib, info, wrqu, extra);
+ up(&priv->wx_sem);
+ return ret;
+}
+
+static int r8192_wx_set_gen_ie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *data, char *extra)
+{
+ int ret = 0;
+
+ struct r8192_priv *priv = rtllib_priv(dev);
+
+ if (priv->bHwRadioOff)
+ return 0;
+
+ down(&priv->wx_sem);
+ ret = rtllib_wx_set_gen_ie(priv->rtllib, extra, data->data.length);
+ up(&priv->wx_sem);
+ return ret;
+}
+
+static int r8192_wx_get_gen_ie(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *data, char *extra)
+{
+ int ret = 0;
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) {
+ data->data.length = 0;
+ return 0;
+ }
+
+ if (data->data.length < ieee->wpa_ie_len)
+ return -E2BIG;
+
+ data->data.length = ieee->wpa_ie_len;
+ memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len);
+ return ret;
+}
+
+#define OID_RT_INTEL_PROMISCUOUS_MODE 0xFF0101F6
+
+static int r8192_wx_set_PromiscuousMode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ u32 info_buf[3];
+
+ u32 oid;
+ u32 bPromiscuousOn;
+ u32 bFilterSourceStationFrame;
+
+ if (copy_from_user(info_buf, wrqu->data.pointer, sizeof(info_buf)))
+ return -EFAULT;
+
+ oid = info_buf[0];
+ bPromiscuousOn = info_buf[1];
+ bFilterSourceStationFrame = info_buf[2];
+
+ if (OID_RT_INTEL_PROMISCUOUS_MODE == oid) {
+ ieee->IntelPromiscuousModeInfo.bPromiscuousOn =
+ (bPromiscuousOn) ? (true) : (false);
+ ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame =
+ (bFilterSourceStationFrame) ? (true) : (false);
+ (bPromiscuousOn) ?
+ (rtllib_EnableIntelPromiscuousMode(dev, false)) :
+ (rtllib_DisableIntelPromiscuousMode(dev, false));
+
+ netdev_info(dev,
+ "=======>%s(), on = %d, filter src sta = %d\n",
+ __func__, bPromiscuousOn,
+ bFilterSourceStationFrame);
+ } else {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int r8192_wx_get_PromiscuousMode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+
+ down(&priv->wx_sem);
+
+ snprintf(extra, 45, "PromiscuousMode:%d, FilterSrcSTAFrame:%d",
+ ieee->IntelPromiscuousModeInfo.bPromiscuousOn,
+ ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame);
+ wrqu->data.length = strlen(extra) + 1;
+
+ up(&priv->wx_sem);
+
+ return 0;
+}
+
+
+#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
+static iw_handler r8192_wx_handlers[] = {
+ IW_IOCTL(SIOCGIWNAME) = r8192_wx_get_name,
+ IW_IOCTL(SIOCSIWFREQ) = r8192_wx_set_freq,
+ IW_IOCTL(SIOCGIWFREQ) = r8192_wx_get_freq,
+ IW_IOCTL(SIOCSIWMODE) = r8192_wx_set_mode,
+ IW_IOCTL(SIOCGIWMODE) = r8192_wx_get_mode,
+ IW_IOCTL(SIOCSIWSENS) = r8192_wx_set_sens,
+ IW_IOCTL(SIOCGIWSENS) = r8192_wx_get_sens,
+ IW_IOCTL(SIOCGIWRANGE) = rtl8192_wx_get_range,
+ IW_IOCTL(SIOCSIWAP) = r8192_wx_set_wap,
+ IW_IOCTL(SIOCGIWAP) = r8192_wx_get_wap,
+ IW_IOCTL(SIOCSIWSCAN) = r8192_wx_set_scan,
+ IW_IOCTL(SIOCGIWSCAN) = r8192_wx_get_scan,
+ IW_IOCTL(SIOCSIWESSID) = r8192_wx_set_essid,
+ IW_IOCTL(SIOCGIWESSID) = r8192_wx_get_essid,
+ IW_IOCTL(SIOCSIWNICKN) = r8192_wx_set_nick,
+ IW_IOCTL(SIOCGIWNICKN) = r8192_wx_get_nick,
+ IW_IOCTL(SIOCSIWRATE) = r8192_wx_set_rate,
+ IW_IOCTL(SIOCGIWRATE) = r8192_wx_get_rate,
+ IW_IOCTL(SIOCSIWRTS) = r8192_wx_set_rts,
+ IW_IOCTL(SIOCGIWRTS) = r8192_wx_get_rts,
+ IW_IOCTL(SIOCSIWFRAG) = r8192_wx_set_frag,
+ IW_IOCTL(SIOCGIWFRAG) = r8192_wx_get_frag,
+ IW_IOCTL(SIOCSIWRETRY) = r8192_wx_set_retry,
+ IW_IOCTL(SIOCGIWRETRY) = r8192_wx_get_retry,
+ IW_IOCTL(SIOCSIWENCODE) = r8192_wx_set_enc,
+ IW_IOCTL(SIOCGIWENCODE) = r8192_wx_get_enc,
+ IW_IOCTL(SIOCSIWPOWER) = r8192_wx_set_power,
+ IW_IOCTL(SIOCGIWPOWER) = r8192_wx_get_power,
+ IW_IOCTL(SIOCSIWGENIE) = r8192_wx_set_gen_ie,
+ IW_IOCTL(SIOCGIWGENIE) = r8192_wx_get_gen_ie,
+ IW_IOCTL(SIOCSIWMLME) = r8192_wx_set_mlme,
+ IW_IOCTL(SIOCSIWAUTH) = r8192_wx_set_auth,
+ IW_IOCTL(SIOCSIWENCODEEXT) = r8192_wx_set_enc_ext,
+};
+
+/* the following rule need to be following,
+ * Odd : get (world access),
+ * even : set (root access)
+ */
+static const struct iw_priv_args r8192_private_args[] = {
+ {
+ SIOCIWFIRSTPRIV + 0x0,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_debugflag"
+ }, {
+ SIOCIWFIRSTPRIV + 0x1,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
+ }, {
+ SIOCIWFIRSTPRIV + 0x2,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
+ }, {
+ SIOCIWFIRSTPRIV + 0x3,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
+ }, {
+ SIOCIWFIRSTPRIV + 0x4,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "force_mic_error"
+ }, {
+ SIOCIWFIRSTPRIV + 0x5,
+ IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT|IW_PRIV_SIZE_FIXED|1,
+ "firm_ver"
+ }, {
+ SIOCIWFIRSTPRIV + 0x6,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
+ "set_power"
+ }, {
+ SIOCIWFIRSTPRIV + 0x9,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
+ "radio"
+ }, {
+ SIOCIWFIRSTPRIV + 0xa,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
+ "lps_interv"
+ }, {
+ SIOCIWFIRSTPRIV + 0xb,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
+ "lps_force"
+ }, {
+ SIOCIWFIRSTPRIV + 0xc,
+ 0, IW_PRIV_TYPE_CHAR|2047, "adhoc_peer_list"
+ }, {
+ SIOCIWFIRSTPRIV + 0x16,
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "setpromisc"
+ }, {
+ SIOCIWFIRSTPRIV + 0x17,
+ 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 45, "getpromisc"
+ }
+
+};
+
+static iw_handler r8192_private_handler[] = {
+ (iw_handler)r8192_wx_set_debugflag, /*SIOCIWSECONDPRIV*/
+ (iw_handler)r8192_wx_set_scan_type,
+ (iw_handler)r8192_wx_set_rawtx,
+ (iw_handler)r8192_wx_force_reset,
+ (iw_handler)r8192_wx_force_mic_error,
+ (iw_handler)r8191se_wx_get_firm_version,
+ (iw_handler)r8192_wx_adapter_power_status,
+ (iw_handler)NULL,
+ (iw_handler)NULL,
+ (iw_handler)r8192se_wx_set_radio,
+ (iw_handler)r8192se_wx_set_lps_awake_interval,
+ (iw_handler)r8192se_wx_set_force_lps,
+ (iw_handler)r8192_wx_get_adhoc_peers,
+ (iw_handler)NULL,
+ (iw_handler)NULL,
+ (iw_handler)NULL,
+ (iw_handler)NULL,
+ (iw_handler)NULL,
+ (iw_handler)NULL,
+ (iw_handler)NULL,
+ (iw_handler)NULL,
+ (iw_handler)NULL,
+ (iw_handler)r8192_wx_set_PromiscuousMode,
+ (iw_handler)r8192_wx_get_PromiscuousMode,
+};
+
+static struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
+{
+ struct r8192_priv *priv = rtllib_priv(dev);
+ struct rtllib_device *ieee = priv->rtllib;
+ struct iw_statistics *wstats = &priv->wstats;
+ int tmp_level = 0;
+ int tmp_qual = 0;
+ int tmp_noise = 0;
+
+ if (ieee->state < RTLLIB_LINKED) {
+ wstats->qual.qual = 10;
+ wstats->qual.level = 0;
+ wstats->qual.noise = -100;
+ wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+ return wstats;
+ }
+
+ tmp_level = (&ieee->current_network)->stats.rssi;
+ tmp_qual = (&ieee->current_network)->stats.signal;
+ tmp_noise = (&ieee->current_network)->stats.noise;
+
+ wstats->qual.level = tmp_level;
+ wstats->qual.qual = tmp_qual;
+ wstats->qual.noise = tmp_noise;
+ wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+ return wstats;
+}
+
+const struct iw_handler_def r8192_wx_handlers_def = {
+ .standard = r8192_wx_handlers,
+ .num_standard = ARRAY_SIZE(r8192_wx_handlers),
+ .private = r8192_private_handler,
+ .num_private = ARRAY_SIZE(r8192_private_handler),
+ .num_private_args = sizeof(r8192_private_args) /
+ sizeof(struct iw_priv_args),
+ .get_wireless_stats = r8192_get_wireless_stats,
+ .private_args = (struct iw_priv_args *)r8192_private_args,
+};
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.h b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.h
new file mode 100644
index 000000000..58398517f
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.h
@@ -0,0 +1,30 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+
+#ifndef R819x_WX_H
+#define R819x_WX_H
+
+struct net_device;
+struct iw_handler_def;
+struct iw_statistics;
+
+extern const struct iw_handler_def r8192_wx_handlers_def;
+u16 rtl8192_11n_user_show_rates(struct net_device *dev);
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl819x_BA.h b/drivers/staging/rtl8192e/rtl819x_BA.h
new file mode 100644
index 000000000..613e14c12
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl819x_BA.h
@@ -0,0 +1,77 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _BATYPE_H_
+#define _BATYPE_H_
+
+#define TOTAL_TXBA_NUM 16
+#define TOTAL_RXBA_NUM 16
+
+#define BA_SETUP_TIMEOUT 200
+#define BA_INACT_TIMEOUT 60000
+
+#define BA_POLICY_DELAYED 0
+#define BA_POLICY_IMMEDIATE 1
+
+#define ADDBA_STATUS_SUCCESS 0
+#define ADDBA_STATUS_REFUSED 37
+#define ADDBA_STATUS_INVALID_PARAM 38
+
+#define DELBA_REASON_QSTA_LEAVING 36
+#define DELBA_REASON_END_BA 37
+#define DELBA_REASON_UNKNOWN_BA 38
+#define DELBA_REASON_TIMEOUT 39
+union sequence_control {
+ u16 ShortData;
+ struct {
+ u16 FragNum:4;
+ u16 SeqNum:12;
+ } field;
+};
+
+union ba_param_set {
+ u8 charData[2];
+ u16 shortData;
+ struct {
+ u16 AMSDU_Support:1;
+ u16 BAPolicy:1;
+ u16 TID:4;
+ u16 BufferSize:10;
+ } field;
+};
+
+union delba_param_set {
+ u8 charData[2];
+ u16 shortData;
+ struct {
+ u16 Reserved:11;
+ u16 Initiator:1;
+ u16 TID:4;
+ } field;
+};
+
+struct ba_record {
+ struct timer_list Timer;
+ u8 bValid;
+ u8 DialogToken;
+ union ba_param_set BaParamSet;
+ u16 BaTimeoutValue;
+ union sequence_control BaStartSeqCtrl;
+};
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl819x_BAProc.c b/drivers/staging/rtl8192e/rtl819x_BAProc.c
new file mode 100644
index 000000000..26258ea8d
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl819x_BAProc.c
@@ -0,0 +1,571 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include <asm/byteorder.h>
+#include <asm/unaligned.h>
+#include "rtllib.h"
+#include "rtl819x_BA.h"
+
+static void ActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA,
+ u16 Time)
+{
+ pBA->bValid = true;
+ if (Time != 0)
+ mod_timer(&pBA->Timer, jiffies + msecs_to_jiffies(Time));
+}
+
+static void DeActivateBAEntry(struct rtllib_device *ieee, struct ba_record *pBA)
+{
+ pBA->bValid = false;
+ del_timer_sync(&pBA->Timer);
+}
+
+static u8 TxTsDeleteBA(struct rtllib_device *ieee, struct tx_ts_record *pTxTs)
+{
+ struct ba_record *pAdmittedBa = &pTxTs->TxAdmittedBARecord;
+ struct ba_record *pPendingBa = &pTxTs->TxPendingBARecord;
+ u8 bSendDELBA = false;
+
+ if (pPendingBa->bValid) {
+ DeActivateBAEntry(ieee, pPendingBa);
+ bSendDELBA = true;
+ }
+
+ if (pAdmittedBa->bValid) {
+ DeActivateBAEntry(ieee, pAdmittedBa);
+ bSendDELBA = true;
+ }
+ return bSendDELBA;
+}
+
+static u8 RxTsDeleteBA(struct rtllib_device *ieee, struct rx_ts_record *pRxTs)
+{
+ struct ba_record *pBa = &pRxTs->RxAdmittedBARecord;
+ u8 bSendDELBA = false;
+
+ if (pBa->bValid) {
+ DeActivateBAEntry(ieee, pBa);
+ bSendDELBA = true;
+ }
+
+ return bSendDELBA;
+}
+
+void ResetBaEntry(struct ba_record *pBA)
+{
+ pBA->bValid = false;
+ pBA->BaParamSet.shortData = 0;
+ pBA->BaTimeoutValue = 0;
+ pBA->DialogToken = 0;
+ pBA->BaStartSeqCtrl.ShortData = 0;
+}
+static struct sk_buff *rtllib_ADDBA(struct rtllib_device *ieee, u8 *Dst,
+ struct ba_record *pBA,
+ u16 StatusCode, u8 type)
+{
+ struct sk_buff *skb = NULL;
+ struct rtllib_hdr_3addr *BAReq = NULL;
+ u8 *tag = NULL;
+ u16 len = ieee->tx_headroom + 9;
+
+ RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA,
+ "========>%s(), frame(%d) sentd to: %pM, ieee->dev:%p\n",
+ __func__, type, Dst, ieee->dev);
+ if (pBA == NULL) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "pBA is NULL\n");
+ return NULL;
+ }
+ skb = dev_alloc_skb(len + sizeof(struct rtllib_hdr_3addr));
+ if (skb == NULL) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
+ return NULL;
+ }
+
+ memset(skb->data, 0, sizeof(struct rtllib_hdr_3addr));
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ BAReq = (struct rtllib_hdr_3addr *)skb_put(skb,
+ sizeof(struct rtllib_hdr_3addr));
+
+ memcpy(BAReq->addr1, Dst, ETH_ALEN);
+ memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
+
+ memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
+ BAReq->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT);
+
+ tag = (u8 *)skb_put(skb, 9);
+ *tag++ = ACT_CAT_BA;
+ *tag++ = type;
+ *tag++ = pBA->DialogToken;
+
+ if (ACT_ADDBARSP == type) {
+ RT_TRACE(COMP_DBG, "====>to send ADDBARSP\n");
+
+ put_unaligned_le16(StatusCode, tag);
+ tag += 2;
+ }
+
+ put_unaligned_le16(pBA->BaParamSet.shortData, tag);
+ tag += 2;
+
+ put_unaligned_le16(pBA->BaTimeoutValue, tag);
+ tag += 2;
+
+ if (ACT_ADDBAREQ == type) {
+ memcpy(tag, (u8 *)&(pBA->BaStartSeqCtrl), 2);
+ tag += 2;
+ }
+
+ RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
+ return skb;
+}
+
+static struct sk_buff *rtllib_DELBA(struct rtllib_device *ieee, u8 *dst,
+ struct ba_record *pBA,
+ enum tr_select TxRxSelect, u16 ReasonCode)
+{
+ union delba_param_set DelbaParamSet;
+ struct sk_buff *skb = NULL;
+ struct rtllib_hdr_3addr *Delba = NULL;
+ u8 *tag = NULL;
+ u16 len = 6 + ieee->tx_headroom;
+
+ if (net_ratelimit())
+ RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA,
+ "========>%s(), ReasonCode(%d) sentd to: %pM\n",
+ __func__, ReasonCode, dst);
+
+ memset(&DelbaParamSet, 0, 2);
+
+ DelbaParamSet.field.Initiator = (TxRxSelect == TX_DIR) ? 1 : 0;
+ DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
+
+ skb = dev_alloc_skb(len + sizeof(struct rtllib_hdr_3addr));
+ if (skb == NULL) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
+ return NULL;
+ }
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ Delba = (struct rtllib_hdr_3addr *) skb_put(skb,
+ sizeof(struct rtllib_hdr_3addr));
+
+ memcpy(Delba->addr1, dst, ETH_ALEN);
+ memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
+ memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
+ Delba->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT);
+
+ tag = (u8 *)skb_put(skb, 6);
+
+ *tag++ = ACT_CAT_BA;
+ *tag++ = ACT_DELBA;
+
+
+ put_unaligned_le16(DelbaParamSet.shortData, tag);
+ tag += 2;
+
+ put_unaligned_le16(ReasonCode, tag);
+ tag += 2;
+
+ RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
+ if (net_ratelimit())
+ RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "<=====%s()\n",
+ __func__);
+ return skb;
+}
+
+static void rtllib_send_ADDBAReq(struct rtllib_device *ieee, u8 *dst,
+ struct ba_record *pBA)
+{
+ struct sk_buff *skb = NULL;
+
+ skb = rtllib_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ);
+
+ if (skb) {
+ RT_TRACE(COMP_DBG, "====>to send ADDBAREQ!!!!!\n");
+ softmac_mgmt_xmit(skb, ieee);
+ } else {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "alloc skb error in function %s()\n", __func__);
+ }
+}
+
+static void rtllib_send_ADDBARsp(struct rtllib_device *ieee, u8 *dst,
+ struct ba_record *pBA, u16 StatusCode)
+{
+ struct sk_buff *skb = NULL;
+
+ skb = rtllib_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP);
+ if (skb)
+ softmac_mgmt_xmit(skb, ieee);
+ else
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "alloc skb error in function %s()\n", __func__);
+}
+
+static void rtllib_send_DELBA(struct rtllib_device *ieee, u8 *dst,
+ struct ba_record *pBA, enum tr_select TxRxSelect,
+ u16 ReasonCode)
+{
+ struct sk_buff *skb = NULL;
+
+ skb = rtllib_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode);
+ if (skb)
+ softmac_mgmt_xmit(skb, ieee);
+ else
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "alloc skb error in function %s()\n", __func__);
+}
+
+int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+ struct rtllib_hdr_3addr *req = NULL;
+ u16 rc = 0;
+ u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
+ struct ba_record *pBA = NULL;
+ union ba_param_set *pBaParamSet = NULL;
+ u16 *pBaTimeoutVal = NULL;
+ union sequence_control *pBaStartSeqCtrl = NULL;
+ struct rx_ts_record *pTS = NULL;
+
+ if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ " Invalid skb len in BAREQ(%d / %d)\n",
+ (int)skb->len,
+ (int)(sizeof(struct rtllib_hdr_3addr) + 9));
+ return -1;
+ }
+
+ RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
+
+ req = (struct rtllib_hdr_3addr *) skb->data;
+ tag = (u8 *)req;
+ dst = (u8 *)(&req->addr2[0]);
+ tag += sizeof(struct rtllib_hdr_3addr);
+ pDialogToken = tag + 2;
+ pBaParamSet = (union ba_param_set *)(tag + 3);
+ pBaTimeoutVal = (u16 *)(tag + 5);
+ pBaStartSeqCtrl = (union sequence_control *)(req + 7);
+
+ RT_TRACE(COMP_DBG, "====>rx ADDBAREQ from : %pM\n", dst);
+ if (ieee->current_network.qos_data.active == 0 ||
+ (ieee->pHTInfo->bCurrentHTSupport == false) ||
+ (ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ)) {
+ rc = ADDBA_STATUS_REFUSED;
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n",
+ ieee->current_network.qos_data.active,
+ ieee->pHTInfo->bCurrentHTSupport);
+ goto OnADDBAReq_Fail;
+ }
+ if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
+ (u8)(pBaParamSet->field.TID), RX_DIR, true)) {
+ rc = ADDBA_STATUS_REFUSED;
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __func__);
+ goto OnADDBAReq_Fail;
+ }
+ pBA = &pTS->RxAdmittedBARecord;
+
+ if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
+ rc = ADDBA_STATUS_INVALID_PARAM;
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "BA Policy is not correct in %s()\n", __func__);
+ goto OnADDBAReq_Fail;
+ }
+
+ rtllib_FlushRxTsPendingPkts(ieee, pTS);
+
+ DeActivateBAEntry(ieee, pBA);
+ pBA->DialogToken = *pDialogToken;
+ pBA->BaParamSet = *pBaParamSet;
+ pBA->BaTimeoutValue = *pBaTimeoutVal;
+ pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
+
+ if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev) ||
+ (ieee->pHTInfo->IOTAction & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT))
+ pBA->BaParamSet.field.BufferSize = 1;
+ else
+ pBA->BaParamSet.field.BufferSize = 32;
+
+ ActivateBAEntry(ieee, pBA, 0);
+ rtllib_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
+
+ return 0;
+
+OnADDBAReq_Fail:
+ {
+ struct ba_record BA;
+
+ BA.BaParamSet = *pBaParamSet;
+ BA.BaTimeoutValue = *pBaTimeoutVal;
+ BA.DialogToken = *pDialogToken;
+ BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
+ rtllib_send_ADDBARsp(ieee, dst, &BA, rc);
+ return 0;
+ }
+}
+
+int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+ struct rtllib_hdr_3addr *rsp = NULL;
+ struct ba_record *pPendingBA, *pAdmittedBA;
+ struct tx_ts_record *pTS = NULL;
+ u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
+ u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL;
+ union ba_param_set *pBaParamSet = NULL;
+ u16 ReasonCode;
+
+ if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "Invalid skb len in BARSP(%d / %d)\n",
+ (int)skb->len,
+ (int)(sizeof(struct rtllib_hdr_3addr) + 9));
+ return -1;
+ }
+ rsp = (struct rtllib_hdr_3addr *)skb->data;
+ tag = (u8 *)rsp;
+ dst = (u8 *)(&rsp->addr2[0]);
+ tag += sizeof(struct rtllib_hdr_3addr);
+ pDialogToken = tag + 2;
+ pStatusCode = (u16 *)(tag + 3);
+ pBaParamSet = (union ba_param_set *)(tag + 5);
+ pBaTimeoutVal = (u16 *)(tag + 7);
+
+ RT_TRACE(COMP_DBG, "====>rx ADDBARSP from : %pM\n", dst);
+ if (ieee->current_network.qos_data.active == 0 ||
+ ieee->pHTInfo->bCurrentHTSupport == false ||
+ ieee->pHTInfo->bCurrentAMPDUEnable == false) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",
+ ieee->current_network.qos_data.active,
+ ieee->pHTInfo->bCurrentHTSupport,
+ ieee->pHTInfo->bCurrentAMPDUEnable);
+ ReasonCode = DELBA_REASON_UNKNOWN_BA;
+ goto OnADDBARsp_Reject;
+ }
+
+
+ if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
+ (u8)(pBaParamSet->field.TID), TX_DIR, false)) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __func__);
+ ReasonCode = DELBA_REASON_UNKNOWN_BA;
+ goto OnADDBARsp_Reject;
+ }
+
+ pTS->bAddBaReqInProgress = false;
+ pPendingBA = &pTS->TxPendingBARecord;
+ pAdmittedBA = &pTS->TxAdmittedBARecord;
+
+
+ if (pAdmittedBA->bValid == true) {
+ RTLLIB_DEBUG(RTLLIB_DL_BA,
+ "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it!\n");
+ return -1;
+ } else if ((pPendingBA->bValid == false) ||
+ (*pDialogToken != pPendingBA->DialogToken)) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA!\n");
+ ReasonCode = DELBA_REASON_UNKNOWN_BA;
+ goto OnADDBARsp_Reject;
+ } else {
+ RTLLIB_DEBUG(RTLLIB_DL_BA,
+ "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n",
+ *pStatusCode);
+ DeActivateBAEntry(ieee, pPendingBA);
+ }
+
+
+ if (*pStatusCode == ADDBA_STATUS_SUCCESS) {
+ if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
+ pTS->bAddBaReqDelayed = true;
+ DeActivateBAEntry(ieee, pAdmittedBA);
+ ReasonCode = DELBA_REASON_END_BA;
+ goto OnADDBARsp_Reject;
+ }
+
+
+ pAdmittedBA->DialogToken = *pDialogToken;
+ pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
+ pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
+ pAdmittedBA->BaParamSet = *pBaParamSet;
+ DeActivateBAEntry(ieee, pAdmittedBA);
+ ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
+ } else {
+ pTS->bAddBaReqDelayed = true;
+ pTS->bDisable_AddBa = true;
+ ReasonCode = DELBA_REASON_END_BA;
+ goto OnADDBARsp_Reject;
+ }
+
+ return 0;
+
+OnADDBARsp_Reject:
+ {
+ struct ba_record BA;
+
+ BA.BaParamSet = *pBaParamSet;
+ rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
+ return 0;
+ }
+}
+
+int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+ struct rtllib_hdr_3addr *delba = NULL;
+ union delba_param_set *pDelBaParamSet = NULL;
+ u16 *pReasonCode = NULL;
+ u8 *dst = NULL;
+
+ if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "Invalid skb len in DELBA(%d / %d)\n",
+ (int)skb->len,
+ (int)(sizeof(struct rtllib_hdr_3addr) + 6));
+ return -1;
+ }
+
+ if (ieee->current_network.qos_data.active == 0 ||
+ ieee->pHTInfo->bCurrentHTSupport == false) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "received DELBA while QOS or HT is not supported(%d, %d)\n",
+ ieee->current_network. qos_data.active,
+ ieee->pHTInfo->bCurrentHTSupport);
+ return -1;
+ }
+
+ RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len);
+ delba = (struct rtllib_hdr_3addr *)skb->data;
+ dst = (u8 *)(&delba->addr2[0]);
+ delba += sizeof(struct rtllib_hdr_3addr);
+ pDelBaParamSet = (union delba_param_set *)(delba+2);
+ pReasonCode = (u16 *)(delba+4);
+
+ if (pDelBaParamSet->field.Initiator == 1) {
+ struct rx_ts_record *pRxTs;
+
+ if (!GetTs(ieee, (struct ts_common_info **)&pRxTs, dst,
+ (u8)pDelBaParamSet->field.TID, RX_DIR, false)) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "can't get TS for RXTS in %s().dst: %pM TID:%d\n",
+ __func__, dst,
+ (u8)pDelBaParamSet->field.TID);
+ return -1;
+ }
+
+ RxTsDeleteBA(ieee, pRxTs);
+ } else {
+ struct tx_ts_record *pTxTs;
+
+ if (!GetTs(ieee, (struct ts_common_info **)&pTxTs, dst,
+ (u8)pDelBaParamSet->field.TID, TX_DIR, false)) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "can't get TS for TXTS in %s()\n",
+ __func__);
+ return -1;
+ }
+
+ pTxTs->bUsingBa = false;
+ pTxTs->bAddBaReqInProgress = false;
+ pTxTs->bAddBaReqDelayed = false;
+ del_timer_sync(&pTxTs->TsAddBaTimer);
+ TxTsDeleteBA(ieee, pTxTs);
+ }
+ return 0;
+}
+
+void TsInitAddBA(struct rtllib_device *ieee, struct tx_ts_record *pTS,
+ u8 Policy, u8 bOverwritePending)
+{
+ struct ba_record *pBA = &pTS->TxPendingBARecord;
+
+ if (pBA->bValid == true && bOverwritePending == false)
+ return;
+
+ DeActivateBAEntry(ieee, pBA);
+
+ pBA->DialogToken++;
+ pBA->BaParamSet.field.AMSDU_Support = 0;
+ pBA->BaParamSet.field.BAPolicy = Policy;
+ pBA->BaParamSet.field.TID =
+ pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID;
+ pBA->BaParamSet.field.BufferSize = 32;
+ pBA->BaTimeoutValue = 0;
+ pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096;
+
+ ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
+
+ rtllib_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
+}
+
+void TsInitDelBA(struct rtllib_device *ieee,
+ struct ts_common_info *pTsCommonInfo,
+ enum tr_select TxRxSelect)
+{
+ if (TxRxSelect == TX_DIR) {
+ struct tx_ts_record *pTxTs =
+ (struct tx_ts_record *)pTsCommonInfo;
+
+ if (TxTsDeleteBA(ieee, pTxTs))
+ rtllib_send_DELBA(ieee, pTsCommonInfo->Addr,
+ (pTxTs->TxAdmittedBARecord.bValid) ?
+ (&pTxTs->TxAdmittedBARecord) :
+ (&pTxTs->TxPendingBARecord),
+ TxRxSelect, DELBA_REASON_END_BA);
+ } else if (TxRxSelect == RX_DIR) {
+ struct rx_ts_record *pRxTs =
+ (struct rx_ts_record *)pTsCommonInfo;
+ if (RxTsDeleteBA(ieee, pRxTs))
+ rtllib_send_DELBA(ieee, pTsCommonInfo->Addr,
+ &pRxTs->RxAdmittedBARecord,
+ TxRxSelect, DELBA_REASON_END_BA);
+ }
+}
+
+void BaSetupTimeOut(unsigned long data)
+{
+ struct tx_ts_record *pTxTs = (struct tx_ts_record *)data;
+
+ pTxTs->bAddBaReqInProgress = false;
+ pTxTs->bAddBaReqDelayed = true;
+ pTxTs->TxPendingBARecord.bValid = false;
+}
+
+void TxBaInactTimeout(unsigned long data)
+{
+ struct tx_ts_record *pTxTs = (struct tx_ts_record *)data;
+ struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device,
+ TxTsRecord[pTxTs->num]);
+ TxTsDeleteBA(ieee, pTxTs);
+ rtllib_send_DELBA(ieee, pTxTs->TsCommonInfo.Addr,
+ &pTxTs->TxAdmittedBARecord, TX_DIR,
+ DELBA_REASON_TIMEOUT);
+}
+
+void RxBaInactTimeout(unsigned long data)
+{
+ struct rx_ts_record *pRxTs = (struct rx_ts_record *)data;
+ struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device,
+ RxTsRecord[pRxTs->num]);
+
+ RxTsDeleteBA(ieee, pRxTs);
+ rtllib_send_DELBA(ieee, pRxTs->TsCommonInfo.Addr,
+ &pRxTs->RxAdmittedBARecord, RX_DIR,
+ DELBA_REASON_TIMEOUT);
+}
diff --git a/drivers/staging/rtl8192e/rtl819x_HT.h b/drivers/staging/rtl8192e/rtl819x_HT.h
new file mode 100644
index 000000000..f7076d7dd
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl819x_HT.h
@@ -0,0 +1,428 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _RTL819XU_HTTYPE_H_
+#define _RTL819XU_HTTYPE_H_
+
+
+#define HT_OPMODE_NO_PROTECT 0
+#define HT_OPMODE_OPTIONAL 1
+#define HT_OPMODE_40MHZ_PROTECT 2
+#define HT_OPMODE_MIXED 3
+
+#define MIMO_PS_STATIC 0
+#define MIMO_PS_DYNAMIC 1
+#define MIMO_PS_NOLIMIT 3
+
+
+
+#define sHTCLng 4
+
+
+#define HT_SUPPORTED_MCS_1SS_BITMAP 0x000000ff
+#define HT_SUPPORTED_MCS_2SS_BITMAP 0x0000ff00
+#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP \
+ (HT_MCS_1SS_BITMAP | HT_MCS_1SS_2SS_BITMAP)
+
+enum ht_mcs_rate {
+ HT_MCS0 = 0x00000001,
+ HT_MCS1 = 0x00000002,
+ HT_MCS2 = 0x00000004,
+ HT_MCS3 = 0x00000008,
+ HT_MCS4 = 0x00000010,
+ HT_MCS5 = 0x00000020,
+ HT_MCS6 = 0x00000040,
+ HT_MCS7 = 0x00000080,
+ HT_MCS8 = 0x00000100,
+ HT_MCS9 = 0x00000200,
+ HT_MCS10 = 0x00000400,
+ HT_MCS11 = 0x00000800,
+ HT_MCS12 = 0x00001000,
+ HT_MCS13 = 0x00002000,
+ HT_MCS14 = 0x00004000,
+ HT_MCS15 = 0x00008000,
+};
+
+enum ht_channel_width {
+ HT_CHANNEL_WIDTH_20 = 0,
+ HT_CHANNEL_WIDTH_20_40 = 1,
+};
+
+enum ht_extchnl_offset {
+ HT_EXTCHNL_OFFSET_NO_EXT = 0,
+ HT_EXTCHNL_OFFSET_UPPER = 1,
+ HT_EXTCHNL_OFFSET_NO_DEF = 2,
+ HT_EXTCHNL_OFFSET_LOWER = 3,
+};
+
+enum chnl_op {
+ CHNLOP_NONE = 0,
+ CHNLOP_SCAN = 1,
+ CHNLOP_SWBW = 2,
+ CHNLOP_SWCHNL = 3,
+};
+
+enum ht_action {
+ ACT_RECOMMAND_WIDTH = 0,
+ ACT_MIMO_PWR_SAVE = 1,
+ ACT_PSMP = 2,
+ ACT_SET_PCO_PHASE = 3,
+ ACT_MIMO_CHL_MEASURE = 4,
+ ACT_RECIPROCITY_CORRECT = 5,
+ ACT_MIMO_CSI_MATRICS = 6,
+ ACT_MIMO_NOCOMPR_STEER = 7,
+ ACT_MIMO_COMPR_STEER = 8,
+ ACT_ANTENNA_SELECT = 9,
+};
+
+
+enum ht_bw40_sc {
+ SC_MODE_DUPLICATE = 0,
+ SC_MODE_LOWER = 1,
+ SC_MODE_UPPER = 2,
+ SC_MODE_FULL40MHZ = 3,
+};
+
+struct ht_capab_ele {
+
+ u8 AdvCoding:1;
+ u8 ChlWidth:1;
+ u8 MimoPwrSave:2;
+ u8 GreenField:1;
+ u8 ShortGI20Mhz:1;
+ u8 ShortGI40Mhz:1;
+ u8 TxSTBC:1;
+ u8 RxSTBC:2;
+ u8 DelayBA:1;
+ u8 MaxAMSDUSize:1;
+ u8 DssCCk:1;
+ u8 PSMP:1;
+ u8 Rsvd1:1;
+ u8 LSigTxopProtect:1;
+
+ u8 MaxRxAMPDUFactor:2;
+ u8 MPDUDensity:3;
+ u8 Rsvd2:3;
+
+ u8 MCS[16];
+
+
+ u16 ExtHTCapInfo;
+
+ u8 TxBFCap[4];
+
+ u8 ASCap;
+
+} __packed;
+
+
+struct ht_info_ele {
+ u8 ControlChl;
+
+ u8 ExtChlOffset:2;
+ u8 RecommemdedTxWidth:1;
+ u8 RIFS:1;
+ u8 PSMPAccessOnly:1;
+ u8 SrvIntGranularity:3;
+
+ u8 OptMode:2;
+ u8 NonGFDevPresent:1;
+ u8 Revd1:5;
+ u8 Revd2:8;
+
+ u8 Rsvd3:6;
+ u8 DualBeacon:1;
+ u8 DualCTSProtect:1;
+
+ u8 SecondaryBeacon:1;
+ u8 LSigTxopProtectFull:1;
+ u8 PcoActive:1;
+ u8 PcoPhase:1;
+ u8 Rsvd4:4;
+
+ u8 BasicMSC[16];
+} __packed;
+
+struct mimops_ctrl {
+ u8 MimoPsEnable:1;
+ u8 MimoPsMode:1;
+ u8 Reserved:6;
+};
+
+enum ht_spec_ver {
+ HT_SPEC_VER_IEEE = 0,
+ HT_SPEC_VER_EWC = 1,
+};
+
+enum ht_aggre_mode {
+ HT_AGG_AUTO = 0,
+ HT_AGG_FORCE_ENABLE = 1,
+ HT_AGG_FORCE_DISABLE = 2,
+};
+
+
+struct rt_hi_throughput {
+ u8 bEnableHT;
+ u8 bCurrentHTSupport;
+
+ u8 bRegBW40MHz;
+ u8 bCurBW40MHz;
+
+ u8 bRegShortGI40MHz;
+ u8 bCurShortGI40MHz;
+
+ u8 bRegShortGI20MHz;
+ u8 bCurShortGI20MHz;
+
+ u8 bRegSuppCCK;
+ u8 bCurSuppCCK;
+
+ enum ht_spec_ver ePeerHTSpecVer;
+
+
+ struct ht_capab_ele SelfHTCap;
+ struct ht_info_ele SelfHTInfo;
+
+ u8 PeerHTCapBuf[32];
+ u8 PeerHTInfoBuf[32];
+
+
+ u8 bAMSDU_Support;
+ u16 nAMSDU_MaxSize;
+ u8 bCurrent_AMSDU_Support;
+ u16 nCurrent_AMSDU_MaxSize;
+
+ u8 bAMPDUEnable;
+ u8 bCurrentAMPDUEnable;
+ u8 AMPDU_Factor;
+ u8 CurrentAMPDUFactor;
+ u8 MPDU_Density;
+ u8 CurrentMPDUDensity;
+
+ enum ht_aggre_mode ForcedAMPDUMode;
+ u8 ForcedAMPDUFactor;
+ u8 ForcedMPDUDensity;
+
+ enum ht_aggre_mode ForcedAMSDUMode;
+ u16 ForcedAMSDUMaxSize;
+
+ u8 bForcedShortGI;
+
+ u8 CurrentOpMode;
+
+ u8 SelfMimoPs;
+ u8 PeerMimoPs;
+
+ enum ht_extchnl_offset CurSTAExtChnlOffset;
+ u8 bCurTxBW40MHz;
+ u8 PeerBandwidth;
+
+ u8 bSwBwInProgress;
+ enum chnl_op ChnlOp;
+ u8 SwBwStep;
+
+ u8 bRegRT2RTAggregation;
+ u8 RT2RT_HT_Mode;
+ u8 bCurrentRT2RTAggregation;
+ u8 bCurrentRT2RTLongSlotTime;
+ u8 szRT2RTAggBuffer[10];
+
+ u8 bRegRxReorderEnable;
+ u8 bCurRxReorderEnable;
+ u8 RxReorderWinSize;
+ u8 RxReorderPendingTime;
+ u16 RxReorderDropCounter;
+
+ u8 bIsPeerBcm;
+
+ u8 IOTPeer;
+ u32 IOTAction;
+ u8 IOTRaFunc;
+
+ u8 bWAIotBroadcom;
+ u8 WAIotTH;
+
+ u8 bAcceptAddbaReq;
+} __packed;
+
+
+
+struct rt_htinfo_sta_entry {
+ u8 bEnableHT;
+
+ u8 bSupportCck;
+
+ u16 AMSDU_MaxSize;
+
+ u8 AMPDU_Factor;
+ u8 MPDU_Density;
+
+ u8 HTHighestOperaRate;
+
+ u8 bBw40MHz;
+
+ u8 bCurTxBW40MHz;
+
+ u8 bCurShortGI20MHz;
+
+ u8 bCurShortGI40MHz;
+
+ u8 MimoPs;
+
+ u8 McsRateSet[16];
+
+ u8 bCurRxReorderEnable;
+
+ u16 nAMSDU_MaxSize;
+
+};
+
+
+
+
+
+
+struct bss_ht {
+
+ u8 bdSupportHT;
+
+ u8 bdHTCapBuf[32];
+ u16 bdHTCapLen;
+ u8 bdHTInfoBuf[32];
+ u16 bdHTInfoLen;
+
+ enum ht_spec_ver bdHTSpecVer;
+ enum ht_channel_width bdBandWidth;
+
+ u8 bdRT2RTAggregation;
+ u8 bdRT2RTLongSlotTime;
+ u8 RT2RT_HT_Mode;
+ u8 bdHT1R;
+};
+
+struct mimo_rssi {
+ u32 EnableAntenna;
+ u32 AntennaA;
+ u32 AntennaB;
+ u32 AntennaC;
+ u32 AntennaD;
+ u32 Average;
+};
+
+struct mimo_evm {
+ u32 EVM1;
+ u32 EVM2;
+};
+
+struct false_alarm_stats {
+ u32 Cnt_Parity_Fail;
+ u32 Cnt_Rate_Illegal;
+ u32 Cnt_Crc8_fail;
+ u32 Cnt_Mcs_fail;
+ u32 Cnt_Ofdm_fail;
+ u32 Cnt_Cck_fail;
+ u32 Cnt_all;
+};
+
+
+extern u8 MCS_FILTER_ALL[16];
+extern u8 MCS_FILTER_1SS[16];
+
+#define RATE_ADPT_1SS_MASK 0xFF
+#define RATE_ADPT_2SS_MASK 0xF0
+#define RATE_ADPT_MCS32_MASK 0x01
+
+#define IS_11N_MCS_RATE(rate) (rate&0x80)
+
+enum ht_aggre_size {
+ HT_AGG_SIZE_8K = 0,
+ HT_AGG_SIZE_16K = 1,
+ HT_AGG_SIZE_32K = 2,
+ HT_AGG_SIZE_64K = 3,
+};
+
+enum ht_iot_peer {
+ HT_IOT_PEER_UNKNOWN = 0,
+ HT_IOT_PEER_REALTEK = 1,
+ HT_IOT_PEER_REALTEK_92SE = 2,
+ HT_IOT_PEER_BROADCOM = 3,
+ HT_IOT_PEER_RALINK = 4,
+ HT_IOT_PEER_ATHEROS = 5,
+ HT_IOT_PEER_CISCO = 6,
+ HT_IOT_PEER_MARVELL = 7,
+ HT_IOT_PEER_92U_SOFTAP = 8,
+ HT_IOT_PEER_SELF_SOFTAP = 9,
+ HT_IOT_PEER_AIRGO = 10,
+ HT_IOT_PEER_MAX = 11,
+};
+
+enum ht_iot_peer_subtype {
+ HT_IOT_PEER_ATHEROS_DIR635 = 0,
+};
+
+enum ht_iot_action {
+ HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001,
+ HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002,
+ HT_IOT_ACT_DISABLE_MCS14 = 0x00000004,
+ HT_IOT_ACT_DISABLE_MCS15 = 0x00000008,
+ HT_IOT_ACT_DISABLE_ALL_2SS = 0x00000010,
+ HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000020,
+ HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000040,
+ HT_IOT_ACT_CDD_FSYNC = 0x00000080,
+ HT_IOT_ACT_PURE_N_MODE = 0x00000100,
+ HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200,
+ HT_IOT_ACT_FORCED_RTS = 0x00000400,
+ HT_IOT_ACT_AMSDU_ENABLE = 0x00000800,
+ HT_IOT_ACT_REJECT_ADDBA_REQ = 0x00001000,
+ HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT = 0x00002000,
+ HT_IOT_ACT_EDCA_BIAS_ON_RX = 0x00004000,
+
+ HT_IOT_ACT_HYBRID_AGGREGATION = 0x00010000,
+ HT_IOT_ACT_DISABLE_SHORT_GI = 0x00020000,
+ HT_IOT_ACT_DISABLE_HIGH_POWER = 0x00040000,
+ HT_IOT_ACT_DISABLE_TX_40_MHZ = 0x00080000,
+ HT_IOT_ACT_TX_NO_AGGREGATION = 0x00100000,
+ HT_IOT_ACT_DISABLE_TX_2SS = 0x00200000,
+
+ HT_IOT_ACT_MID_HIGHPOWER = 0x00400000,
+ HT_IOT_ACT_NULL_DATA_POWER_SAVING = 0x00800000,
+
+ HT_IOT_ACT_DISABLE_CCK_RATE = 0x01000000,
+ HT_IOT_ACT_FORCED_ENABLE_BE_TXOP = 0x02000000,
+ HT_IOT_ACT_WA_IOT_Broadcom = 0x04000000,
+
+ HT_IOT_ACT_DISABLE_RX_40MHZ_SHORT_GI = 0x08000000,
+
+};
+
+enum ht_iot_rafunc {
+ HT_IOT_RAFUNC_DISABLE_ALL = 0x00,
+ HT_IOT_RAFUNC_PEER_1R = 0x01,
+ HT_IOT_RAFUNC_TX_AMSDU = 0x02,
+};
+
+enum rt_ht_capability {
+ RT_HT_CAP_USE_TURBO_AGGR = 0x01,
+ RT_HT_CAP_USE_LONG_PREAMBLE = 0x02,
+ RT_HT_CAP_USE_AMPDU = 0x04,
+ RT_HT_CAP_USE_WOW = 0x8,
+ RT_HT_CAP_USE_SOFTAP = 0x10,
+ RT_HT_CAP_USE_92SE = 0x20,
+};
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c
new file mode 100644
index 000000000..7f103114d
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl819x_HTProc.c
@@ -0,0 +1,919 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtllib.h"
+#include "rtl819x_HT.h"
+u8 MCS_FILTER_ALL[16] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+u8 MCS_FILTER_1SS[16] = {
+ 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+;
+
+u16 MCS_DATA_RATE[2][2][77] = {
+ {{13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234,
+ 260, 39, 78, 117, 234, 312, 351, 390, 52, 104, 156, 208, 312, 416,
+ 468, 520, 0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182,
+ 182, 208, 156, 195, 195, 234, 273, 273, 312, 130, 156, 181, 156,
+ 181, 208, 234, 208, 234, 260, 260, 286, 195, 234, 273, 234, 273,
+ 312, 351, 312, 351, 390, 390, 429},
+ {14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289,
+ 43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520,
+ 578, 0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231,
+ 173, 217, 217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260,
+ 231, 260, 289, 289, 318, 217, 260, 303, 260, 303, 347, 390, 347, 390,
+ 433, 433, 477} },
+ {{27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486,
+ 540, 81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648,
+ 864, 972, 1080, 12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324,
+ 378, 378, 432, 324, 405, 405, 486, 567, 567, 648, 270, 324, 378, 324,
+ 378, 432, 486, 432, 486, 540, 540, 594, 405, 486, 567, 486, 567, 648,
+ 729, 648, 729, 810, 810, 891},
+ {30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540,
+ 600, 90, 180, 270, 360, 540, 720, 810, 900, 120, 240, 360, 480, 720,
+ 960, 1080, 1200, 13, 180, 240, 300, 270, 360, 450, 240, 300, 300, 360,
+ 420, 420, 480, 360, 450, 450, 540, 630, 630, 720, 300, 360, 420, 360,
+ 420, 480, 540, 480, 540, 600, 600, 660, 450, 540, 630, 540, 630, 720,
+ 810, 720, 810, 900, 900, 990} }
+};
+
+static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf};
+
+static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70};
+
+static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e};
+
+static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f};
+
+static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf};
+
+static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc};
+
+static u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e};
+
+static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
+
+static u8 DLINK_ATHEROS_1[3] = {0x00, 0x1c, 0xf0};
+
+static u8 DLINK_ATHEROS_2[3] = {0x00, 0x21, 0x91};
+
+static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
+
+static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
+
+void HTUpdateDefaultSetting(struct rtllib_device *ieee)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+
+ pHTInfo->bAcceptAddbaReq = 1;
+
+ pHTInfo->bRegShortGI20MHz = 1;
+ pHTInfo->bRegShortGI40MHz = 1;
+
+ pHTInfo->bRegBW40MHz = 1;
+
+ if (pHTInfo->bRegBW40MHz)
+ pHTInfo->bRegSuppCCK = 1;
+ else
+ pHTInfo->bRegSuppCCK = true;
+
+ pHTInfo->nAMSDU_MaxSize = 7935UL;
+ pHTInfo->bAMSDU_Support = 0;
+
+ pHTInfo->bAMPDUEnable = 1;
+ pHTInfo->AMPDU_Factor = 2;
+ pHTInfo->MPDU_Density = 0;
+
+ pHTInfo->SelfMimoPs = 3;
+ if (pHTInfo->SelfMimoPs == 2)
+ pHTInfo->SelfMimoPs = 3;
+ ieee->bTxDisableRateFallBack = 0;
+ ieee->bTxUseDriverAssingedRate = 0;
+
+ ieee->bTxEnableFwCalcDur = 1;
+
+ pHTInfo->bRegRT2RTAggregation = 1;
+
+ pHTInfo->bRegRxReorderEnable = 1;
+ pHTInfo->RxReorderWinSize = 64;
+ pHTInfo->RxReorderPendingTime = 30;
+}
+
+u16 HTMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+
+ u8 is40MHz = (pHTInfo->bCurBW40MHz) ? 1 : 0;
+ u8 isShortGI = (pHTInfo->bCurBW40MHz) ?
+ ((pHTInfo->bCurShortGI40MHz) ? 1 : 0) :
+ ((pHTInfo->bCurShortGI20MHz) ? 1 : 0);
+ return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate & 0x7f)];
+}
+
+u16 TxCountToDataRate(struct rtllib_device *ieee, u8 nDataRate)
+{
+ u16 CCKOFDMRate[12] = {0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18,
+ 0x24, 0x30, 0x48, 0x60, 0x6c};
+ u8 is40MHz = 0;
+ u8 isShortGI = 0;
+
+ if (nDataRate < 12)
+ return CCKOFDMRate[nDataRate];
+ if (nDataRate >= 0x10 && nDataRate <= 0x1f) {
+ is40MHz = 0;
+ isShortGI = 0;
+ } else if (nDataRate >= 0x20 && nDataRate <= 0x2f) {
+ is40MHz = 1;
+ isShortGI = 0;
+ } else if (nDataRate >= 0x30 && nDataRate <= 0x3f) {
+ is40MHz = 0;
+ isShortGI = 1;
+ } else if (nDataRate >= 0x40 && nDataRate <= 0x4f) {
+ is40MHz = 1;
+ isShortGI = 1;
+ }
+ return MCS_DATA_RATE[is40MHz][isShortGI][nDataRate&0xf];
+}
+
+bool IsHTHalfNmodeAPs(struct rtllib_device *ieee)
+{
+ bool retValue = false;
+ struct rtllib_network *net = &ieee->current_network;
+
+ if ((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3) == 0) ||
+ (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3) == 0) ||
+ (memcmp(net->bssid, PCI_RALINK, 3) == 0) ||
+ (memcmp(net->bssid, EDIMAX_RALINK, 3) == 0) ||
+ (memcmp(net->bssid, AIRLINK_RALINK, 3) == 0) ||
+ (net->ralink_cap_exist))
+ retValue = true;
+ else if (!memcmp(net->bssid, UNKNOWN_BORADCOM, 3) ||
+ !memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3) ||
+ !memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3) ||
+ (net->broadcom_cap_exist))
+ retValue = true;
+ else if (net->bssht.bdRT2RTAggregation)
+ retValue = true;
+ else
+ retValue = false;
+
+ return retValue;
+}
+
+static void HTIOTPeerDetermine(struct rtllib_device *ieee)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+ struct rtllib_network *net = &ieee->current_network;
+
+ if (net->bssht.bdRT2RTAggregation) {
+ pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK;
+ if (net->bssht.RT2RT_HT_Mode & RT_HT_CAP_USE_92SE)
+ pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK_92SE;
+ if (net->bssht.RT2RT_HT_Mode & RT_HT_CAP_USE_SOFTAP)
+ pHTInfo->IOTPeer = HT_IOT_PEER_92U_SOFTAP;
+ } else if (net->broadcom_cap_exist)
+ pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
+ else if (!memcmp(net->bssid, UNKNOWN_BORADCOM, 3) ||
+ !memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3) ||
+ !memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3))
+ pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
+ else if ((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3) == 0) ||
+ (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3) == 0) ||
+ (memcmp(net->bssid, PCI_RALINK, 3) == 0) ||
+ (memcmp(net->bssid, EDIMAX_RALINK, 3) == 0) ||
+ (memcmp(net->bssid, AIRLINK_RALINK, 3) == 0) ||
+ net->ralink_cap_exist)
+ pHTInfo->IOTPeer = HT_IOT_PEER_RALINK;
+ else if ((net->atheros_cap_exist) ||
+ (memcmp(net->bssid, DLINK_ATHEROS_1, 3) == 0) ||
+ (memcmp(net->bssid, DLINK_ATHEROS_2, 3) == 0))
+ pHTInfo->IOTPeer = HT_IOT_PEER_ATHEROS;
+ else if ((memcmp(net->bssid, CISCO_BROADCOM, 3) == 0) ||
+ net->cisco_cap_exist)
+ pHTInfo->IOTPeer = HT_IOT_PEER_CISCO;
+ else if ((memcmp(net->bssid, LINKSYS_MARVELL_4400N, 3) == 0) ||
+ net->marvell_cap_exist)
+ pHTInfo->IOTPeer = HT_IOT_PEER_MARVELL;
+ else if (net->airgo_cap_exist)
+ pHTInfo->IOTPeer = HT_IOT_PEER_AIRGO;
+ else
+ pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
+
+ RTLLIB_DEBUG(RTLLIB_DL_IOT, "Joseph debug!! IOTPEER: %x\n",
+ pHTInfo->IOTPeer);
+}
+
+static u8 HTIOTActIsDisableMCS14(struct rtllib_device *ieee, u8 *PeerMacAddr)
+{
+ return 0;
+}
+
+
+static bool HTIOTActIsDisableMCS15(struct rtllib_device *ieee)
+{
+ return false;
+}
+
+static bool HTIOTActIsDisableMCSTwoSpatialStream(struct rtllib_device *ieee)
+{
+ return false;
+}
+
+static u8 HTIOTActIsDisableEDCATurbo(struct rtllib_device *ieee, u8 *PeerMacAddr)
+{
+ return false;
+}
+
+static u8 HTIOTActIsMgntUseCCK6M(struct rtllib_device *ieee,
+ struct rtllib_network *network)
+{
+ u8 retValue = 0;
+
+
+ if (ieee->pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)
+ retValue = 1;
+
+ return retValue;
+}
+
+static u8 HTIOTActIsCCDFsync(struct rtllib_device *ieee)
+{
+ u8 retValue = 0;
+
+ if (ieee->pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)
+ retValue = 1;
+ return retValue;
+}
+
+static void HTIOTActDetermineRaFunc(struct rtllib_device *ieee, bool bPeerRx2ss)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+
+ pHTInfo->IOTRaFunc &= HT_IOT_RAFUNC_DISABLE_ALL;
+
+ if (pHTInfo->IOTPeer == HT_IOT_PEER_RALINK && !bPeerRx2ss)
+ pHTInfo->IOTRaFunc |= HT_IOT_RAFUNC_PEER_1R;
+
+ if (pHTInfo->IOTAction & HT_IOT_ACT_AMSDU_ENABLE)
+ pHTInfo->IOTRaFunc |= HT_IOT_RAFUNC_TX_AMSDU;
+
+}
+
+void HTResetIOTSetting(struct rt_hi_throughput *pHTInfo)
+{
+ pHTInfo->IOTAction = 0;
+ pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
+ pHTInfo->IOTRaFunc = 0;
+}
+
+void HTConstructCapabilityElement(struct rtllib_device *ieee, u8 *posHTCap,
+ u8 *len, u8 IsEncrypt, bool bAssoc)
+{
+ struct rt_hi_throughput *pHT = ieee->pHTInfo;
+ struct ht_capab_ele *pCapELE = NULL;
+
+ if ((posHTCap == NULL) || (pHT == NULL)) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "posHTCap or pHTInfo can't be null in HTConstructCapabilityElement()\n");
+ return;
+ }
+ memset(posHTCap, 0, *len);
+
+ if ((bAssoc) && (pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)) {
+ u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
+
+ memcpy(posHTCap, EWC11NHTCap, sizeof(EWC11NHTCap));
+ pCapELE = (struct ht_capab_ele *)&(posHTCap[4]);
+ *len = 30 + 2;
+ } else {
+ pCapELE = (struct ht_capab_ele *)posHTCap;
+ *len = 26 + 2;
+ }
+
+ pCapELE->AdvCoding = 0;
+ if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+ pCapELE->ChlWidth = 0;
+ else
+ pCapELE->ChlWidth = (pHT->bRegBW40MHz ? 1 : 0);
+
+ pCapELE->MimoPwrSave = pHT->SelfMimoPs;
+ pCapELE->GreenField = 0;
+ pCapELE->ShortGI20Mhz = 1;
+ pCapELE->ShortGI40Mhz = 1;
+
+ pCapELE->TxSTBC = 1;
+ pCapELE->RxSTBC = 0;
+ pCapELE->DelayBA = 0;
+ pCapELE->MaxAMSDUSize = (MAX_RECEIVE_BUFFER_SIZE >= 7935) ? 1 : 0;
+ pCapELE->DssCCk = ((pHT->bRegBW40MHz) ? (pHT->bRegSuppCCK ? 1 : 0) : 0);
+ pCapELE->PSMP = 0;
+ pCapELE->LSigTxopProtect = 0;
+
+
+ RTLLIB_DEBUG(RTLLIB_DL_HT,
+ "TX HT cap/info ele BW=%d MaxAMSDUSize:%d DssCCk:%d\n",
+ pCapELE->ChlWidth, pCapELE->MaxAMSDUSize, pCapELE->DssCCk);
+
+ if (IsEncrypt) {
+ pCapELE->MPDUDensity = 7;
+ pCapELE->MaxRxAMPDUFactor = 2;
+ } else {
+ pCapELE->MaxRxAMPDUFactor = 3;
+ pCapELE->MPDUDensity = 0;
+ }
+
+ memcpy(pCapELE->MCS, ieee->Regdot11HTOperationalRateSet, 16);
+ memset(&pCapELE->ExtHTCapInfo, 0, 2);
+ memset(pCapELE->TxBFCap, 0, 4);
+
+ pCapELE->ASCap = 0;
+
+ if (bAssoc) {
+ if (pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS15)
+ pCapELE->MCS[1] &= 0x7f;
+
+ if (pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS14)
+ pCapELE->MCS[1] &= 0xbf;
+
+ if (pHT->IOTAction & HT_IOT_ACT_DISABLE_ALL_2SS)
+ pCapELE->MCS[1] &= 0x00;
+
+ if (pHT->IOTAction & HT_IOT_ACT_DISABLE_RX_40MHZ_SHORT_GI)
+ pCapELE->ShortGI40Mhz = 0;
+
+ if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) {
+ pCapELE->ChlWidth = 0;
+ pCapELE->MCS[1] = 0;
+ }
+ }
+}
+
+void HTConstructInfoElement(struct rtllib_device *ieee, u8 *posHTInfo,
+ u8 *len, u8 IsEncrypt)
+{
+ struct rt_hi_throughput *pHT = ieee->pHTInfo;
+ struct ht_info_ele *pHTInfoEle = (struct ht_info_ele *)posHTInfo;
+
+ if ((posHTInfo == NULL) || (pHTInfoEle == NULL)) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "posHTInfo or pHTInfoEle can't be null in HTConstructInfoElement()\n");
+ return;
+ }
+
+ memset(posHTInfo, 0, *len);
+ if ((ieee->iw_mode == IW_MODE_ADHOC) ||
+ (ieee->iw_mode == IW_MODE_MASTER)) {
+ pHTInfoEle->ControlChl = ieee->current_network.channel;
+ pHTInfoEle->ExtChlOffset = ((pHT->bRegBW40MHz == false) ?
+ HT_EXTCHNL_OFFSET_NO_EXT :
+ (ieee->current_network.channel <= 6)
+ ? HT_EXTCHNL_OFFSET_UPPER :
+ HT_EXTCHNL_OFFSET_LOWER);
+ pHTInfoEle->RecommemdedTxWidth = pHT->bRegBW40MHz;
+ pHTInfoEle->RIFS = 0;
+ pHTInfoEle->PSMPAccessOnly = 0;
+ pHTInfoEle->SrvIntGranularity = 0;
+ pHTInfoEle->OptMode = pHT->CurrentOpMode;
+ pHTInfoEle->NonGFDevPresent = 0;
+ pHTInfoEle->DualBeacon = 0;
+ pHTInfoEle->SecondaryBeacon = 0;
+ pHTInfoEle->LSigTxopProtectFull = 0;
+ pHTInfoEle->PcoActive = 0;
+ pHTInfoEle->PcoPhase = 0;
+
+ memset(pHTInfoEle->BasicMSC, 0, 16);
+
+
+ *len = 22 + 2;
+
+ } else {
+ *len = 0;
+ }
+}
+
+void HTConstructRT2RTAggElement(struct rtllib_device *ieee, u8 *posRT2RTAgg,
+ u8 *len)
+{
+ if (posRT2RTAgg == NULL) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "posRT2RTAgg can't be null in HTConstructRT2RTAggElement()\n");
+ return;
+ }
+ memset(posRT2RTAgg, 0, *len);
+ *posRT2RTAgg++ = 0x00;
+ *posRT2RTAgg++ = 0xe0;
+ *posRT2RTAgg++ = 0x4c;
+ *posRT2RTAgg++ = 0x02;
+ *posRT2RTAgg++ = 0x01;
+
+ *posRT2RTAgg = 0x30;
+
+ if (ieee->bSupportRemoteWakeUp)
+ *posRT2RTAgg |= RT_HT_CAP_USE_WOW;
+
+ *len = 6 + 2;
+}
+
+static u8 HT_PickMCSRate(struct rtllib_device *ieee, u8 *pOperateMCS)
+{
+ u8 i;
+
+ if (pOperateMCS == NULL) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "pOperateMCS can't be null in HT_PickMCSRate()\n");
+ return false;
+ }
+
+ switch (ieee->mode) {
+ case IEEE_A:
+ case IEEE_B:
+ case IEEE_G:
+ for (i = 0; i <= 15; i++)
+ pOperateMCS[i] = 0;
+ break;
+ case IEEE_N_24G:
+ case IEEE_N_5G:
+ pOperateMCS[0] &= RATE_ADPT_1SS_MASK;
+ pOperateMCS[1] &= RATE_ADPT_2SS_MASK;
+ pOperateMCS[3] &= RATE_ADPT_MCS32_MASK;
+ break;
+ default:
+ break;
+
+ }
+
+ return true;
+}
+
+u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
+ u8 *pMCSFilter)
+{
+ u8 i, j;
+ u8 bitMap;
+ u8 mcsRate = 0;
+ u8 availableMcsRate[16];
+
+ if (pMCSRateSet == NULL || pMCSFilter == NULL) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "pMCSRateSet or pMCSFilter can't be null in HTGetHighestMCSRate()\n");
+ return false;
+ }
+ for (i = 0; i < 16; i++)
+ availableMcsRate[i] = pMCSRateSet[i] & pMCSFilter[i];
+
+ for (i = 0; i < 16; i++) {
+ if (availableMcsRate[i] != 0)
+ break;
+ }
+ if (i == 16)
+ return false;
+
+ for (i = 0; i < 16; i++) {
+ if (availableMcsRate[i] != 0) {
+ bitMap = availableMcsRate[i];
+ for (j = 0; j < 8; j++) {
+ if ((bitMap%2) != 0) {
+ if (HTMcsToDataRate(ieee, (8*i+j)) >
+ HTMcsToDataRate(ieee, mcsRate))
+ mcsRate = (8*i+j);
+ }
+ bitMap >>= 1;
+ }
+ }
+ }
+ return mcsRate | 0x80;
+}
+
+u8 HTFilterMCSRate(struct rtllib_device *ieee, u8 *pSupportMCS, u8 *pOperateMCS)
+{
+
+ u8 i;
+
+ for (i = 0; i <= 15; i++)
+ pOperateMCS[i] = ieee->Regdot11TxHTOperationalRateSet[i] &
+ pSupportMCS[i];
+
+ HT_PickMCSRate(ieee, pOperateMCS);
+
+ if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+ pOperateMCS[1] = 0;
+
+ for (i = 2; i <= 15; i++)
+ pOperateMCS[i] = 0;
+
+ return true;
+}
+
+void HTSetConnectBwMode(struct rtllib_device *ieee,
+ enum ht_channel_width Bandwidth,
+ enum ht_extchnl_offset Offset);
+
+void HTOnAssocRsp(struct rtllib_device *ieee)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+ struct ht_capab_ele *pPeerHTCap = NULL;
+ struct ht_info_ele *pPeerHTInfo = NULL;
+ u16 nMaxAMSDUSize = 0;
+ u8 *pMcsFilter = NULL;
+
+ static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
+ static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34};
+
+ if (pHTInfo->bCurrentHTSupport == false) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "<=== HTOnAssocRsp(): HT_DISABLE\n");
+ return;
+ }
+ RTLLIB_DEBUG(RTLLIB_DL_HT, "===> HTOnAssocRsp_wq(): HT_ENABLE\n");
+
+ if (!memcmp(pHTInfo->PeerHTCapBuf, EWC11NHTCap, sizeof(EWC11NHTCap)))
+ pPeerHTCap = (struct ht_capab_ele *)(&pHTInfo->PeerHTCapBuf[4]);
+ else
+ pPeerHTCap = (struct ht_capab_ele *)(pHTInfo->PeerHTCapBuf);
+
+ if (!memcmp(pHTInfo->PeerHTInfoBuf, EWC11NHTInfo, sizeof(EWC11NHTInfo)))
+ pPeerHTInfo = (struct ht_info_ele *)
+ (&pHTInfo->PeerHTInfoBuf[4]);
+ else
+ pPeerHTInfo = (struct ht_info_ele *)(pHTInfo->PeerHTInfoBuf);
+
+ RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA | RTLLIB_DL_HT, pPeerHTCap,
+ sizeof(struct ht_capab_ele));
+ HTSetConnectBwMode(ieee, (enum ht_channel_width)(pPeerHTCap->ChlWidth),
+ (enum ht_extchnl_offset)(pPeerHTInfo->ExtChlOffset));
+ pHTInfo->bCurTxBW40MHz = ((pPeerHTInfo->RecommemdedTxWidth == 1) ?
+ true : false);
+
+ pHTInfo->bCurShortGI20MHz = ((pHTInfo->bRegShortGI20MHz) ?
+ ((pPeerHTCap->ShortGI20Mhz == 1) ?
+ true : false) : false);
+ pHTInfo->bCurShortGI40MHz = ((pHTInfo->bRegShortGI40MHz) ?
+ ((pPeerHTCap->ShortGI40Mhz == 1) ?
+ true : false) : false);
+
+ pHTInfo->bCurSuppCCK = ((pHTInfo->bRegSuppCCK) ?
+ ((pPeerHTCap->DssCCk == 1) ? true :
+ false) : false);
+
+
+ pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
+
+ nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize == 0) ? 3839 : 7935;
+
+ if (pHTInfo->nAMSDU_MaxSize > nMaxAMSDUSize)
+ pHTInfo->nCurrent_AMSDU_MaxSize = nMaxAMSDUSize;
+ else
+ pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
+
+ pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
+ if (ieee->rtllib_ap_sec_type &&
+ (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))) {
+ if ((pHTInfo->IOTPeer == HT_IOT_PEER_ATHEROS) ||
+ (pHTInfo->IOTPeer == HT_IOT_PEER_UNKNOWN))
+ pHTInfo->bCurrentAMPDUEnable = false;
+ }
+
+ if (!pHTInfo->bRegRT2RTAggregation) {
+ if (pHTInfo->AMPDU_Factor > pPeerHTCap->MaxRxAMPDUFactor)
+ pHTInfo->CurrentAMPDUFactor =
+ pPeerHTCap->MaxRxAMPDUFactor;
+ else
+ pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
+
+ } else {
+ if (ieee->current_network.bssht.bdRT2RTAggregation) {
+ if (ieee->pairwise_key_type != KEY_TYPE_NA)
+ pHTInfo->CurrentAMPDUFactor =
+ pPeerHTCap->MaxRxAMPDUFactor;
+ else
+ pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_64K;
+ } else {
+ if (pPeerHTCap->MaxRxAMPDUFactor < HT_AGG_SIZE_32K)
+ pHTInfo->CurrentAMPDUFactor =
+ pPeerHTCap->MaxRxAMPDUFactor;
+ else
+ pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_32K;
+ }
+ }
+ if (pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity)
+ pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
+ else
+ pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity;
+ if (pHTInfo->IOTAction & HT_IOT_ACT_TX_USE_AMSDU_8K) {
+ pHTInfo->bCurrentAMPDUEnable = false;
+ pHTInfo->ForcedAMSDUMode = HT_AGG_FORCE_ENABLE;
+ pHTInfo->ForcedAMSDUMaxSize = 7935;
+ }
+ pHTInfo->bCurRxReorderEnable = pHTInfo->bRegRxReorderEnable;
+
+ if (pPeerHTCap->MCS[0] == 0)
+ pPeerHTCap->MCS[0] = 0xff;
+
+ HTIOTActDetermineRaFunc(ieee, ((pPeerHTCap->MCS[1]) != 0));
+
+ HTFilterMCSRate(ieee, pPeerHTCap->MCS, ieee->dot11HTOperationalRateSet);
+
+ pHTInfo->PeerMimoPs = pPeerHTCap->MimoPwrSave;
+ if (pHTInfo->PeerMimoPs == MIMO_PS_STATIC)
+ pMcsFilter = MCS_FILTER_1SS;
+ else
+ pMcsFilter = MCS_FILTER_ALL;
+ ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee,
+ ieee->dot11HTOperationalRateSet, pMcsFilter);
+ ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate;
+
+ pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
+}
+
+void HTInitializeHTInfo(struct rtllib_device *ieee)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+
+ RTLLIB_DEBUG(RTLLIB_DL_HT, "===========>%s()\n", __func__);
+ pHTInfo->bCurrentHTSupport = false;
+
+ pHTInfo->bCurBW40MHz = false;
+ pHTInfo->bCurTxBW40MHz = false;
+
+ pHTInfo->bCurShortGI20MHz = false;
+ pHTInfo->bCurShortGI40MHz = false;
+ pHTInfo->bForcedShortGI = false;
+
+ pHTInfo->bCurSuppCCK = true;
+
+ pHTInfo->bCurrent_AMSDU_Support = false;
+ pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
+ pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
+ pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
+
+ memset((void *)(&(pHTInfo->SelfHTCap)), 0,
+ sizeof(pHTInfo->SelfHTCap));
+ memset((void *)(&(pHTInfo->SelfHTInfo)), 0,
+ sizeof(pHTInfo->SelfHTInfo));
+ memset((void *)(&(pHTInfo->PeerHTCapBuf)), 0,
+ sizeof(pHTInfo->PeerHTCapBuf));
+ memset((void *)(&(pHTInfo->PeerHTInfoBuf)), 0,
+ sizeof(pHTInfo->PeerHTInfoBuf));
+
+ pHTInfo->bSwBwInProgress = false;
+ pHTInfo->ChnlOp = CHNLOP_NONE;
+
+ pHTInfo->ePeerHTSpecVer = HT_SPEC_VER_IEEE;
+
+ pHTInfo->bCurrentRT2RTAggregation = false;
+ pHTInfo->bCurrentRT2RTLongSlotTime = false;
+ pHTInfo->RT2RT_HT_Mode = (enum rt_ht_capability)0;
+
+ pHTInfo->IOTPeer = 0;
+ pHTInfo->IOTAction = 0;
+ pHTInfo->IOTRaFunc = 0;
+
+ {
+ u8 *RegHTSuppRateSets = &(ieee->RegHTSuppRateSet[0]);
+
+ RegHTSuppRateSets[0] = 0xFF;
+ RegHTSuppRateSets[1] = 0xFF;
+ RegHTSuppRateSets[4] = 0x01;
+ }
+}
+
+void HTInitializeBssDesc(struct bss_ht *pBssHT)
+{
+
+ pBssHT->bdSupportHT = false;
+ memset(pBssHT->bdHTCapBuf, 0, sizeof(pBssHT->bdHTCapBuf));
+ pBssHT->bdHTCapLen = 0;
+ memset(pBssHT->bdHTInfoBuf, 0, sizeof(pBssHT->bdHTInfoBuf));
+ pBssHT->bdHTInfoLen = 0;
+
+ pBssHT->bdHTSpecVer = HT_SPEC_VER_IEEE;
+
+ pBssHT->bdRT2RTAggregation = false;
+ pBssHT->bdRT2RTLongSlotTime = false;
+ pBssHT->RT2RT_HT_Mode = (enum rt_ht_capability)0;
+}
+
+void HTResetSelfAndSavePeerSetting(struct rtllib_device *ieee,
+ struct rtllib_network *pNetwork)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+ u8 bIOTAction = 0;
+
+ RTLLIB_DEBUG(RTLLIB_DL_HT, "==============>%s()\n", __func__);
+ /* unmark bEnableHT flag here is the same reason why unmarked in
+ * function rtllib_softmac_new_net. WB 2008.09.10
+ */
+ if (pNetwork->bssht.bdSupportHT) {
+ pHTInfo->bCurrentHTSupport = true;
+ pHTInfo->ePeerHTSpecVer = pNetwork->bssht.bdHTSpecVer;
+
+ if (pNetwork->bssht.bdHTCapLen > 0 &&
+ pNetwork->bssht.bdHTCapLen <= sizeof(pHTInfo->PeerHTCapBuf))
+ memcpy(pHTInfo->PeerHTCapBuf,
+ pNetwork->bssht.bdHTCapBuf,
+ pNetwork->bssht.bdHTCapLen);
+
+ if (pNetwork->bssht.bdHTInfoLen > 0 &&
+ pNetwork->bssht.bdHTInfoLen <=
+ sizeof(pHTInfo->PeerHTInfoBuf))
+ memcpy(pHTInfo->PeerHTInfoBuf,
+ pNetwork->bssht.bdHTInfoBuf,
+ pNetwork->bssht.bdHTInfoLen);
+
+ if (pHTInfo->bRegRT2RTAggregation) {
+ pHTInfo->bCurrentRT2RTAggregation =
+ pNetwork->bssht.bdRT2RTAggregation;
+ pHTInfo->bCurrentRT2RTLongSlotTime =
+ pNetwork->bssht.bdRT2RTLongSlotTime;
+ pHTInfo->RT2RT_HT_Mode = pNetwork->bssht.RT2RT_HT_Mode;
+ } else {
+ pHTInfo->bCurrentRT2RTAggregation = false;
+ pHTInfo->bCurrentRT2RTLongSlotTime = false;
+ pHTInfo->RT2RT_HT_Mode = (enum rt_ht_capability)0;
+ }
+
+ HTIOTPeerDetermine(ieee);
+
+ pHTInfo->IOTAction = 0;
+ bIOTAction = HTIOTActIsDisableMCS14(ieee, pNetwork->bssid);
+ if (bIOTAction)
+ pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS14;
+
+ bIOTAction = HTIOTActIsDisableMCS15(ieee);
+ if (bIOTAction)
+ pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS15;
+
+ bIOTAction = HTIOTActIsDisableMCSTwoSpatialStream(ieee);
+ if (bIOTAction)
+ pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_ALL_2SS;
+
+
+ bIOTAction = HTIOTActIsDisableEDCATurbo(ieee, pNetwork->bssid);
+ if (bIOTAction)
+ pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_EDCA_TURBO;
+
+ bIOTAction = HTIOTActIsMgntUseCCK6M(ieee, pNetwork);
+ if (bIOTAction)
+ pHTInfo->IOTAction |= HT_IOT_ACT_MGNT_USE_CCK_6M;
+ bIOTAction = HTIOTActIsCCDFsync(ieee);
+ if (bIOTAction)
+ pHTInfo->IOTAction |= HT_IOT_ACT_CDD_FSYNC;
+ } else {
+ pHTInfo->bCurrentHTSupport = false;
+ pHTInfo->bCurrentRT2RTAggregation = false;
+ pHTInfo->bCurrentRT2RTLongSlotTime = false;
+ pHTInfo->RT2RT_HT_Mode = (enum rt_ht_capability)0;
+
+ pHTInfo->IOTAction = 0;
+ pHTInfo->IOTRaFunc = 0;
+ }
+}
+
+void HT_update_self_and_peer_setting(struct rtllib_device *ieee,
+ struct rtllib_network *pNetwork)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+ struct ht_info_ele *pPeerHTInfo =
+ (struct ht_info_ele *)pNetwork->bssht.bdHTInfoBuf;
+
+ if (pHTInfo->bCurrentHTSupport) {
+ if (pNetwork->bssht.bdHTInfoLen != 0)
+ pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
+ }
+}
+EXPORT_SYMBOL(HT_update_self_and_peer_setting);
+
+void HTUseDefaultSetting(struct rtllib_device *ieee)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+
+ if (pHTInfo->bEnableHT) {
+ pHTInfo->bCurrentHTSupport = true;
+ pHTInfo->bCurSuppCCK = pHTInfo->bRegSuppCCK;
+
+ pHTInfo->bCurBW40MHz = pHTInfo->bRegBW40MHz;
+ pHTInfo->bCurShortGI20MHz = pHTInfo->bRegShortGI20MHz;
+
+ pHTInfo->bCurShortGI40MHz = pHTInfo->bRegShortGI40MHz;
+
+ if (ieee->iw_mode == IW_MODE_ADHOC)
+ ieee->current_network.qos_data.active =
+ ieee->current_network.qos_data.supported;
+ pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
+ pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
+
+ pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
+ pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
+
+ pHTInfo->CurrentMPDUDensity = pHTInfo->CurrentMPDUDensity;
+
+ HTFilterMCSRate(ieee, ieee->Regdot11TxHTOperationalRateSet,
+ ieee->dot11HTOperationalRateSet);
+ ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee,
+ ieee->dot11HTOperationalRateSet,
+ MCS_FILTER_ALL);
+ ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate;
+
+ } else {
+ pHTInfo->bCurrentHTSupport = false;
+ }
+}
+
+u8 HTCCheck(struct rtllib_device *ieee, u8 *pFrame)
+{
+ if (ieee->pHTInfo->bCurrentHTSupport) {
+ if ((IsQoSDataFrame(pFrame) && Frame_Order(pFrame)) == 1) {
+ RTLLIB_DEBUG(RTLLIB_DL_HT,
+ "HT CONTROL FILED EXIST!!\n");
+ return true;
+ }
+ }
+ return false;
+}
+
+static void HTSetConnectBwModeCallback(struct rtllib_device *ieee)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+
+ RTLLIB_DEBUG(RTLLIB_DL_HT, "======>%s()\n", __func__);
+ if (pHTInfo->bCurBW40MHz) {
+ if (pHTInfo->CurSTAExtChnlOffset == HT_EXTCHNL_OFFSET_UPPER)
+ ieee->set_chan(ieee->dev,
+ ieee->current_network.channel + 2);
+ else if (pHTInfo->CurSTAExtChnlOffset ==
+ HT_EXTCHNL_OFFSET_LOWER)
+ ieee->set_chan(ieee->dev,
+ ieee->current_network.channel - 2);
+ else
+ ieee->set_chan(ieee->dev,
+ ieee->current_network.channel);
+
+ ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20_40,
+ pHTInfo->CurSTAExtChnlOffset);
+ } else {
+ ieee->set_chan(ieee->dev, ieee->current_network.channel);
+ ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20,
+ HT_EXTCHNL_OFFSET_NO_EXT);
+ }
+
+ pHTInfo->bSwBwInProgress = false;
+}
+
+void HTSetConnectBwMode(struct rtllib_device *ieee,
+ enum ht_channel_width Bandwidth,
+ enum ht_extchnl_offset Offset)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+
+ if (pHTInfo->bRegBW40MHz == false)
+ return;
+
+ if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+ Bandwidth = HT_CHANNEL_WIDTH_20;
+
+ if (pHTInfo->bSwBwInProgress) {
+ pr_info("%s: bSwBwInProgress!!\n", __func__);
+ return;
+ }
+ if (Bandwidth == HT_CHANNEL_WIDTH_20_40) {
+ if (ieee->current_network.channel < 2 &&
+ Offset == HT_EXTCHNL_OFFSET_LOWER)
+ Offset = HT_EXTCHNL_OFFSET_NO_EXT;
+ if (Offset == HT_EXTCHNL_OFFSET_UPPER ||
+ Offset == HT_EXTCHNL_OFFSET_LOWER) {
+ pHTInfo->bCurBW40MHz = true;
+ pHTInfo->CurSTAExtChnlOffset = Offset;
+ } else {
+ pHTInfo->bCurBW40MHz = false;
+ pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
+ }
+ } else {
+ pHTInfo->bCurBW40MHz = false;
+ pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
+ }
+
+ pr_info("%s():pHTInfo->bCurBW40MHz:%x\n", __func__,
+ pHTInfo->bCurBW40MHz);
+
+ pHTInfo->bSwBwInProgress = true;
+
+ HTSetConnectBwModeCallback(ieee);
+}
diff --git a/drivers/staging/rtl8192e/rtl819x_Qos.h b/drivers/staging/rtl8192e/rtl819x_Qos.h
new file mode 100644
index 000000000..55ef7ec33
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl819x_Qos.h
@@ -0,0 +1,389 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef __INC_QOS_TYPE_H
+#define __INC_QOS_TYPE_H
+
+#define BIT0 0x00000001
+#define BIT1 0x00000002
+#define BIT2 0x00000004
+#define BIT3 0x00000008
+#define BIT4 0x00000010
+#define BIT5 0x00000020
+#define BIT6 0x00000040
+#define BIT7 0x00000080
+#define BIT8 0x00000100
+#define BIT9 0x00000200
+#define BIT10 0x00000400
+#define BIT11 0x00000800
+#define BIT12 0x00001000
+#define BIT13 0x00002000
+#define BIT14 0x00004000
+#define BIT15 0x00008000
+#define BIT16 0x00010000
+#define BIT17 0x00020000
+#define BIT18 0x00040000
+#define BIT19 0x00080000
+#define BIT20 0x00100000
+#define BIT21 0x00200000
+#define BIT22 0x00400000
+#define BIT23 0x00800000
+#define BIT24 0x01000000
+#define BIT25 0x02000000
+#define BIT26 0x04000000
+#define BIT27 0x08000000
+#define BIT28 0x10000000
+#define BIT29 0x20000000
+#define BIT30 0x40000000
+#define BIT31 0x80000000
+
+union qos_tsinfo {
+ u8 charData[3];
+ struct {
+ u8 ucTrafficType:1;
+ u8 ucTSID:4;
+ u8 ucDirection:2;
+ u8 ucAccessPolicy:2;
+ u8 ucAggregation:1;
+ u8 ucPSB:1;
+ u8 ucUP:3;
+ u8 ucTSInfoAckPolicy:2;
+ u8 ucSchedule:1;
+ u8 ucReserved:7;
+ } field;
+};
+
+union tspec_body {
+ u8 charData[55];
+
+ struct {
+ union qos_tsinfo TSInfo;
+ u16 NominalMSDUsize;
+ u16 MaxMSDUsize;
+ u32 MinServiceItv;
+ u32 MaxServiceItv;
+ u32 InactivityItv;
+ u32 SuspenItv;
+ u32 ServiceStartTime;
+ u32 MinDataRate;
+ u32 MeanDataRate;
+ u32 PeakDataRate;
+ u32 MaxBurstSize;
+ u32 DelayBound;
+ u32 MinPhyRate;
+ u16 SurplusBandwidthAllowance;
+ u16 MediumTime;
+ } f;
+};
+
+struct wmm_tspec {
+ u8 ID;
+ u8 Length;
+ u8 OUI[3];
+ u8 OUI_Type;
+ u8 OUI_SubType;
+ u8 Version;
+ union tspec_body Body;
+};
+
+struct octet_string {
+ u8 *Octet;
+ u16 Length;
+};
+
+#define MAX_WMMELE_LENGTH 64
+
+#define QOS_MODE u32
+
+#define QOS_DISABLE 0
+#define QOS_WMM 1
+#define QOS_WMMSA 2
+#define QOS_EDCA 4
+#define QOS_HCCA 8
+#define QOS_WMM_UAPSD 16
+
+#define WMM_PARAM_ELE_BODY_LEN 18
+
+#define MAX_STA_TS_COUNT 16
+#define MAX_AP_TS_COUNT 32
+#define QOS_TSTREAM_KEY_SIZE 13
+
+#define WMM_ACTION_CATEGORY_CODE 17
+#define WMM_PARAM_ELE_BODY_LEN 18
+
+#define MAX_TSPEC_TSID 15
+#define SESSION_REJECT_TSID 0xfe
+#define DEFAULT_TSID 0xff
+
+#define ADDTS_TIME_SLOT 100
+
+#define ACM_TIMEOUT 1000
+#define SESSION_REJECT_TIMEOUT 60000
+
+enum ack_policy {
+ eAckPlc0_ACK = 0x00,
+ eAckPlc1_NoACK = 0x01,
+};
+
+
+#define SET_WMM_QOS_INFO_FIELD(_pStart, _val) \
+ WriteEF1Byte(_pStart, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_PARAMETERSET_COUNT(_pStart) \
+ LE_BITS_TO_1BYTE(_pStart, 0, 4)
+#define SET_WMM_QOS_INFO_FIELD_PARAMETERSET_COUNT(_pStart, _val) \
+ SET_BITS_TO_LE_1BYTE(_pStart, 0, 4, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_AP_UAPSD(_pStart) \
+ LE_BITS_TO_1BYTE(_pStart, 7, 1)
+#define SET_WMM_QOS_INFO_FIELD_AP_UAPSD(_pStart, _val) \
+ SET_BITS_TO_LE_1BYTE(_pStart, 7, 1, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_STA_AC_VO_UAPSD(_pStart) \
+ LE_BITS_TO_1BYTE(_pStart, 0, 1)
+#define SET_WMM_QOS_INFO_FIELD_STA_AC_VO_UAPSD(_pStart, _val) \
+ SET_BITS_TO_LE_1BYTE(_pStart, 0, 1, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_STA_AC_VI_UAPSD(_pStart) \
+ LE_BITS_TO_1BYTE(_pStart, 1, 1)
+#define SET_WMM_QOS_INFO_FIELD_STA_AC_VI_UAPSD(_pStart, _val) \
+ SET_BITS_TO_LE_1BYTE(_pStart, 1, 1, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_STA_AC_BE_UAPSD(_pStart) \
+ LE_BITS_TO_1BYTE(_pStart, 2, 1)
+#define SET_WMM_QOS_INFO_FIELD_STA_AC_BE_UAPSD(_pStart, _val) \
+ SET_BITS_TO_LE_1BYTE(_pStart, 2, 1, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_STA_AC_BK_UAPSD(_pStart) \
+ LE_BITS_TO_1BYTE(_pStart, 3, 1)
+#define SET_WMM_QOS_INFO_FIELD_STA_AC_BK_UAPSD(_pStart, _val) \
+ SET_BITS_TO_LE_1BYTE(_pStart, 3, 1, _val)
+
+#define GET_WMM_QOS_INFO_FIELD_STA_MAX_SP_LEN(_pStart) \
+ LE_BITS_TO_1BYTE(_pStart, 5, 2)
+#define SET_WMM_QOS_INFO_FIELD_STA_MAX_SP_LEN(_pStart, _val) \
+ SET_BITS_TO_LE_1BYTE(_pStart, 5, 2, _val)
+
+enum qos_ie_source {
+ QOSIE_SRC_ADDTSREQ,
+ QOSIE_SRC_ADDTSRSP,
+ QOSIE_SRC_REASOCREQ,
+ QOSIE_SRC_REASOCRSP,
+ QOSIE_SRC_DELTS,
+};
+
+
+#define AC_CODING u32
+
+#define AC0_BE 0
+#define AC1_BK 1
+#define AC2_VI 2
+#define AC3_VO 3
+#define AC_MAX 4
+
+
+#define AC_PARAM_SIZE 4
+
+#define WMM_PARAM_ELEMENT_SIZE (8+(4*AC_PARAM_SIZE))
+
+enum qos_ele_subtype {
+ QOSELE_TYPE_INFO = 0x00,
+ QOSELE_TYPE_PARAM = 0x01,
+};
+
+
+enum direction_value {
+ DIR_UP = 0,
+ DIR_DOWN = 1,
+ DIR_DIRECT = 2,
+ DIR_BI_DIR = 3,
+};
+
+enum acm_method {
+ eAcmWay0_SwAndHw = 0,
+ eAcmWay1_HW = 1,
+ eAcmWay2_SW = 2,
+};
+
+
+struct acm {
+ u64 UsedTime;
+ u64 MediumTime;
+ u8 HwAcmCtl;
+};
+
+
+
+#define AC_UAPSD u8
+
+#define GET_VO_UAPSD(_apsd) ((_apsd) & BIT0)
+#define SET_VO_UAPSD(_apsd) ((_apsd) |= BIT0)
+
+#define GET_VI_UAPSD(_apsd) ((_apsd) & BIT1)
+#define SET_VI_UAPSD(_apsd) ((_apsd) |= BIT1)
+
+#define GET_BK_UAPSD(_apsd) ((_apsd) & BIT2)
+#define SET_BK_UAPSD(_apsd) ((_apsd) |= BIT2)
+
+#define GET_BE_UAPSD(_apsd) ((_apsd) & BIT3)
+#define SET_BE_UAPSD(_apsd) ((_apsd) |= BIT3)
+
+union qos_tclas {
+
+ struct _TYPE_GENERAL {
+ u8 Priority;
+ u8 ClassifierType;
+ u8 Mask;
+ } TYPE_GENERAL;
+
+ struct _TYPE0_ETH {
+ u8 Priority;
+ u8 ClassifierType;
+ u8 Mask;
+ u8 SrcAddr[6];
+ u8 DstAddr[6];
+ u16 Type;
+ } TYPE0_ETH;
+
+ struct _TYPE1_IPV4 {
+ u8 Priority;
+ u8 ClassifierType;
+ u8 Mask;
+ u8 Version;
+ u8 SrcIP[4];
+ u8 DstIP[4];
+ u16 SrcPort;
+ u16 DstPort;
+ u8 DSCP;
+ u8 Protocol;
+ u8 Reserved;
+ } TYPE1_IPV4;
+
+ struct _TYPE1_IPV6 {
+ u8 Priority;
+ u8 ClassifierType;
+ u8 Mask;
+ u8 Version;
+ u8 SrcIP[16];
+ u8 DstIP[16];
+ u16 SrcPort;
+ u16 DstPort;
+ u8 FlowLabel[3];
+ } TYPE1_IPV6;
+
+ struct _TYPE2_8021Q {
+ u8 Priority;
+ u8 ClassifierType;
+ u8 Mask;
+ u16 TagType;
+ } TYPE2_8021Q;
+};
+
+struct qos_tstream {
+
+ bool bUsed;
+ u16 MsduLifetime;
+ bool bEstablishing;
+ u8 TimeSlotCount;
+ u8 DialogToken;
+ struct wmm_tspec TSpec;
+ struct wmm_tspec OutStandingTSpec;
+ u8 NominalPhyRate;
+};
+
+struct sta_qos {
+ u8 WMMIEBuf[MAX_WMMELE_LENGTH];
+ u8 *WMMIE;
+
+ QOS_MODE QosCapability;
+ QOS_MODE CurrentQosMode;
+
+ AC_UAPSD b4ac_Uapsd;
+ AC_UAPSD Curr4acUapsd;
+ u8 bInServicePeriod;
+ u8 MaxSPLength;
+ int NumBcnBeforeTrigger;
+
+ u8 *pWMMInfoEle;
+ u8 WMMParamEle[WMM_PARAM_ELEMENT_SIZE];
+
+ struct acm acm[4];
+ enum acm_method AcmMethod;
+
+ struct qos_tstream StaTsArray[MAX_STA_TS_COUNT];
+ u8 DialogToken;
+ struct wmm_tspec TSpec;
+
+ u8 QBssWirelessMode;
+
+ bool bNoAck;
+
+ bool bEnableRxImmBA;
+
+};
+
+#define QBSS_LOAD_SIZE 5
+
+struct bss_qos {
+ QOS_MODE bdQoSMode;
+ u8 bdWMMIEBuf[MAX_WMMELE_LENGTH];
+ struct octet_string bdWMMIE;
+
+ enum qos_ele_subtype EleSubType;
+
+ u8 *pWMMInfoEle;
+ u8 *pWMMParamEle;
+
+ u8 QBssLoad[QBSS_LOAD_SIZE];
+ bool bQBssLoadValid;
+};
+
+#define IsACValid(ac) ((ac >= 0 && ac <= 7) ? true : false)
+
+
+union aci_aifsn {
+ u8 charData;
+
+ struct {
+ u8 AIFSN:4;
+ u8 acm:1;
+ u8 ACI:2;
+ u8 Reserved:1;
+ } f;
+};
+
+union ecw {
+ u8 charData;
+ struct {
+ u8 ECWmin:4;
+ u8 ECWmax:4;
+ } f;
+};
+
+union ac_param {
+ u32 longData;
+ u8 charData[4];
+
+ struct {
+ union aci_aifsn AciAifsn;
+ union ecw Ecw;
+ u16 TXOPLimit;
+ } f;
+};
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl819x_TS.h b/drivers/staging/rtl8192e/rtl819x_TS.h
new file mode 100644
index 000000000..8601b1ad2
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl819x_TS.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _TSTYPE_H_
+#define _TSTYPE_H_
+#include "rtl819x_Qos.h"
+#define TS_SETUP_TIMEOUT 60
+#define TS_INACT_TIMEOUT 60
+#define TS_ADDBA_DELAY 60
+
+#define TOTAL_TS_NUM 16
+#define TCLAS_NUM 4
+
+enum tr_select {
+ TX_DIR = 0,
+ RX_DIR = 1,
+};
+
+struct ts_common_info {
+ struct list_head List;
+ struct timer_list SetupTimer;
+ struct timer_list InactTimer;
+ u8 Addr[6];
+ union tspec_body TSpec;
+ union qos_tclas TClass[TCLAS_NUM];
+ u8 TClasProc;
+ u8 TClasNum;
+};
+
+struct tx_ts_record {
+ struct ts_common_info TsCommonInfo;
+ u16 TxCurSeq;
+ struct ba_record TxPendingBARecord;
+ struct ba_record TxAdmittedBARecord;
+ u8 bAddBaReqInProgress;
+ u8 bAddBaReqDelayed;
+ u8 bUsingBa;
+ u8 bDisable_AddBa;
+ struct timer_list TsAddBaTimer;
+ u8 num;
+};
+
+struct rx_ts_record {
+ struct ts_common_info TsCommonInfo;
+ u16 RxIndicateSeq;
+ u16 RxTimeoutIndicateSeq;
+ struct list_head RxPendingPktList;
+ struct timer_list RxPktPendingTimer;
+ struct ba_record RxAdmittedBARecord;
+ u16 RxLastSeqNum;
+ u8 RxLastFragNum;
+ u8 num;
+};
+
+void _setup_timer(struct timer_list *, void *, unsigned long);
+
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c
new file mode 100644
index 000000000..7d77d0562
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtl819x_TSProc.c
@@ -0,0 +1,554 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#include "rtllib.h"
+#include <linux/etherdevice.h>
+#include "rtl819x_TS.h"
+
+static void TsSetupTimeOut(unsigned long data)
+{
+}
+
+static void TsInactTimeout(unsigned long data)
+{
+}
+
+static void RxPktPendingTimeout(unsigned long data)
+{
+ struct rx_ts_record *pRxTs = (struct rx_ts_record *)data;
+ struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device,
+ RxTsRecord[pRxTs->num]);
+
+ struct rx_reorder_entry *pReorderEntry = NULL;
+
+ unsigned long flags = 0;
+ u8 index = 0;
+ bool bPktInBuf = false;
+
+ spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
+ if (pRxTs->RxTimeoutIndicateSeq != 0xffff) {
+ while (!list_empty(&pRxTs->RxPendingPktList)) {
+ pReorderEntry = (struct rx_reorder_entry *)
+ list_entry(pRxTs->RxPendingPktList.prev,
+ struct rx_reorder_entry, List);
+ if (index == 0)
+ pRxTs->RxIndicateSeq = pReorderEntry->SeqNum;
+
+ if (SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) ||
+ SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq)) {
+ list_del_init(&pReorderEntry->List);
+
+ if (SN_EQUAL(pReorderEntry->SeqNum,
+ pRxTs->RxIndicateSeq))
+ pRxTs->RxIndicateSeq =
+ (pRxTs->RxIndicateSeq + 1) % 4096;
+
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER,
+ "%s(): Indicate SeqNum: %d\n",
+ __func__, pReorderEntry->SeqNum);
+ ieee->stats_IndicateArray[index] =
+ pReorderEntry->prxb;
+ index++;
+
+ list_add_tail(&pReorderEntry->List,
+ &ieee->RxReorder_Unused_List);
+ } else {
+ bPktInBuf = true;
+ break;
+ }
+ }
+ }
+
+ if (index > 0) {
+ pRxTs->RxTimeoutIndicateSeq = 0xffff;
+
+ if (index > REORDER_WIN_SIZE) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "RxReorderIndicatePacket(): Rx Reorder struct buffer full!!\n");
+ spin_unlock_irqrestore(&(ieee->reorder_spinlock),
+ flags);
+ return;
+ }
+ rtllib_indicate_packets(ieee, ieee->stats_IndicateArray, index);
+ bPktInBuf = false;
+ }
+
+ if (bPktInBuf && (pRxTs->RxTimeoutIndicateSeq == 0xffff)) {
+ pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq;
+ mod_timer(&pRxTs->RxPktPendingTimer, jiffies +
+ msecs_to_jiffies(ieee->pHTInfo->RxReorderPendingTime));
+ }
+ spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+}
+
+static void TsAddBaProcess(unsigned long data)
+{
+ struct tx_ts_record *pTxTs = (struct tx_ts_record *)data;
+ u8 num = pTxTs->num;
+ struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device,
+ TxTsRecord[num]);
+
+ TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
+ RTLLIB_DEBUG(RTLLIB_DL_BA,
+ "TsAddBaProcess(): ADDBA Req is started!!\n");
+}
+
+static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo)
+{
+ memset(pTsCommonInfo->Addr, 0, 6);
+ memset(&pTsCommonInfo->TSpec, 0, sizeof(union tspec_body));
+ memset(&pTsCommonInfo->TClass, 0, sizeof(union qos_tclas)*TCLAS_NUM);
+ pTsCommonInfo->TClasProc = 0;
+ pTsCommonInfo->TClasNum = 0;
+}
+
+static void ResetTxTsEntry(struct tx_ts_record *pTS)
+{
+ ResetTsCommonInfo(&pTS->TsCommonInfo);
+ pTS->TxCurSeq = 0;
+ pTS->bAddBaReqInProgress = false;
+ pTS->bAddBaReqDelayed = false;
+ pTS->bUsingBa = false;
+ pTS->bDisable_AddBa = false;
+ ResetBaEntry(&pTS->TxAdmittedBARecord);
+ ResetBaEntry(&pTS->TxPendingBARecord);
+}
+
+static void ResetRxTsEntry(struct rx_ts_record *pTS)
+{
+ ResetTsCommonInfo(&pTS->TsCommonInfo);
+ pTS->RxIndicateSeq = 0xffff;
+ pTS->RxTimeoutIndicateSeq = 0xffff;
+ ResetBaEntry(&pTS->RxAdmittedBARecord);
+}
+
+void TSInitialize(struct rtllib_device *ieee)
+{
+ struct tx_ts_record *pTxTS = ieee->TxTsRecord;
+ struct rx_ts_record *pRxTS = ieee->RxTsRecord;
+ struct rx_reorder_entry *pRxReorderEntry = ieee->RxReorderEntry;
+ u8 count = 0;
+
+ RTLLIB_DEBUG(RTLLIB_DL_TS, "==========>%s()\n", __func__);
+ INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List);
+ INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
+ INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
+
+ for (count = 0; count < TOTAL_TS_NUM; count++) {
+ pTxTS->num = count;
+ _setup_timer(&pTxTS->TsCommonInfo.SetupTimer,
+ TsSetupTimeOut,
+ (unsigned long) pTxTS);
+
+ _setup_timer(&pTxTS->TsCommonInfo.InactTimer,
+ TsInactTimeout,
+ (unsigned long) pTxTS);
+
+ _setup_timer(&pTxTS->TsAddBaTimer,
+ TsAddBaProcess,
+ (unsigned long) pTxTS);
+
+ _setup_timer(&pTxTS->TxPendingBARecord.Timer,
+ BaSetupTimeOut,
+ (unsigned long) pTxTS);
+ _setup_timer(&pTxTS->TxAdmittedBARecord.Timer,
+ TxBaInactTimeout,
+ (unsigned long) pTxTS);
+
+ ResetTxTsEntry(pTxTS);
+ list_add_tail(&pTxTS->TsCommonInfo.List,
+ &ieee->Tx_TS_Unused_List);
+ pTxTS++;
+ }
+
+ INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
+ INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
+ INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
+ for (count = 0; count < TOTAL_TS_NUM; count++) {
+ pRxTS->num = count;
+ INIT_LIST_HEAD(&pRxTS->RxPendingPktList);
+
+ _setup_timer(&pRxTS->TsCommonInfo.SetupTimer,
+ TsSetupTimeOut,
+ (unsigned long) pRxTS);
+
+ _setup_timer(&pRxTS->TsCommonInfo.InactTimer,
+ TsInactTimeout,
+ (unsigned long) pRxTS);
+
+ _setup_timer(&pRxTS->RxAdmittedBARecord.Timer,
+ RxBaInactTimeout,
+ (unsigned long) pRxTS);
+
+ _setup_timer(&pRxTS->RxPktPendingTimer,
+ RxPktPendingTimeout,
+ (unsigned long) pRxTS);
+
+ ResetRxTsEntry(pRxTS);
+ list_add_tail(&pRxTS->TsCommonInfo.List,
+ &ieee->Rx_TS_Unused_List);
+ pRxTS++;
+ }
+ INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
+ for (count = 0; count < REORDER_ENTRY_NUM; count++) {
+ list_add_tail(&pRxReorderEntry->List,
+ &ieee->RxReorder_Unused_List);
+ if (count == (REORDER_ENTRY_NUM-1))
+ break;
+ pRxReorderEntry = &ieee->RxReorderEntry[count+1];
+ }
+
+}
+
+static void AdmitTS(struct rtllib_device *ieee,
+ struct ts_common_info *pTsCommonInfo, u32 InactTime)
+{
+ del_timer_sync(&pTsCommonInfo->SetupTimer);
+ del_timer_sync(&pTsCommonInfo->InactTimer);
+
+ if (InactTime != 0)
+ mod_timer(&pTsCommonInfo->InactTimer, jiffies +
+ msecs_to_jiffies(InactTime));
+}
+
+static struct ts_common_info *SearchAdmitTRStream(struct rtllib_device *ieee,
+ u8 *Addr, u8 TID,
+ enum tr_select TxRxSelect)
+{
+ u8 dir;
+ bool search_dir[4] = {0};
+ struct list_head *psearch_list;
+ struct ts_common_info *pRet = NULL;
+
+ if (ieee->iw_mode == IW_MODE_MASTER) {
+ if (TxRxSelect == TX_DIR) {
+ search_dir[DIR_DOWN] = true;
+ search_dir[DIR_BI_DIR] = true;
+ } else {
+ search_dir[DIR_UP] = true;
+ search_dir[DIR_BI_DIR] = true;
+ }
+ } else if (ieee->iw_mode == IW_MODE_ADHOC) {
+ if (TxRxSelect == TX_DIR)
+ search_dir[DIR_UP] = true;
+ else
+ search_dir[DIR_DOWN] = true;
+ } else {
+ if (TxRxSelect == TX_DIR) {
+ search_dir[DIR_UP] = true;
+ search_dir[DIR_BI_DIR] = true;
+ search_dir[DIR_DIRECT] = true;
+ } else {
+ search_dir[DIR_DOWN] = true;
+ search_dir[DIR_BI_DIR] = true;
+ search_dir[DIR_DIRECT] = true;
+ }
+ }
+
+ if (TxRxSelect == TX_DIR)
+ psearch_list = &ieee->Tx_TS_Admit_List;
+ else
+ psearch_list = &ieee->Rx_TS_Admit_List;
+
+ for (dir = 0; dir <= DIR_BI_DIR; dir++) {
+ if (!search_dir[dir])
+ continue;
+ list_for_each_entry(pRet, psearch_list, List) {
+ if (memcmp(pRet->Addr, Addr, 6) == 0)
+ if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
+ if (pRet->TSpec.f.TSInfo.field.ucDirection == dir)
+ break;
+
+ }
+ if (&pRet->List != psearch_list)
+ break;
+ }
+
+ if (pRet && &pRet->List != psearch_list)
+ return pRet;
+ return NULL;
+}
+
+static void MakeTSEntry(struct ts_common_info *pTsCommonInfo, u8 *Addr,
+ union tspec_body *pTSPEC, union qos_tclas *pTCLAS,
+ u8 TCLAS_Num, u8 TCLAS_Proc)
+{
+ u8 count;
+
+ if (pTsCommonInfo == NULL)
+ return;
+
+ memcpy(pTsCommonInfo->Addr, Addr, 6);
+
+ if (pTSPEC != NULL)
+ memcpy((u8 *)(&(pTsCommonInfo->TSpec)), (u8 *)pTSPEC,
+ sizeof(union tspec_body));
+
+ for (count = 0; count < TCLAS_Num; count++)
+ memcpy((u8 *)(&(pTsCommonInfo->TClass[count])),
+ (u8 *)pTCLAS, sizeof(union qos_tclas));
+
+ pTsCommonInfo->TClasProc = TCLAS_Proc;
+ pTsCommonInfo->TClasNum = TCLAS_Num;
+}
+
+bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS,
+ u8 *Addr, u8 TID, enum tr_select TxRxSelect, bool bAddNewTs)
+{
+ u8 UP = 0;
+ union tspec_body TSpec;
+ union qos_tsinfo *pTSInfo = &TSpec.f.TSInfo;
+ struct list_head *pUnusedList;
+ struct list_head *pAddmitList;
+ enum direction_value Dir;
+
+ if (is_multicast_ether_addr(Addr)) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "ERR! get TS for Broadcast or Multicast\n");
+ return false;
+ }
+ if (ieee->current_network.qos_data.supported == 0) {
+ UP = 0;
+ } else {
+ if (!IsACValid(TID)) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "ERR! in %s(), TID(%d) is not valid\n",
+ __func__, TID);
+ return false;
+ }
+
+ switch (TID) {
+ case 0:
+ case 3:
+ UP = 0;
+ break;
+ case 1:
+ case 2:
+ UP = 2;
+ break;
+ case 4:
+ case 5:
+ UP = 5;
+ break;
+ case 6:
+ case 7:
+ UP = 7;
+ break;
+ }
+ }
+
+ *ppTS = SearchAdmitTRStream(ieee, Addr, UP, TxRxSelect);
+ if (*ppTS != NULL)
+ return true;
+
+ if (!bAddNewTs) {
+ RTLLIB_DEBUG(RTLLIB_DL_TS,
+ "add new TS failed(tid:%d)\n", UP);
+ return false;
+ }
+
+ pUnusedList = (TxRxSelect == TX_DIR) ?
+ (&ieee->Tx_TS_Unused_List) :
+ (&ieee->Rx_TS_Unused_List);
+
+ pAddmitList = (TxRxSelect == TX_DIR) ?
+ (&ieee->Tx_TS_Admit_List) :
+ (&ieee->Rx_TS_Admit_List);
+
+ Dir = (ieee->iw_mode == IW_MODE_MASTER) ?
+ ((TxRxSelect == TX_DIR) ? DIR_DOWN : DIR_UP) :
+ ((TxRxSelect == TX_DIR) ? DIR_UP : DIR_DOWN);
+
+ RTLLIB_DEBUG(RTLLIB_DL_TS, "to add Ts\n");
+ if (!list_empty(pUnusedList)) {
+ (*ppTS) = list_entry(pUnusedList->next,
+ struct ts_common_info, List);
+ list_del_init(&(*ppTS)->List);
+ if (TxRxSelect == TX_DIR) {
+ struct tx_ts_record *tmp =
+ container_of(*ppTS,
+ struct tx_ts_record,
+ TsCommonInfo);
+ ResetTxTsEntry(tmp);
+ } else {
+ struct rx_ts_record *tmp =
+ container_of(*ppTS,
+ struct rx_ts_record,
+ TsCommonInfo);
+ ResetRxTsEntry(tmp);
+ }
+
+ RTLLIB_DEBUG(RTLLIB_DL_TS,
+ "to init current TS, UP:%d, Dir:%d, addr: %pM ppTs=%p\n",
+ UP, Dir, Addr, *ppTS);
+ pTSInfo->field.ucTrafficType = 0;
+ pTSInfo->field.ucTSID = UP;
+ pTSInfo->field.ucDirection = Dir;
+ pTSInfo->field.ucAccessPolicy = 1;
+ pTSInfo->field.ucAggregation = 0;
+ pTSInfo->field.ucPSB = 0;
+ pTSInfo->field.ucUP = UP;
+ pTSInfo->field.ucTSInfoAckPolicy = 0;
+ pTSInfo->field.ucSchedule = 0;
+
+ MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
+ AdmitTS(ieee, *ppTS, 0);
+ list_add_tail(&((*ppTS)->List), pAddmitList);
+
+ return true;
+ }
+
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "ERR!!in function %s() There is not enough dir=%d(0=up down=1) TS record to be used!!",
+ __func__, Dir);
+ return false;
+}
+
+static void RemoveTsEntry(struct rtllib_device *ieee, struct ts_common_info *pTs,
+ enum tr_select TxRxSelect)
+{
+ del_timer_sync(&pTs->SetupTimer);
+ del_timer_sync(&pTs->InactTimer);
+ TsInitDelBA(ieee, pTs, TxRxSelect);
+
+ if (TxRxSelect == RX_DIR) {
+ struct rx_reorder_entry *pRxReorderEntry;
+ struct rx_ts_record *pRxTS = (struct rx_ts_record *)pTs;
+
+ if (timer_pending(&pRxTS->RxPktPendingTimer))
+ del_timer_sync(&pRxTS->RxPktPendingTimer);
+
+ while (!list_empty(&pRxTS->RxPendingPktList)) {
+ pRxReorderEntry = (struct rx_reorder_entry *)
+ list_entry(pRxTS->RxPendingPktList.prev,
+ struct rx_reorder_entry, List);
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER,
+ "%s(): Delete SeqNum %d!\n", __func__,
+ pRxReorderEntry->SeqNum);
+ list_del_init(&pRxReorderEntry->List);
+ {
+ int i = 0;
+ struct rtllib_rxb *prxb = pRxReorderEntry->prxb;
+
+ if (unlikely(!prxb))
+ return;
+ for (i = 0; i < prxb->nr_subframes; i++)
+ dev_kfree_skb(prxb->subframes[i]);
+ kfree(prxb);
+ prxb = NULL;
+ }
+ list_add_tail(&pRxReorderEntry->List,
+ &ieee->RxReorder_Unused_List);
+ }
+ } else {
+ struct tx_ts_record *pTxTS = (struct tx_ts_record *)pTs;
+
+ del_timer_sync(&pTxTS->TsAddBaTimer);
+ }
+}
+
+void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr)
+{
+ struct ts_common_info *pTS, *pTmpTS;
+
+ netdev_info(ieee->dev, "===========>RemovePeerTS, %pM\n", Addr);
+
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) {
+ if (memcmp(pTS->Addr, Addr, 6) == 0) {
+ RemoveTsEntry(ieee, pTS, TX_DIR);
+ list_del_init(&pTS->List);
+ list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
+ }
+ }
+
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) {
+ if (memcmp(pTS->Addr, Addr, 6) == 0) {
+ netdev_info(ieee->dev,
+ "====>remove Tx_TS_admin_list\n");
+ RemoveTsEntry(ieee, pTS, TX_DIR);
+ list_del_init(&pTS->List);
+ list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
+ }
+ }
+
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) {
+ if (memcmp(pTS->Addr, Addr, 6) == 0) {
+ RemoveTsEntry(ieee, pTS, RX_DIR);
+ list_del_init(&pTS->List);
+ list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
+ }
+ }
+
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) {
+ if (memcmp(pTS->Addr, Addr, 6) == 0) {
+ RemoveTsEntry(ieee, pTS, RX_DIR);
+ list_del_init(&pTS->List);
+ list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
+ }
+ }
+}
+EXPORT_SYMBOL(RemovePeerTS);
+
+void RemoveAllTS(struct rtllib_device *ieee)
+{
+ struct ts_common_info *pTS, *pTmpTS;
+
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) {
+ RemoveTsEntry(ieee, pTS, TX_DIR);
+ list_del_init(&pTS->List);
+ list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
+ }
+
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) {
+ RemoveTsEntry(ieee, pTS, TX_DIR);
+ list_del_init(&pTS->List);
+ list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
+ }
+
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) {
+ RemoveTsEntry(ieee, pTS, RX_DIR);
+ list_del_init(&pTS->List);
+ list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
+ }
+
+ list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) {
+ RemoveTsEntry(ieee, pTS, RX_DIR);
+ list_del_init(&pTS->List);
+ list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
+ }
+}
+
+void TsStartAddBaProcess(struct rtllib_device *ieee, struct tx_ts_record *pTxTS)
+{
+ if (pTxTS->bAddBaReqInProgress == false) {
+ pTxTS->bAddBaReqInProgress = true;
+
+ if (pTxTS->bAddBaReqDelayed) {
+ RTLLIB_DEBUG(RTLLIB_DL_BA,
+ "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n");
+ mod_timer(&pTxTS->TsAddBaTimer, jiffies +
+ msecs_to_jiffies(TS_ADDBA_DELAY));
+ } else {
+ RTLLIB_DEBUG(RTLLIB_DL_BA,
+ "TsStartAddBaProcess(): Immediately Start ADDBA now!!\n");
+ mod_timer(&pTxTS->TsAddBaTimer, jiffies+10);
+ }
+ } else
+ RTLLIB_DEBUG(RTLLIB_DL_BA, "%s()==>BA timer is already added\n",
+ __func__);
+}
diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h
new file mode 100644
index 000000000..3c8b708df
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib.h
@@ -0,0 +1,2975 @@
+/*
+ * Merged with mainline rtllib.h in Aug 2004. Original ieee802_11
+ * remains copyright by the original authors
+ *
+ * Portions of the merged code are based on Host AP (software wireless
+ * LAN access point) driver for Intersil Prism2/2.5/3.
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * Adaption to a generic IEEE 802.11 stack by James Ketrenos
+ * <jketreno@linux.intel.com>
+ * Copyright (c) 2004, Intel Corporation
+ *
+ * Modified for Realtek's wi-fi cards by Andrea Merello
+ * <andrea.merello@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+#ifndef RTLLIB_H
+#define RTLLIB_H
+#include <linux/if_ether.h> /* ETH_ALEN */
+#include <linux/kernel.h> /* ARRAY_SIZE */
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
+
+#include <linux/delay.h>
+#include <linux/wireless.h>
+
+#include "rtllib_debug.h"
+#include "rtl819x_HT.h"
+#include "rtl819x_BA.h"
+#include "rtl819x_TS.h"
+
+#include <linux/netdevice.h>
+#include <linux/if_arp.h> /* ARPHRD_ETHER */
+#include <net/lib80211.h>
+
+#define MAX_PRECMD_CNT 16
+#define MAX_RFDEPENDCMD_CNT 16
+#define MAX_POSTCMD_CNT 16
+
+#ifndef WIRELESS_SPY
+#define WIRELESS_SPY
+#endif
+#include <net/iw_handler.h>
+
+#ifndef IW_MODE_MONITOR
+#define IW_MODE_MONITOR 6
+#endif
+
+#ifndef IWEVCUSTOM
+#define IWEVCUSTOM 0x8c02
+#endif
+
+#ifndef IW_CUSTOM_MAX
+/* Max number of char in custom event - use multiple of them if needed */
+#define IW_CUSTOM_MAX 256 /* In bytes */
+#endif
+
+#define skb_tail_pointer_rsl(skb) skb_tail_pointer(skb)
+
+#define queue_delayed_work_rsl(x, y, z) queue_delayed_work(x, y, z)
+#define INIT_DELAYED_WORK_RSL(x, y, z) INIT_DELAYED_WORK(x, y)
+
+#define queue_work_rsl(x, y) queue_work(x, y)
+#define INIT_WORK_RSL(x, y, z) INIT_WORK(x, y)
+
+#define container_of_work_rsl(x, y, z) container_of(x, y, z)
+#define container_of_dwork_rsl(x, y, z) \
+ container_of(container_of(x, struct delayed_work, work), y, z)
+
+#define iwe_stream_add_event_rsl(info, start, stop, iwe, len) \
+ iwe_stream_add_event(info, start, stop, iwe, len)
+
+#define iwe_stream_add_point_rsl(info, start, stop, iwe, p) \
+ iwe_stream_add_point(info, start, stop, iwe, p)
+
+#define usb_alloc_urb_rsl(x, y) usb_alloc_urb(x, y)
+#define usb_submit_urb_rsl(x, y) usb_submit_urb(x, y)
+
+static inline void *netdev_priv_rsl(struct net_device *dev)
+{
+ return netdev_priv(dev);
+}
+
+#define KEY_TYPE_NA 0x0
+#define KEY_TYPE_WEP40 0x1
+#define KEY_TYPE_TKIP 0x2
+#define KEY_TYPE_CCMP 0x4
+#define KEY_TYPE_WEP104 0x5
+/* added for rtl819x tx procedure */
+#define MAX_QUEUE_SIZE 0x10
+
+#define BK_QUEUE 0
+#define BE_QUEUE 1
+#define VI_QUEUE 2
+#define VO_QUEUE 3
+#define HCCA_QUEUE 4
+#define TXCMD_QUEUE 5
+#define MGNT_QUEUE 6
+#define HIGH_QUEUE 7
+#define BEACON_QUEUE 8
+
+#define LOW_QUEUE BE_QUEUE
+#define NORMAL_QUEUE MGNT_QUEUE
+
+#ifndef IW_MODE_MESH
+#define IW_MODE_MESH 7
+#endif
+#define AMSDU_SUBHEADER_LEN 14
+#define SWRF_TIMEOUT 50
+
+#define IE_CISCO_FLAG_POSITION 0x08
+#define SUPPORT_CKIP_MIC 0x08
+#define SUPPORT_CKIP_PK 0x10
+#define RT_RF_OFF_LEVL_ASPM BIT0
+#define RT_RF_OFF_LEVL_CLK_REQ BIT1
+#define RT_RF_OFF_LEVL_PCI_D3 BIT2
+#define RT_RF_OFF_LEVL_HALT_NIC BIT3
+#define RT_RF_OFF_LEVL_FREE_FW BIT4
+#define RT_RF_OFF_LEVL_FW_32K BIT5
+#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT6
+#define RT_RF_LPS_DISALBE_2R BIT30
+#define RT_RF_LPS_LEVEL_ASPM BIT31
+#define RT_IN_PS_LEVEL(pPSC, _PS_FLAG) \
+ ((pPSC->CurPsLevel & _PS_FLAG) ? true : false)
+#define RT_CLEAR_PS_LEVEL(pPSC, _PS_FLAG) \
+ (pPSC->CurPsLevel &= (~(_PS_FLAG)))
+#define RT_SET_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel |= _PS_FLAG)
+
+/* defined for skb cb field */
+/* At most 28 byte */
+struct cb_desc {
+ /* Tx Desc Related flags (8-9) */
+ u8 bLastIniPkt:1;
+ u8 bCmdOrInit:1;
+ u8 bFirstSeg:1;
+ u8 bLastSeg:1;
+ u8 bEncrypt:1;
+ u8 bTxDisableRateFallBack:1;
+ u8 bTxUseDriverAssingedRate:1;
+ u8 bHwSec:1;
+
+ u8 nStuckCount;
+
+ /* Tx Firmware Related flags (10-11)*/
+ u8 bCTSEnable:1;
+ u8 bRTSEnable:1;
+ u8 bUseShortGI:1;
+ u8 bUseShortPreamble:1;
+ u8 bTxEnableFwCalcDur:1;
+ u8 bAMPDUEnable:1;
+ u8 bRTSSTBC:1;
+ u8 RTSSC:1;
+
+ u8 bRTSBW:1;
+ u8 bPacketBW:1;
+ u8 bRTSUseShortPreamble:1;
+ u8 bRTSUseShortGI:1;
+ u8 bMulticast:1;
+ u8 bBroadcast:1;
+ u8 drv_agg_enable:1;
+ u8 reserved2:1;
+
+ /* Tx Desc related element(12-19) */
+ u8 rata_index;
+ u8 queue_index;
+ u16 txbuf_size;
+ u8 RATRIndex;
+ u8 bAMSDU:1;
+ u8 bFromAggrQ:1;
+ u8 reserved6:6;
+ u8 macId;
+ u8 priority;
+
+ /* Tx firmware related element(20-27) */
+ u8 data_rate;
+ u8 rts_rate;
+ u8 ampdu_factor;
+ u8 ampdu_density;
+ u8 DrvAggrNum;
+ u8 bdhcp;
+ u16 pkt_size;
+ u8 bIsSpecialDataFrame;
+
+ u8 bBTTxPacket;
+ u8 bIsBTProbRsp;
+};
+
+enum sw_chnl_cmd_id {
+ CmdID_End,
+ CmdID_SetTxPowerLevel,
+ CmdID_BBRegWrite10,
+ CmdID_WritePortUlong,
+ CmdID_WritePortUshort,
+ CmdID_WritePortUchar,
+ CmdID_RF_WriteReg,
+};
+
+struct sw_chnl_cmd {
+ enum sw_chnl_cmd_id CmdID;
+ u32 Para1;
+ u32 Para2;
+ u32 msDelay;
+} __packed;
+
+/*--------------------------Define -------------------------------------------*/
+#define MGN_1M 0x02
+#define MGN_2M 0x04
+#define MGN_5_5M 0x0b
+#define MGN_11M 0x16
+
+#define MGN_6M 0x0c
+#define MGN_9M 0x12
+#define MGN_12M 0x18
+#define MGN_18M 0x24
+#define MGN_24M 0x30
+#define MGN_36M 0x48
+#define MGN_48M 0x60
+#define MGN_54M 0x6c
+
+#define MGN_MCS0 0x80
+#define MGN_MCS1 0x81
+#define MGN_MCS2 0x82
+#define MGN_MCS3 0x83
+#define MGN_MCS4 0x84
+#define MGN_MCS5 0x85
+#define MGN_MCS6 0x86
+#define MGN_MCS7 0x87
+#define MGN_MCS8 0x88
+#define MGN_MCS9 0x89
+#define MGN_MCS10 0x8a
+#define MGN_MCS11 0x8b
+#define MGN_MCS12 0x8c
+#define MGN_MCS13 0x8d
+#define MGN_MCS14 0x8e
+#define MGN_MCS15 0x8f
+#define MGN_MCS0_SG 0x90
+#define MGN_MCS1_SG 0x91
+#define MGN_MCS2_SG 0x92
+#define MGN_MCS3_SG 0x93
+#define MGN_MCS4_SG 0x94
+#define MGN_MCS5_SG 0x95
+#define MGN_MCS6_SG 0x96
+#define MGN_MCS7_SG 0x97
+#define MGN_MCS8_SG 0x98
+#define MGN_MCS9_SG 0x99
+#define MGN_MCS10_SG 0x9a
+#define MGN_MCS11_SG 0x9b
+#define MGN_MCS12_SG 0x9c
+#define MGN_MCS13_SG 0x9d
+#define MGN_MCS14_SG 0x9e
+#define MGN_MCS15_SG 0x9f
+
+
+enum _ReasonCode {
+ unspec_reason = 0x1,
+ auth_not_valid = 0x2,
+ deauth_lv_ss = 0x3,
+ inactivity = 0x4,
+ ap_overload = 0x5,
+ class2_err = 0x6,
+ class3_err = 0x7,
+ disas_lv_ss = 0x8,
+ asoc_not_auth = 0x9,
+
+ mic_failure = 0xe,
+
+ invalid_IE = 0x0d,
+ four_way_tmout = 0x0f,
+ two_way_tmout = 0x10,
+ IE_dismatch = 0x11,
+ invalid_Gcipher = 0x12,
+ invalid_Pcipher = 0x13,
+ invalid_AKMP = 0x14,
+ unsup_RSNIEver = 0x15,
+ invalid_RSNIE = 0x16,
+ auth_802_1x_fail = 0x17,
+ ciper_reject = 0x18,
+
+ QoS_unspec = 0x20,
+ QAP_bandwidth = 0x21,
+ poor_condition = 0x22,
+ no_facility = 0x23,
+ req_declined = 0x25,
+ invalid_param = 0x26,
+ req_not_honored = 0x27,
+ TS_not_created = 0x2F,
+ DL_not_allowed = 0x30,
+ dest_not_exist = 0x31,
+ dest_not_QSTA = 0x32,
+};
+
+enum hal_def_variable {
+ HAL_DEF_TPC_ENABLE,
+ HAL_DEF_INIT_GAIN,
+ HAL_DEF_PROT_IMP_MODE,
+ HAL_DEF_HIGH_POWER_MECHANISM,
+ HAL_DEF_RATE_ADAPTIVE_MECHANISM,
+ HAL_DEF_ANTENNA_DIVERSITY_MECHANISM,
+ HAL_DEF_LED,
+ HAL_DEF_CW_MAX_MIN,
+
+ HAL_DEF_WOWLAN,
+ HAL_DEF_ENDPOINTS,
+ HAL_DEF_MIN_TX_POWER_DBM,
+ HAL_DEF_MAX_TX_POWER_DBM,
+ HW_DEF_EFUSE_REPG_SECTION1_FLAG,
+ HW_DEF_EFUSE_REPG_DATA,
+ HW_DEF_GPIO,
+ HAL_DEF_PCI_SUPPORT_ASPM,
+ HAL_DEF_THERMAL_VALUE,
+ HAL_DEF_USB_IN_TOKEN_REV,
+};
+
+enum hw_variables {
+ HW_VAR_ETHER_ADDR,
+ HW_VAR_MULTICAST_REG,
+ HW_VAR_BASIC_RATE,
+ HW_VAR_BSSID,
+ HW_VAR_MEDIA_STATUS,
+ HW_VAR_SECURITY_CONF,
+ HW_VAR_BEACON_INTERVAL,
+ HW_VAR_ATIM_WINDOW,
+ HW_VAR_LISTEN_INTERVAL,
+ HW_VAR_CS_COUNTER,
+ HW_VAR_DEFAULTKEY0,
+ HW_VAR_DEFAULTKEY1,
+ HW_VAR_DEFAULTKEY2,
+ HW_VAR_DEFAULTKEY3,
+ HW_VAR_SIFS,
+ HW_VAR_DIFS,
+ HW_VAR_EIFS,
+ HW_VAR_SLOT_TIME,
+ HW_VAR_ACK_PREAMBLE,
+ HW_VAR_CW_CONFIG,
+ HW_VAR_CW_VALUES,
+ HW_VAR_RATE_FALLBACK_CONTROL,
+ HW_VAR_CONTENTION_WINDOW,
+ HW_VAR_RETRY_COUNT,
+ HW_VAR_TR_SWITCH,
+ HW_VAR_COMMAND,
+ HW_VAR_WPA_CONFIG,
+ HW_VAR_AMPDU_MIN_SPACE,
+ HW_VAR_SHORTGI_DENSITY,
+ HW_VAR_AMPDU_FACTOR,
+ HW_VAR_MCS_RATE_AVAILABLE,
+ HW_VAR_AC_PARAM,
+ HW_VAR_ACM_CTRL,
+ HW_VAR_DIS_Req_Qsize,
+ HW_VAR_CCX_CHNL_LOAD,
+ HW_VAR_CCX_NOISE_HISTOGRAM,
+ HW_VAR_CCX_CLM_NHM,
+ HW_VAR_TxOPLimit,
+ HW_VAR_TURBO_MODE,
+ HW_VAR_RF_STATE,
+ HW_VAR_RF_OFF_BY_HW,
+ HW_VAR_BUS_SPEED,
+ HW_VAR_SET_DEV_POWER,
+
+ HW_VAR_RCR,
+ HW_VAR_RATR_0,
+ HW_VAR_RRSR,
+ HW_VAR_CPU_RST,
+ HW_VAR_CECHK_BSSID,
+ HW_VAR_LBK_MODE,
+ HW_VAR_AES_11N_FIX,
+ HW_VAR_USB_RX_AGGR,
+ HW_VAR_USER_CONTROL_TURBO_MODE,
+ HW_VAR_RETRY_LIMIT,
+ HW_VAR_INIT_TX_RATE,
+ HW_VAR_TX_RATE_REG,
+ HW_VAR_EFUSE_USAGE,
+ HW_VAR_EFUSE_BYTES,
+ HW_VAR_AUTOLOAD_STATUS,
+ HW_VAR_RF_2R_DISABLE,
+ HW_VAR_SET_RPWM,
+ HW_VAR_H2C_FW_PWRMODE,
+ HW_VAR_H2C_FW_JOINBSSRPT,
+ HW_VAR_1X1_RECV_COMBINE,
+ HW_VAR_STOP_SEND_BEACON,
+ HW_VAR_TSF_TIMER,
+ HW_VAR_IO_CMD,
+
+ HW_VAR_RF_RECOVERY,
+ HW_VAR_H2C_FW_UPDATE_GTK,
+ HW_VAR_WF_MASK,
+ HW_VAR_WF_CRC,
+ HW_VAR_WF_IS_MAC_ADDR,
+ HW_VAR_H2C_FW_OFFLOAD,
+ HW_VAR_RESET_WFCRC,
+
+ HW_VAR_HANDLE_FW_C2H,
+ HW_VAR_DL_FW_RSVD_PAGE,
+ HW_VAR_AID,
+ HW_VAR_HW_SEQ_ENABLE,
+ HW_VAR_CORRECT_TSF,
+ HW_VAR_BCN_VALID,
+ HW_VAR_FWLPS_RF_ON,
+ HW_VAR_DUAL_TSF_RST,
+ HW_VAR_SWITCH_EPHY_WoWLAN,
+ HW_VAR_INT_MIGRATION,
+ HW_VAR_INT_AC,
+ HW_VAR_RF_TIMING,
+};
+
+enum rt_op_mode {
+ RT_OP_MODE_AP,
+ RT_OP_MODE_INFRASTRUCTURE,
+ RT_OP_MODE_IBSS,
+ RT_OP_MODE_NO_LINK,
+};
+
+
+#define aSifsTime \
+ (((priv->rtllib->current_network.mode == IEEE_A) \
+ || (priv->rtllib->current_network.mode == IEEE_N_24G) \
+ || (priv->rtllib->current_network.mode == IEEE_N_5G)) ? 16 : 10)
+
+#define MGMT_QUEUE_NUM 5
+
+#define IEEE_CMD_SET_WPA_PARAM 1
+#define IEEE_CMD_SET_WPA_IE 2
+#define IEEE_CMD_SET_ENCRYPTION 3
+#define IEEE_CMD_MLME 4
+
+#define IEEE_PARAM_WPA_ENABLED 1
+#define IEEE_PARAM_TKIP_COUNTERMEASURES 2
+#define IEEE_PARAM_DROP_UNENCRYPTED 3
+#define IEEE_PARAM_PRIVACY_INVOKED 4
+#define IEEE_PARAM_AUTH_ALGS 5
+#define IEEE_PARAM_IEEE_802_1X 6
+#define IEEE_PARAM_WPAX_SELECT 7
+#define IEEE_PROTO_WPA 1
+#define IEEE_PROTO_RSN 2
+#define IEEE_WPAX_USEGROUP 0
+#define IEEE_WPAX_WEP40 1
+#define IEEE_WPAX_TKIP 2
+#define IEEE_WPAX_WRAP 3
+#define IEEE_WPAX_CCMP 4
+#define IEEE_WPAX_WEP104 5
+
+#define IEEE_KEY_MGMT_IEEE8021X 1
+#define IEEE_KEY_MGMT_PSK 2
+
+#define IEEE_MLME_STA_DEAUTH 1
+#define IEEE_MLME_STA_DISASSOC 2
+
+
+#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2
+#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3
+#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4
+#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5
+#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6
+#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7
+#define IEEE_CRYPT_ALG_NAME_LEN 16
+
+#define MAX_IE_LEN 0xff
+
+struct ieee_param {
+ u32 cmd;
+ u8 sta_addr[ETH_ALEN];
+ union {
+ struct {
+ u8 name;
+ u32 value;
+ } wpa_param;
+ struct {
+ u32 len;
+ u8 reserved[32];
+ u8 data[0];
+ } wpa_ie;
+ struct {
+ int command;
+ int reason_code;
+ } mlme;
+ struct {
+ u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
+ u8 set_tx;
+ u32 err;
+ u8 idx;
+ u8 seq[8]; /* sequence counter (set: RX, get: TX) */
+ u16 key_len;
+ u8 key[0];
+ } crypt;
+ } u;
+};
+
+
+#if WIRELESS_EXT < 17
+#define IW_QUAL_QUAL_INVALID 0x10
+#define IW_QUAL_LEVEL_INVALID 0x20
+#define IW_QUAL_NOISE_INVALID 0x40
+#define IW_QUAL_QUAL_UPDATED 0x1
+#define IW_QUAL_LEVEL_UPDATED 0x2
+#define IW_QUAL_NOISE_UPDATED 0x4
+#endif
+
+#define msleep_interruptible_rsl msleep_interruptible
+
+#define RTLLIB_DATA_LEN 2304
+/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
+ * 6.2.1.1.2.
+ *
+ * The figure in section 7.1.2 suggests a body size of up to 2312
+ * bytes is allowed, which is a bit confusing, I suspect this
+ * represents the 2304 bytes of real data, plus a possible 8 bytes of
+ * WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro)
+ */
+#define RTLLIB_1ADDR_LEN 10
+#define RTLLIB_2ADDR_LEN 16
+#define RTLLIB_3ADDR_LEN 24
+#define RTLLIB_4ADDR_LEN 30
+#define RTLLIB_FCS_LEN 4
+#define RTLLIB_HLEN (RTLLIB_4ADDR_LEN)
+#define RTLLIB_FRAME_LEN (RTLLIB_DATA_LEN + RTLLIB_HLEN)
+#define RTLLIB_MGMT_HDR_LEN 24
+#define RTLLIB_DATA_HDR3_LEN 24
+#define RTLLIB_DATA_HDR4_LEN 30
+
+#define RTLLIB_SKBBUFFER_SIZE 2500
+
+#define MIN_FRAG_THRESHOLD 256U
+#define MAX_FRAG_THRESHOLD 2346U
+#define MAX_HT_DATA_FRAG_THRESHOLD 0x2000
+
+#define HT_AMSDU_SIZE_4K 3839
+#define HT_AMSDU_SIZE_8K 7935
+
+/* Frame control field constants */
+#define RTLLIB_FCTL_VERS 0x0003
+#define RTLLIB_FCTL_FTYPE 0x000c
+#define RTLLIB_FCTL_STYPE 0x00f0
+#define RTLLIB_FCTL_FRAMETYPE 0x00fc
+#define RTLLIB_FCTL_TODS 0x0100
+#define RTLLIB_FCTL_FROMDS 0x0200
+#define RTLLIB_FCTL_DSTODS 0x0300
+#define RTLLIB_FCTL_MOREFRAGS 0x0400
+#define RTLLIB_FCTL_RETRY 0x0800
+#define RTLLIB_FCTL_PM 0x1000
+#define RTLLIB_FCTL_MOREDATA 0x2000
+#define RTLLIB_FCTL_WEP 0x4000
+#define RTLLIB_FCTL_ORDER 0x8000
+
+#define RTLLIB_FTYPE_MGMT 0x0000
+#define RTLLIB_FTYPE_CTL 0x0004
+#define RTLLIB_FTYPE_DATA 0x0008
+
+/* management */
+#define RTLLIB_STYPE_ASSOC_REQ 0x0000
+#define RTLLIB_STYPE_ASSOC_RESP 0x0010
+#define RTLLIB_STYPE_REASSOC_REQ 0x0020
+#define RTLLIB_STYPE_REASSOC_RESP 0x0030
+#define RTLLIB_STYPE_PROBE_REQ 0x0040
+#define RTLLIB_STYPE_PROBE_RESP 0x0050
+#define RTLLIB_STYPE_BEACON 0x0080
+#define RTLLIB_STYPE_ATIM 0x0090
+#define RTLLIB_STYPE_DISASSOC 0x00A0
+#define RTLLIB_STYPE_AUTH 0x00B0
+#define RTLLIB_STYPE_DEAUTH 0x00C0
+#define RTLLIB_STYPE_MANAGE_ACT 0x00D0
+
+/* control */
+#define RTLLIB_STYPE_PSPOLL 0x00A0
+#define RTLLIB_STYPE_RTS 0x00B0
+#define RTLLIB_STYPE_CTS 0x00C0
+#define RTLLIB_STYPE_ACK 0x00D0
+#define RTLLIB_STYPE_CFEND 0x00E0
+#define RTLLIB_STYPE_CFENDACK 0x00F0
+#define RTLLIB_STYPE_BLOCKACK 0x0094
+
+/* data */
+#define RTLLIB_STYPE_DATA 0x0000
+#define RTLLIB_STYPE_DATA_CFACK 0x0010
+#define RTLLIB_STYPE_DATA_CFPOLL 0x0020
+#define RTLLIB_STYPE_DATA_CFACKPOLL 0x0030
+#define RTLLIB_STYPE_NULLFUNC 0x0040
+#define RTLLIB_STYPE_CFACK 0x0050
+#define RTLLIB_STYPE_CFPOLL 0x0060
+#define RTLLIB_STYPE_CFACKPOLL 0x0070
+#define RTLLIB_STYPE_QOS_DATA 0x0080
+#define RTLLIB_STYPE_QOS_NULL 0x00C0
+
+#define RTLLIB_SCTL_FRAG 0x000F
+#define RTLLIB_SCTL_SEQ 0xFFF0
+
+/* QOS control */
+#define RTLLIB_QCTL_TID 0x000F
+
+#define FC_QOS_BIT BIT7
+#define IsDataFrame(pdu) (((pdu[0] & 0x0C) == 0x08) ? true : false)
+#define IsLegacyDataFrame(pdu) (IsDataFrame(pdu) && (!(pdu[0]&FC_QOS_BIT)))
+#define IsQoSDataFrame(pframe) \
+ ((*(u16 *)pframe&(RTLLIB_STYPE_QOS_DATA|RTLLIB_FTYPE_DATA)) == \
+ (RTLLIB_STYPE_QOS_DATA|RTLLIB_FTYPE_DATA))
+#define Frame_Order(pframe) (*(u16 *)pframe&RTLLIB_FCTL_ORDER)
+#define SN_LESS(a, b) (((a-b)&0x800) != 0)
+#define SN_EQUAL(a, b) (a == b)
+#define MAX_DEV_ADDR_SIZE 8
+
+enum act_category {
+ ACT_CAT_QOS = 1,
+ ACT_CAT_DLS = 2,
+ ACT_CAT_BA = 3,
+ ACT_CAT_HT = 7,
+ ACT_CAT_WMM = 17,
+};
+
+enum ts_action {
+ ACT_ADDTSREQ = 0,
+ ACT_ADDTSRSP = 1,
+ ACT_DELTS = 2,
+ ACT_SCHEDULE = 3,
+};
+
+enum ba_action {
+ ACT_ADDBAREQ = 0,
+ ACT_ADDBARSP = 1,
+ ACT_DELBA = 2,
+};
+
+enum init_gain_op_type {
+ IG_Backup = 0,
+ IG_Restore,
+ IG_Max
+};
+
+enum led_ctl_mode {
+ LED_CTL_POWER_ON = 1,
+ LED_CTL_LINK = 2,
+ LED_CTL_NO_LINK = 3,
+ LED_CTL_TX = 4,
+ LED_CTL_RX = 5,
+ LED_CTL_SITE_SURVEY = 6,
+ LED_CTL_POWER_OFF = 7,
+ LED_CTL_START_TO_LINK = 8,
+ LED_CTL_START_WPS = 9,
+ LED_CTL_STOP_WPS = 10,
+ LED_CTL_START_WPS_BOTTON = 11,
+ LED_CTL_STOP_WPS_FAIL = 12,
+ LED_CTL_STOP_WPS_FAIL_OVERLAP = 13,
+};
+
+enum rt_rf_type_def {
+ RF_1T2R = 0,
+ RF_2T4R,
+ RF_2T2R,
+ RF_1T1R,
+ RF_2T2R_GREEN,
+ RF_819X_MAX_TYPE
+};
+
+enum wireless_mode {
+ WIRELESS_MODE_UNKNOWN = 0x00,
+ WIRELESS_MODE_A = 0x01,
+ WIRELESS_MODE_B = 0x02,
+ WIRELESS_MODE_G = 0x04,
+ WIRELESS_MODE_AUTO = 0x08,
+ WIRELESS_MODE_N_24G = 0x10,
+ WIRELESS_MODE_N_5G = 0x20
+};
+
+enum wireless_network_type {
+ WIRELESS_11B = 1,
+ WIRELESS_11G = 2,
+ WIRELESS_11A = 4,
+ WIRELESS_11N = 8
+};
+
+#define OUI_SUBTYPE_WMM_INFO 0
+#define OUI_SUBTYPE_WMM_PARAM 1
+#define OUI_SUBTYPE_QOS_CAPABI 5
+
+/* debug macros */
+extern u32 rtllib_debug_level;
+#define RTLLIB_DEBUG(level, fmt, args...) \
+do { \
+ if (rtllib_debug_level & (level)) \
+ printk(KERN_DEBUG "rtllib: " fmt, ## args); \
+} while (0)
+
+#define RTLLIB_DEBUG_DATA(level, data, datalen) \
+ do { \
+ if ((rtllib_debug_level & (level)) == (level)) { \
+ printk(KERN_DEBUG "rtllib: %s()\n", __func__); \
+ print_hex_dump_bytes(KERN_DEBUG, DUMP_PREFIX_NONE, \
+ data, datalen); \
+ } \
+ } while (0)
+
+/* To use the debug system;
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of:
+ *
+ * #define RTLLIB_DL_xxxx VALUE
+ *
+ * shifting value to the left one bit from the previous entry. xxxx should be
+ * the name of the classification (for example, WEP)
+ *
+ * You then need to either add a RTLLIB_xxxx_DEBUG() macro definition for your
+ * classification, or use RTLLIB_DEBUG(RTLLIB_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * To add your debug level to the list of levels seen when you perform
+ *
+ * % cat /proc/net/ipw/debug_level
+ *
+ * you simply need to add your entry to the ipw_debug_levels array.
+ */
+
+#define RTLLIB_DL_INFO (1<<0)
+#define RTLLIB_DL_WX (1<<1)
+#define RTLLIB_DL_SCAN (1<<2)
+#define RTLLIB_DL_STATE (1<<3)
+#define RTLLIB_DL_MGMT (1<<4)
+#define RTLLIB_DL_FRAG (1<<5)
+#define RTLLIB_DL_EAP (1<<6)
+#define RTLLIB_DL_DROP (1<<7)
+
+#define RTLLIB_DL_TX (1<<8)
+#define RTLLIB_DL_RX (1<<9)
+
+#define RTLLIB_DL_HT (1<<10)
+#define RTLLIB_DL_BA (1<<11)
+#define RTLLIB_DL_TS (1<<12)
+#define RTLLIB_DL_QOS (1<<13)
+#define RTLLIB_DL_REORDER (1<<14)
+#define RTLLIB_DL_IOT (1<<15)
+#define RTLLIB_DL_IPS (1<<16)
+#define RTLLIB_DL_TRACE (1<<29)
+#define RTLLIB_DL_DATA (1<<30)
+#define RTLLIB_DL_ERR (1<<31)
+#define RTLLIB_ERROR(f, a...) pr_err("rtllib: " f, ## a)
+#define RTLLIB_WARNING(f, a...) pr_warn("rtllib: " f, ## a)
+#define RTLLIB_DEBUG_INFO(f, a...) RTLLIB_DEBUG(RTLLIB_DL_INFO, f, ## a)
+
+#define RTLLIB_DEBUG_WX(f, a...) RTLLIB_DEBUG(RTLLIB_DL_WX, f, ## a)
+#define RTLLIB_DEBUG_SCAN(f, a...) RTLLIB_DEBUG(RTLLIB_DL_SCAN, f, ## a)
+#define RTLLIB_DEBUG_STATE(f, a...) RTLLIB_DEBUG(RTLLIB_DL_STATE, f, ## a)
+#define RTLLIB_DEBUG_MGMT(f, a...) RTLLIB_DEBUG(RTLLIB_DL_MGMT, f, ## a)
+#define RTLLIB_DEBUG_FRAG(f, a...) RTLLIB_DEBUG(RTLLIB_DL_FRAG, f, ## a)
+#define RTLLIB_DEBUG_EAP(f, a...) RTLLIB_DEBUG(RTLLIB_DL_EAP, f, ## a)
+#define RTLLIB_DEBUG_DROP(f, a...) RTLLIB_DEBUG(RTLLIB_DL_DROP, f, ## a)
+#define RTLLIB_DEBUG_TX(f, a...) RTLLIB_DEBUG(RTLLIB_DL_TX, f, ## a)
+#define RTLLIB_DEBUG_RX(f, a...) RTLLIB_DEBUG(RTLLIB_DL_RX, f, ## a)
+#define RTLLIB_DEBUG_QOS(f, a...) RTLLIB_DEBUG(RTLLIB_DL_QOS, f, ## a)
+
+#ifndef ETH_P_PAE
+#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
+#define ETH_P_IP 0x0800 /* Internet Protocol packet */
+#define ETH_P_ARP 0x0806 /* Address Resolution packet */
+#endif /* ETH_P_PAE */
+
+#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
+
+#ifndef ETH_P_80211_RAW
+#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
+#endif
+
+/* IEEE 802.11 defines */
+
+#define P80211_OUI_LEN 3
+
+struct rtllib_snap_hdr {
+
+ u8 dsap; /* always 0xAA */
+ u8 ssap; /* always 0xAA */
+ u8 ctrl; /* always 0x03 */
+ u8 oui[P80211_OUI_LEN]; /* organizational universal id */
+
+} __packed;
+
+enum _REG_PREAMBLE_MODE {
+ PREAMBLE_LONG = 1,
+ PREAMBLE_AUTO = 2,
+ PREAMBLE_SHORT = 3,
+};
+
+#define SNAP_SIZE sizeof(struct rtllib_snap_hdr)
+
+#define WLAN_FC_GET_VERS(fc) ((fc) & RTLLIB_FCTL_VERS)
+#define WLAN_FC_GET_TYPE(fc) ((fc) & RTLLIB_FCTL_FTYPE)
+#define WLAN_FC_GET_STYPE(fc) ((fc) & RTLLIB_FCTL_STYPE)
+#define WLAN_FC_MORE_DATA(fc) ((fc) & RTLLIB_FCTL_MOREDATA)
+
+#define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & RTLLIB_FCTL_FRAMETYPE)
+#define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTLLIB_SCTL_FRAG)
+#define WLAN_GET_SEQ_SEQ(seq) (((seq) & RTLLIB_SCTL_SEQ) >> 4)
+
+/* Authentication algorithms */
+#define WLAN_AUTH_OPEN 0
+#define WLAN_AUTH_SHARED_KEY 1
+#define WLAN_AUTH_LEAP 128
+
+#define WLAN_AUTH_CHALLENGE_LEN 128
+
+#define WLAN_CAPABILITY_ESS (1<<0)
+#define WLAN_CAPABILITY_IBSS (1<<1)
+#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
+#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
+#define WLAN_CAPABILITY_PRIVACY (1<<4)
+#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
+#define WLAN_CAPABILITY_PBCC (1<<6)
+#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
+#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
+#define WLAN_CAPABILITY_QOS (1<<9)
+#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
+#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
+
+/* 802.11g ERP information element */
+#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
+#define WLAN_ERP_USE_PROTECTION (1<<1)
+#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
+
+#define RTLLIB_STATMASK_SIGNAL (1<<0)
+#define RTLLIB_STATMASK_RSSI (1<<1)
+#define RTLLIB_STATMASK_NOISE (1<<2)
+#define RTLLIB_STATMASK_RATE (1<<3)
+#define RTLLIB_STATMASK_WEMASK 0x7
+
+#define RTLLIB_CCK_MODULATION (1<<0)
+#define RTLLIB_OFDM_MODULATION (1<<1)
+
+#define RTLLIB_24GHZ_BAND (1<<0)
+#define RTLLIB_52GHZ_BAND (1<<1)
+
+#define RTLLIB_CCK_RATE_LEN 4
+#define RTLLIB_CCK_RATE_1MB 0x02
+#define RTLLIB_CCK_RATE_2MB 0x04
+#define RTLLIB_CCK_RATE_5MB 0x0B
+#define RTLLIB_CCK_RATE_11MB 0x16
+#define RTLLIB_OFDM_RATE_LEN 8
+#define RTLLIB_OFDM_RATE_6MB 0x0C
+#define RTLLIB_OFDM_RATE_9MB 0x12
+#define RTLLIB_OFDM_RATE_12MB 0x18
+#define RTLLIB_OFDM_RATE_18MB 0x24
+#define RTLLIB_OFDM_RATE_24MB 0x30
+#define RTLLIB_OFDM_RATE_36MB 0x48
+#define RTLLIB_OFDM_RATE_48MB 0x60
+#define RTLLIB_OFDM_RATE_54MB 0x6C
+#define RTLLIB_BASIC_RATE_MASK 0x80
+
+#define RTLLIB_CCK_RATE_1MB_MASK (1<<0)
+#define RTLLIB_CCK_RATE_2MB_MASK (1<<1)
+#define RTLLIB_CCK_RATE_5MB_MASK (1<<2)
+#define RTLLIB_CCK_RATE_11MB_MASK (1<<3)
+#define RTLLIB_OFDM_RATE_6MB_MASK (1<<4)
+#define RTLLIB_OFDM_RATE_9MB_MASK (1<<5)
+#define RTLLIB_OFDM_RATE_12MB_MASK (1<<6)
+#define RTLLIB_OFDM_RATE_18MB_MASK (1<<7)
+#define RTLLIB_OFDM_RATE_24MB_MASK (1<<8)
+#define RTLLIB_OFDM_RATE_36MB_MASK (1<<9)
+#define RTLLIB_OFDM_RATE_48MB_MASK (1<<10)
+#define RTLLIB_OFDM_RATE_54MB_MASK (1<<11)
+
+#define RTLLIB_CCK_RATES_MASK 0x0000000F
+#define RTLLIB_CCK_BASIC_RATES_MASK (RTLLIB_CCK_RATE_1MB_MASK | \
+ RTLLIB_CCK_RATE_2MB_MASK)
+#define RTLLIB_CCK_DEFAULT_RATES_MASK (RTLLIB_CCK_BASIC_RATES_MASK | \
+ RTLLIB_CCK_RATE_5MB_MASK | \
+ RTLLIB_CCK_RATE_11MB_MASK)
+
+#define RTLLIB_OFDM_RATES_MASK 0x00000FF0
+#define RTLLIB_OFDM_BASIC_RATES_MASK (RTLLIB_OFDM_RATE_6MB_MASK | \
+ RTLLIB_OFDM_RATE_12MB_MASK | \
+ RTLLIB_OFDM_RATE_24MB_MASK)
+#define RTLLIB_OFDM_DEFAULT_RATES_MASK (RTLLIB_OFDM_BASIC_RATES_MASK | \
+ RTLLIB_OFDM_RATE_9MB_MASK | \
+ RTLLIB_OFDM_RATE_18MB_MASK | \
+ RTLLIB_OFDM_RATE_36MB_MASK | \
+ RTLLIB_OFDM_RATE_48MB_MASK | \
+ RTLLIB_OFDM_RATE_54MB_MASK)
+#define RTLLIB_DEFAULT_RATES_MASK (RTLLIB_OFDM_DEFAULT_RATES_MASK | \
+ RTLLIB_CCK_DEFAULT_RATES_MASK)
+
+#define RTLLIB_NUM_OFDM_RATES 8
+#define RTLLIB_NUM_CCK_RATES 4
+#define RTLLIB_OFDM_SHIFT_MASK_A 4
+
+
+/* this is stolen and modified from the madwifi driver*/
+#define RTLLIB_FC0_TYPE_MASK 0x0c
+#define RTLLIB_FC0_TYPE_DATA 0x08
+#define RTLLIB_FC0_SUBTYPE_MASK 0xB0
+#define RTLLIB_FC0_SUBTYPE_QOS 0x80
+
+#define RTLLIB_QOS_HAS_SEQ(fc) \
+ (((fc) & (RTLLIB_FC0_TYPE_MASK | RTLLIB_FC0_SUBTYPE_MASK)) == \
+ (RTLLIB_FC0_TYPE_DATA | RTLLIB_FC0_SUBTYPE_QOS))
+
+/* this is stolen from ipw2200 driver */
+#define IEEE_IBSS_MAC_HASH_SIZE 31
+struct ieee_ibss_seq {
+ u8 mac[ETH_ALEN];
+ u16 seq_num[17];
+ u16 frag_num[17];
+ unsigned long packet_time[17];
+ struct list_head list;
+};
+
+/* NOTE: This data is for statistical purposes; not all hardware provides this
+ * information for frames received. Not setting these will not cause
+ * any adverse affects. */
+struct rtllib_rx_stats {
+ u64 mac_time;
+ s8 rssi;
+ u8 signal;
+ u8 noise;
+ u16 rate; /* in 100 kbps */
+ u8 received_channel;
+ u8 control;
+ u8 mask;
+ u8 freq;
+ u16 len;
+ u64 tsf;
+ u32 beacon_time;
+ u8 nic_type;
+ u16 Length;
+ u8 SignalQuality;
+ s32 RecvSignalPower;
+ s8 RxPower;
+ u8 SignalStrength;
+ u16 bHwError:1;
+ u16 bCRC:1;
+ u16 bICV:1;
+ u16 bShortPreamble:1;
+ u16 Antenna:1;
+ u16 Decrypted:1;
+ u16 Wakeup:1;
+ u16 Reserved0:1;
+ u8 AGC;
+ u32 TimeStampLow;
+ u32 TimeStampHigh;
+ bool bShift;
+ bool bIsQosData;
+ u8 UserPriority;
+
+ u8 RxDrvInfoSize;
+ u8 RxBufShift;
+ bool bIsAMPDU;
+ bool bFirstMPDU;
+ bool bContainHTC;
+ bool RxIs40MHzPacket;
+ u32 RxPWDBAll;
+ u8 RxMIMOSignalStrength[4];
+ s8 RxMIMOSignalQuality[2];
+ bool bPacketMatchBSSID;
+ bool bIsCCK;
+ bool bPacketToSelf;
+ u8 *virtual_address;
+ u16 packetlength;
+ u16 fraglength;
+ u16 fragoffset;
+ u16 ntotalfrag;
+ bool bisrxaggrsubframe;
+ bool bPacketBeacon;
+ bool bToSelfBA;
+ char cck_adc_pwdb[4];
+ u16 Seq_Num;
+ u8 nTotalAggPkt;
+};
+
+/* IEEE 802.11 requires that STA supports concurrent reception of at least
+ * three fragmented frames. This define can be increased to support more
+ * concurrent frames, but it should be noted that each entry can consume about
+ * 2 kB of RAM and increasing cache size will slow down frame reassembly.
+ */
+#define RTLLIB_FRAG_CACHE_LEN 4
+
+struct rtllib_frag_entry {
+ unsigned long first_frag_time;
+ unsigned int seq;
+ unsigned int last_frag;
+ struct sk_buff *skb;
+ u8 src_addr[ETH_ALEN];
+ u8 dst_addr[ETH_ALEN];
+};
+
+struct rtllib_stats {
+ unsigned int tx_unicast_frames;
+ unsigned int tx_multicast_frames;
+ unsigned int tx_fragments;
+ unsigned int tx_unicast_octets;
+ unsigned int tx_multicast_octets;
+ unsigned int tx_deferred_transmissions;
+ unsigned int tx_single_retry_frames;
+ unsigned int tx_multiple_retry_frames;
+ unsigned int tx_retry_limit_exceeded;
+ unsigned int tx_discards;
+ unsigned int rx_unicast_frames;
+ unsigned int rx_multicast_frames;
+ unsigned int rx_fragments;
+ unsigned int rx_unicast_octets;
+ unsigned int rx_multicast_octets;
+ unsigned int rx_fcs_errors;
+ unsigned int rx_discards_no_buffer;
+ unsigned int tx_discards_wrong_sa;
+ unsigned int rx_discards_undecryptable;
+ unsigned int rx_message_in_msg_fragments;
+ unsigned int rx_message_in_bad_msg_fragments;
+};
+
+struct rtllib_device;
+
+#define SEC_KEY_1 (1<<0)
+#define SEC_KEY_2 (1<<1)
+#define SEC_KEY_3 (1<<2)
+#define SEC_KEY_4 (1<<3)
+#define SEC_ACTIVE_KEY (1<<4)
+#define SEC_AUTH_MODE (1<<5)
+#define SEC_UNICAST_GROUP (1<<6)
+#define SEC_LEVEL (1<<7)
+#define SEC_ENABLED (1<<8)
+#define SEC_ENCRYPT (1<<9)
+
+#define SEC_LEVEL_0 0 /* None */
+#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */
+#define SEC_LEVEL_2 2 /* Level 1 + TKIP */
+#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
+#define SEC_LEVEL_3 4 /* Level 2 + CCMP */
+
+#define SEC_ALG_NONE 0
+#define SEC_ALG_WEP 1
+#define SEC_ALG_TKIP 2
+#define SEC_ALG_CCMP 4
+
+#define WEP_KEY_LEN 13
+#define SCM_KEY_LEN 32
+#define SCM_TEMPORAL_KEY_LENGTH 16
+
+struct rtllib_security {
+ u16 active_key:2,
+ enabled:1,
+ auth_mode:2,
+ auth_algo:4,
+ unicast_uses_group:1,
+ encrypt:1;
+ u8 key_sizes[NUM_WEP_KEYS];
+ u8 keys[NUM_WEP_KEYS][SCM_KEY_LEN];
+ u8 level;
+ u16 flags;
+} __packed;
+
+
+/* 802.11 data frame from AP
+ * ,-------------------------------------------------------------------.
+ * Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
+ * |------|------|---------|---------|---------|------|---------|------|
+ * Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs |
+ * | | tion | (BSSID) | | | ence | data | |
+ * `-------------------------------------------------------------------'
+ * Total: 28-2340 bytes
+ */
+
+/* Management Frame Information Element Types */
+enum rtllib_mfie {
+ MFIE_TYPE_SSID = 0,
+ MFIE_TYPE_RATES = 1,
+ MFIE_TYPE_FH_SET = 2,
+ MFIE_TYPE_DS_SET = 3,
+ MFIE_TYPE_CF_SET = 4,
+ MFIE_TYPE_TIM = 5,
+ MFIE_TYPE_IBSS_SET = 6,
+ MFIE_TYPE_COUNTRY = 7,
+ MFIE_TYPE_HOP_PARAMS = 8,
+ MFIE_TYPE_HOP_TABLE = 9,
+ MFIE_TYPE_REQUEST = 10,
+ MFIE_TYPE_CHALLENGE = 16,
+ MFIE_TYPE_POWER_CONSTRAINT = 32,
+ MFIE_TYPE_POWER_CAPABILITY = 33,
+ MFIE_TYPE_TPC_REQUEST = 34,
+ MFIE_TYPE_TPC_REPORT = 35,
+ MFIE_TYPE_SUPP_CHANNELS = 36,
+ MFIE_TYPE_CSA = 37,
+ MFIE_TYPE_MEASURE_REQUEST = 38,
+ MFIE_TYPE_MEASURE_REPORT = 39,
+ MFIE_TYPE_QUIET = 40,
+ MFIE_TYPE_IBSS_DFS = 41,
+ MFIE_TYPE_ERP = 42,
+ MFIE_TYPE_HT_CAP = 45,
+ MFIE_TYPE_RSN = 48,
+ MFIE_TYPE_RATES_EX = 50,
+ MFIE_TYPE_HT_INFO = 61,
+ MFIE_TYPE_AIRONET = 133,
+ MFIE_TYPE_GENERIC = 221,
+ MFIE_TYPE_QOS_PARAMETER = 222,
+};
+
+/* Minimal header; can be used for passing 802.11 frames with sufficient
+ * information to determine what type of underlying data type is actually
+ * stored in the data.
+ */
+struct rtllib_pspoll_hdr {
+ __le16 frame_ctl;
+ __le16 aid;
+ u8 bssid[ETH_ALEN];
+ u8 ta[ETH_ALEN];
+} __packed;
+
+struct rtllib_hdr {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 payload[0];
+} __packed;
+
+struct rtllib_hdr_1addr {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 payload[0];
+} __packed;
+
+struct rtllib_hdr_2addr {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 payload[0];
+} __packed;
+
+struct rtllib_hdr_3addr {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ __le16 seq_ctl;
+ u8 payload[0];
+} __packed;
+
+struct rtllib_hdr_4addr {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ __le16 seq_ctl;
+ u8 addr4[ETH_ALEN];
+ u8 payload[0];
+} __packed;
+
+struct rtllib_hdr_3addrqos {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ __le16 seq_ctl;
+ __le16 qos_ctl;
+ u8 payload[0];
+} __packed;
+
+struct rtllib_hdr_4addrqos {
+ __le16 frame_ctl;
+ __le16 duration_id;
+ u8 addr1[ETH_ALEN];
+ u8 addr2[ETH_ALEN];
+ u8 addr3[ETH_ALEN];
+ __le16 seq_ctl;
+ u8 addr4[ETH_ALEN];
+ __le16 qos_ctl;
+ u8 payload[0];
+} __packed;
+
+struct rtllib_info_element {
+ u8 id;
+ u8 len;
+ u8 data[0];
+} __packed;
+
+struct rtllib_authentication {
+ struct rtllib_hdr_3addr header;
+ __le16 algorithm;
+ __le16 transaction;
+ __le16 status;
+ /*challenge*/
+ struct rtllib_info_element info_element[0];
+} __packed;
+
+struct rtllib_disauth {
+ struct rtllib_hdr_3addr header;
+ __le16 reason;
+} __packed;
+
+struct rtllib_disassoc {
+ struct rtllib_hdr_3addr header;
+ __le16 reason;
+} __packed;
+
+struct rtllib_probe_request {
+ struct rtllib_hdr_3addr header;
+ /* SSID, supported rates */
+ struct rtllib_info_element info_element[0];
+} __packed;
+
+struct rtllib_probe_response {
+ struct rtllib_hdr_3addr header;
+ u32 time_stamp[2];
+ __le16 beacon_interval;
+ __le16 capability;
+ /* SSID, supported rates, FH params, DS params,
+ * CF params, IBSS params, TIM (if beacon), RSN
+ */
+ struct rtllib_info_element info_element[0];
+} __packed;
+
+/* Alias beacon for probe_response */
+#define rtllib_beacon rtllib_probe_response
+
+struct rtllib_assoc_request_frame {
+ struct rtllib_hdr_3addr header;
+ __le16 capability;
+ __le16 listen_interval;
+ /* SSID, supported rates, RSN */
+ struct rtllib_info_element info_element[0];
+} __packed;
+
+struct rtllib_reassoc_request_frame {
+ struct rtllib_hdr_3addr header;
+ __le16 capability;
+ __le16 listen_interval;
+ u8 current_ap[ETH_ALEN];
+ /* SSID, supported rates, RSN */
+ struct rtllib_info_element info_element[0];
+} __packed;
+
+struct rtllib_assoc_response_frame {
+ struct rtllib_hdr_3addr header;
+ __le16 capability;
+ __le16 status;
+ __le16 aid;
+ struct rtllib_info_element info_element[0]; /* supported rates */
+} __packed;
+
+struct rtllib_txb {
+ u8 nr_frags;
+ u8 encrypted;
+ u8 queue_index;
+ u8 rts_included;
+ u16 reserved;
+ __le16 frag_size;
+ __le16 payload_size;
+ struct sk_buff *fragments[0];
+};
+
+#define MAX_TX_AGG_COUNT 16
+struct rtllib_drv_agg_txb {
+ u8 nr_drv_agg_frames;
+ struct sk_buff *tx_agg_frames[MAX_TX_AGG_COUNT];
+} __packed;
+
+#define MAX_SUBFRAME_COUNT 64
+struct rtllib_rxb {
+ u8 nr_subframes;
+ struct sk_buff *subframes[MAX_SUBFRAME_COUNT];
+ u8 dst[ETH_ALEN];
+ u8 src[ETH_ALEN];
+} __packed;
+
+union frameqos {
+ u16 shortdata;
+ u8 chardata[2];
+ struct {
+ u16 tid:4;
+ u16 eosp:1;
+ u16 ack_policy:2;
+ u16 reserved:1;
+ u16 txop:8;
+ } field;
+};
+
+/* SWEEP TABLE ENTRIES NUMBER*/
+#define MAX_SWEEP_TAB_ENTRIES 42
+#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7
+/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs
+ * only use 8, and then use extended rates for the remaining supported
+ * rates. Other APs, however, stick all of their supported rates on the
+ * main rates information element...
+ */
+#define MAX_RATES_LENGTH ((u8)12)
+#define MAX_RATES_EX_LENGTH ((u8)16)
+#define MAX_NETWORK_COUNT 96
+
+#define MAX_CHANNEL_NUMBER 161
+#define RTLLIB_SOFTMAC_SCAN_TIME 100
+#define RTLLIB_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2)
+
+#define CRC_LENGTH 4U
+
+#define MAX_WPA_IE_LEN 64
+#define MAX_WZC_IE_LEN 256
+
+#define NETWORK_EMPTY_ESSID (1<<0)
+#define NETWORK_HAS_OFDM (1<<1)
+#define NETWORK_HAS_CCK (1<<2)
+
+/* QoS structure */
+#define NETWORK_HAS_QOS_PARAMETERS (1<<3)
+#define NETWORK_HAS_QOS_INFORMATION (1<<4)
+#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \
+ NETWORK_HAS_QOS_INFORMATION)
+/* 802.11h */
+#define NETWORK_HAS_POWER_CONSTRAINT (1<<5)
+#define NETWORK_HAS_CSA (1<<6)
+#define NETWORK_HAS_QUIET (1<<7)
+#define NETWORK_HAS_IBSS_DFS (1<<8)
+#define NETWORK_HAS_TPC_REPORT (1<<9)
+
+#define NETWORK_HAS_ERP_VALUE (1<<10)
+
+#define QOS_QUEUE_NUM 4
+#define QOS_OUI_LEN 3
+#define QOS_OUI_TYPE 2
+#define QOS_ELEMENT_ID 221
+#define QOS_OUI_INFO_SUB_TYPE 0
+#define QOS_OUI_PARAM_SUB_TYPE 1
+#define QOS_VERSION_1 1
+#define QOS_AIFSN_MIN_VALUE 2
+
+struct rtllib_qos_information_element {
+ u8 elementID;
+ u8 length;
+ u8 qui[QOS_OUI_LEN];
+ u8 qui_type;
+ u8 qui_subtype;
+ u8 version;
+ u8 ac_info;
+} __packed;
+
+struct rtllib_qos_ac_parameter {
+ u8 aci_aifsn;
+ u8 ecw_min_max;
+ __le16 tx_op_limit;
+} __packed;
+
+struct rtllib_qos_parameter_info {
+ struct rtllib_qos_information_element info_element;
+ u8 reserved;
+ struct rtllib_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
+} __packed;
+
+struct rtllib_qos_parameters {
+ __le16 cw_min[QOS_QUEUE_NUM];
+ __le16 cw_max[QOS_QUEUE_NUM];
+ u8 aifs[QOS_QUEUE_NUM];
+ u8 flag[QOS_QUEUE_NUM];
+ __le16 tx_op_limit[QOS_QUEUE_NUM];
+} __packed;
+
+struct rtllib_qos_data {
+ struct rtllib_qos_parameters parameters;
+ unsigned int wmm_acm;
+ int active;
+ int supported;
+ u8 param_count;
+ u8 old_param_count;
+};
+
+struct rtllib_tim_parameters {
+ u8 tim_count;
+ u8 tim_period;
+} __packed;
+
+struct rtllib_wmm_ac_param {
+ u8 ac_aci_acm_aifsn;
+ u8 ac_ecwmin_ecwmax;
+ u16 ac_txop_limit;
+};
+
+struct rtllib_wmm_ts_info {
+ u8 ac_dir_tid;
+ u8 ac_up_psb;
+ u8 reserved;
+} __packed;
+
+struct rtllib_wmm_tspec_elem {
+ struct rtllib_wmm_ts_info ts_info;
+ u16 norm_msdu_size;
+ u16 max_msdu_size;
+ u32 min_serv_inter;
+ u32 max_serv_inter;
+ u32 inact_inter;
+ u32 suspen_inter;
+ u32 serv_start_time;
+ u32 min_data_rate;
+ u32 mean_data_rate;
+ u32 peak_data_rate;
+ u32 max_burst_size;
+ u32 delay_bound;
+ u32 min_phy_rate;
+ u16 surp_band_allow;
+ u16 medium_time;
+} __packed;
+
+enum eap_type {
+ EAP_PACKET = 0,
+ EAPOL_START,
+ EAPOL_LOGOFF,
+ EAPOL_KEY,
+ EAPOL_ENCAP_ASF_ALERT
+};
+
+static const char * const eap_types[] = {
+ [EAP_PACKET] = "EAP-Packet",
+ [EAPOL_START] = "EAPOL-Start",
+ [EAPOL_LOGOFF] = "EAPOL-Logoff",
+ [EAPOL_KEY] = "EAPOL-Key",
+ [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert"
+};
+
+static inline const char *eap_get_type(int type)
+{
+ return ((u32)type >= ARRAY_SIZE(eap_types)) ? "Unknown" :
+ eap_types[type];
+}
+static inline u8 Frame_QoSTID(u8 *buf)
+{
+ struct rtllib_hdr_3addr *hdr;
+ u16 fc;
+
+ hdr = (struct rtllib_hdr_3addr *)buf;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ return (u8)((union frameqos *)(buf + (((fc & RTLLIB_FCTL_TODS) &&
+ (fc & RTLLIB_FCTL_FROMDS)) ? 30 : 24)))->field.tid;
+}
+
+
+struct eapol {
+ u8 snap[6];
+ u16 ethertype;
+ u8 version;
+ u8 type;
+ u16 length;
+} __packed;
+
+struct rtllib_softmac_stats {
+ unsigned int rx_ass_ok;
+ unsigned int rx_ass_err;
+ unsigned int rx_probe_rq;
+ unsigned int tx_probe_rs;
+ unsigned int tx_beacons;
+ unsigned int rx_auth_rq;
+ unsigned int rx_auth_rs_ok;
+ unsigned int rx_auth_rs_err;
+ unsigned int tx_auth_rq;
+ unsigned int no_auth_rs;
+ unsigned int no_ass_rs;
+ unsigned int tx_ass_rq;
+ unsigned int rx_ass_rq;
+ unsigned int tx_probe_rq;
+ unsigned int reassoc;
+ unsigned int swtxstop;
+ unsigned int swtxawake;
+ unsigned char CurrentShowTxate;
+ unsigned char last_packet_rate;
+ unsigned int txretrycount;
+};
+
+#define BEACON_PROBE_SSID_ID_POSITION 12
+
+struct rtllib_info_element_hdr {
+ u8 id;
+ u8 len;
+} __packed;
+
+/* These are the data types that can make up management packets
+ *
+ * u16 auth_algorithm;
+ * u16 auth_sequence;
+ * u16 beacon_interval;
+ * u16 capability;
+ * u8 current_ap[ETH_ALEN];
+ * u16 listen_interval;
+ * struct {
+ * u16 association_id:14, reserved:2;
+ * } __packed;
+ * u32 time_stamp[2];
+ * u16 reason;
+ * u16 status;
+ */
+
+#define RTLLIB_DEFAULT_TX_ESSID "Penguin"
+#define RTLLIB_DEFAULT_BASIC_RATE 2
+
+enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
+#define MAX_SP_Len (WMM_all_frame << 4)
+#define RTLLIB_QOS_TID 0x0f
+#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5)
+
+#define RTLLIB_DTIM_MBCAST 4
+#define RTLLIB_DTIM_UCAST 2
+#define RTLLIB_DTIM_VALID 1
+#define RTLLIB_DTIM_INVALID 0
+
+#define RTLLIB_PS_DISABLED 0
+#define RTLLIB_PS_UNICAST RTLLIB_DTIM_UCAST
+#define RTLLIB_PS_MBCAST RTLLIB_DTIM_MBCAST
+
+#define WME_AC_BK 0x00
+#define WME_AC_BE 0x01
+#define WME_AC_VI 0x02
+#define WME_AC_VO 0x03
+#define WME_ACI_MASK 0x03
+#define WME_AIFSN_MASK 0x03
+#define WME_AC_PRAM_LEN 16
+
+#define MAX_RECEIVE_BUFFER_SIZE 9100
+
+#define UP2AC(up) ( \
+ ((up) < 1) ? WME_AC_BE : \
+ ((up) < 3) ? WME_AC_BK : \
+ ((up) < 4) ? WME_AC_BE : \
+ ((up) < 6) ? WME_AC_VI : \
+ WME_AC_VO)
+
+#define AC2UP(_ac) ( \
+ ((_ac) == WME_AC_VO) ? 6 : \
+ ((_ac) == WME_AC_VI) ? 5 : \
+ ((_ac) == WME_AC_BK) ? 1 : \
+ 0)
+
+#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */
+#define ETHERNET_HEADER_SIZE 14 /* length of two Ethernet address
+ * plus ether type*/
+
+struct ether_header {
+ u8 ether_dhost[ETHER_ADDR_LEN];
+ u8 ether_shost[ETHER_ADDR_LEN];
+ u16 ether_type;
+} __packed;
+
+#ifndef ETHERTYPE_PAE
+#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */
+#endif
+#ifndef ETHERTYPE_IP
+#define ETHERTYPE_IP 0x0800 /* IP protocol */
+#endif
+
+
+enum erp_t {
+ ERP_NonERPpresent = 0x01,
+ ERP_UseProtection = 0x02,
+ ERP_BarkerPreambleMode = 0x04,
+};
+
+struct rtllib_network {
+ /* These entries are used to identify a unique network */
+ u8 bssid[ETH_ALEN];
+ u8 channel;
+ /* Ensure null-terminated for any debug msgs */
+ u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 ssid_len;
+ u8 hidden_ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 hidden_ssid_len;
+ struct rtllib_qos_data qos_data;
+
+ bool bWithAironetIE;
+ bool bCkipSupported;
+ bool bCcxRmEnable;
+ u16 CcxRmState[2];
+ bool bMBssidValid;
+ u8 MBssidMask;
+ u8 MBssid[6];
+ bool bWithCcxVerNum;
+ u8 BssCcxVerNumber;
+ /* These are network statistics */
+ struct rtllib_rx_stats stats;
+ u16 capability;
+ u8 rates[MAX_RATES_LENGTH];
+ u8 rates_len;
+ u8 rates_ex[MAX_RATES_EX_LENGTH];
+ u8 rates_ex_len;
+ unsigned long last_scanned;
+ u8 mode;
+ u32 flags;
+ u32 last_associate;
+ u32 time_stamp[2];
+ u16 beacon_interval;
+ u16 listen_interval;
+ u16 atim_window;
+ u8 erp_value;
+ u8 wpa_ie[MAX_WPA_IE_LEN];
+ size_t wpa_ie_len;
+ u8 rsn_ie[MAX_WPA_IE_LEN];
+ size_t rsn_ie_len;
+ u8 wzc_ie[MAX_WZC_IE_LEN];
+ size_t wzc_ie_len;
+
+ struct rtllib_tim_parameters tim;
+ u8 dtim_period;
+ u8 dtim_data;
+ u64 last_dtim_sta_time;
+
+ u8 wmm_info;
+ struct rtllib_wmm_ac_param wmm_param[4];
+ u8 Turbo_Enable;
+ u16 CountryIeLen;
+ u8 CountryIeBuf[MAX_IE_LEN];
+ struct bss_ht bssht;
+ bool broadcom_cap_exist;
+ bool realtek_cap_exit;
+ bool marvell_cap_exist;
+ bool ralink_cap_exist;
+ bool atheros_cap_exist;
+ bool cisco_cap_exist;
+ bool airgo_cap_exist;
+ bool unknown_cap_exist;
+ bool berp_info_valid;
+ bool buseprotection;
+ bool bIsNetgear854T;
+ u8 SignalStrength;
+ u8 RSSI;
+ struct list_head list;
+};
+
+enum rtllib_state {
+
+ /* the card is not linked at all */
+ RTLLIB_NOLINK = 0,
+
+ /* RTLLIB_ASSOCIATING* are for BSS client mode
+ * the driver shall not perform RX filtering unless
+ * the state is LINKED.
+ * The driver shall just check for the state LINKED and
+ * defaults to NOLINK for ALL the other states (including
+ * LINKED_SCANNING)
+ */
+
+ /* the association procedure will start (wq scheduling)*/
+ RTLLIB_ASSOCIATING,
+ RTLLIB_ASSOCIATING_RETRY,
+
+ /* the association procedure is sending AUTH request*/
+ RTLLIB_ASSOCIATING_AUTHENTICATING,
+
+ /* the association procedure has successfully authenticated
+ * and is sending association request
+ */
+ RTLLIB_ASSOCIATING_AUTHENTICATED,
+
+ /* the link is ok. the card associated to a BSS or linked
+ * to a ibss cell or acting as an AP and creating the bss
+ */
+ RTLLIB_LINKED,
+
+ /* same as LINKED, but the driver shall apply RX filter
+ * rules as we are in NO_LINK mode. As the card is still
+ * logically linked, but it is doing a syncro site survey
+ * then it will be back to LINKED state.
+ */
+ RTLLIB_LINKED_SCANNING,
+};
+
+#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
+#define DEFAULT_FTS 2346
+
+#define CFG_RTLLIB_RESERVE_FCS (1<<0)
+#define CFG_RTLLIB_COMPUTE_FCS (1<<1)
+#define CFG_RTLLIB_RTS (1<<2)
+
+#define RTLLIB_24GHZ_MIN_CHANNEL 1
+#define RTLLIB_24GHZ_MAX_CHANNEL 14
+#define RTLLIB_24GHZ_CHANNELS (RTLLIB_24GHZ_MAX_CHANNEL - \
+ RTLLIB_24GHZ_MIN_CHANNEL + 1)
+
+#define RTLLIB_52GHZ_MIN_CHANNEL 34
+#define RTLLIB_52GHZ_MAX_CHANNEL 165
+#define RTLLIB_52GHZ_CHANNELS (RTLLIB_52GHZ_MAX_CHANNEL - \
+ RTLLIB_52GHZ_MIN_CHANNEL + 1)
+struct tx_pending {
+ int frag;
+ struct rtllib_txb *txb;
+};
+
+struct bandwidth_autoswitch {
+ long threshold_20Mhzto40Mhz;
+ long threshold_40Mhzto20Mhz;
+ bool bforced_tx20Mhz;
+ bool bautoswitch_enable;
+};
+
+
+
+#define REORDER_WIN_SIZE 128
+#define REORDER_ENTRY_NUM 128
+struct rx_reorder_entry {
+ struct list_head List;
+ u16 SeqNum;
+ struct rtllib_rxb *prxb;
+};
+enum fsync_state {
+ Default_Fsync,
+ HW_Fsync,
+ SW_Fsync
+};
+
+enum rt_ps_mode {
+ eActive,
+ eMaxPs,
+ eFastPs,
+ eAutoPs,
+};
+
+enum ips_callback_function {
+ IPS_CALLBACK_NONE = 0,
+ IPS_CALLBACK_MGNT_LINK_REQUEST = 1,
+ IPS_CALLBACK_JOIN_REQUEST = 2,
+};
+
+enum rt_join_action {
+ RT_JOIN_INFRA = 1,
+ RT_JOIN_IBSS = 2,
+ RT_START_IBSS = 3,
+ RT_NO_ACTION = 4,
+};
+
+struct ibss_parms {
+ u16 atimWin;
+};
+#define MAX_NUM_RATES 264
+
+enum rt_rf_power_state {
+ eRfOn,
+ eRfSleep,
+ eRfOff
+};
+
+#define MAX_SUPPORT_WOL_PATTERN_NUM 8
+
+#define MAX_WOL_BIT_MASK_SIZE 16
+#define MAX_WOL_PATTERN_SIZE 128
+
+enum wol_pattern_type {
+ eNetBIOS = 0,
+ eIPv4IPv6ARP,
+ eIPv4IPv6TCPSYN,
+ eMACIDOnly,
+ eNoDefined,
+};
+
+struct rt_pm_wol_info {
+ u32 PatternId;
+ u32 Mask[4];
+ u16 CrcRemainder;
+ u8 WFMIndex;
+ enum wol_pattern_type PatternType;
+};
+
+struct rt_pwr_save_ctrl {
+
+ bool bInactivePs;
+ bool bIPSModeBackup;
+ bool bHaltAdapterClkRQ;
+ bool bSwRfProcessing;
+ enum rt_rf_power_state eInactivePowerState;
+ struct work_struct InactivePsWorkItem;
+ struct timer_list InactivePsTimer;
+
+ enum ips_callback_function ReturnPoint;
+
+ bool bTmpBssDesc;
+ enum rt_join_action tmpJoinAction;
+ struct rtllib_network tmpBssDesc;
+
+ bool bTmpScanOnly;
+ bool bTmpActiveScan;
+ bool bTmpFilterHiddenAP;
+ bool bTmpUpdateParms;
+ u8 tmpSsidBuf[33];
+ struct octet_string tmpSsid2Scan;
+ bool bTmpSsid2Scan;
+ u8 tmpNetworkType;
+ u8 tmpChannelNumber;
+ u16 tmpBcnPeriod;
+ u8 tmpDtimPeriod;
+ u16 tmpmCap;
+ struct octet_string tmpSuppRateSet;
+ u8 tmpSuppRateBuf[MAX_NUM_RATES];
+ bool bTmpSuppRate;
+ struct ibss_parms tmpIbpm;
+ bool bTmpIbpm;
+
+ bool bLeisurePs;
+ u32 PowerProfile;
+ u8 LpsIdleCount;
+ u8 RegMaxLPSAwakeIntvl;
+ u8 LPSAwakeIntvl;
+
+ u32 CurPsLevel;
+ u32 RegRfPsLevel;
+
+ bool bFwCtrlLPS;
+ u8 FWCtrlPSMode;
+
+ bool LinkReqInIPSRFOffPgs;
+ bool BufConnectinfoBefore;
+
+
+ bool bGpioRfSw;
+
+ u8 RegAMDPciASPM;
+
+ u8 oWLANMode;
+ struct rt_pm_wol_info PmWoLPatternInfo[MAX_SUPPORT_WOL_PATTERN_NUM];
+
+};
+
+#define RT_RF_CHANGE_SOURCE u32
+
+#define RF_CHANGE_BY_SW BIT31
+#define RF_CHANGE_BY_HW BIT30
+#define RF_CHANGE_BY_PS BIT29
+#define RF_CHANGE_BY_IPS BIT28
+#define RF_CHANGE_BY_INIT 0
+
+enum country_code_type {
+ COUNTRY_CODE_FCC = 0,
+ COUNTRY_CODE_IC = 1,
+ COUNTRY_CODE_ETSI = 2,
+ COUNTRY_CODE_SPAIN = 3,
+ COUNTRY_CODE_FRANCE = 4,
+ COUNTRY_CODE_MKK = 5,
+ COUNTRY_CODE_MKK1 = 6,
+ COUNTRY_CODE_ISRAEL = 7,
+ COUNTRY_CODE_TELEC = 8,
+ COUNTRY_CODE_MIC = 9,
+ COUNTRY_CODE_GLOBAL_DOMAIN = 10,
+ COUNTRY_CODE_WORLD_WIDE_13 = 11,
+ COUNTRY_CODE_TELEC_NETGEAR = 12,
+ COUNTRY_CODE_MAX
+};
+
+enum scan_op_backup_opt {
+ SCAN_OPT_BACKUP = 0,
+ SCAN_OPT_RESTORE,
+ SCAN_OPT_MAX
+};
+
+enum fw_cmd_io_type {
+ FW_CMD_DIG_ENABLE = 0,
+ FW_CMD_DIG_DISABLE = 1,
+ FW_CMD_DIG_HALT = 2,
+ FW_CMD_DIG_RESUME = 3,
+ FW_CMD_HIGH_PWR_ENABLE = 4,
+ FW_CMD_HIGH_PWR_DISABLE = 5,
+ FW_CMD_RA_RESET = 6,
+ FW_CMD_RA_ACTIVE = 7,
+ FW_CMD_RA_REFRESH_N = 8,
+ FW_CMD_RA_REFRESH_BG = 9,
+ FW_CMD_RA_INIT = 10,
+ FW_CMD_IQK_ENABLE = 11,
+ FW_CMD_TXPWR_TRACK_ENABLE = 12,
+ FW_CMD_TXPWR_TRACK_DISABLE = 13,
+ FW_CMD_TXPWR_TRACK_THERMAL = 14,
+ FW_CMD_PAUSE_DM_BY_SCAN = 15,
+ FW_CMD_RESUME_DM_BY_SCAN = 16,
+ FW_CMD_RA_REFRESH_N_COMB = 17,
+ FW_CMD_RA_REFRESH_BG_COMB = 18,
+ FW_CMD_ANTENNA_SW_ENABLE = 19,
+ FW_CMD_ANTENNA_SW_DISABLE = 20,
+ FW_CMD_TX_FEEDBACK_CCX_ENABLE = 21,
+ FW_CMD_LPS_ENTER = 22,
+ FW_CMD_LPS_LEAVE = 23,
+ FW_CMD_DIG_MODE_SS = 24,
+ FW_CMD_DIG_MODE_FA = 25,
+ FW_CMD_ADD_A2_ENTRY = 26,
+ FW_CMD_CTRL_DM_BY_DRIVER = 27,
+ FW_CMD_CTRL_DM_BY_DRIVER_NEW = 28,
+ FW_CMD_PAPE_CONTROL = 29,
+ FW_CMD_CHAN_SET = 30,
+};
+
+#define RT_MAX_LD_SLOT_NUM 10
+struct rt_link_detect {
+
+ u32 NumRecvBcnInPeriod;
+ u32 NumRecvDataInPeriod;
+
+ u32 RxBcnNum[RT_MAX_LD_SLOT_NUM];
+ u32 RxDataNum[RT_MAX_LD_SLOT_NUM];
+ u16 SlotNum;
+ u16 SlotIndex;
+
+ u32 NumTxOkInPeriod;
+ u32 NumRxOkInPeriod;
+ u32 NumRxUnicastOkInPeriod;
+ bool bBusyTraffic;
+ bool bHigherBusyTraffic;
+ bool bHigherBusyRxTraffic;
+ u8 IdleCount;
+ u32 NumTxUnicastOkInPeriod;
+ u32 LastNumTxUnicast;
+ u32 LastNumRxUnicast;
+};
+
+struct sw_cam_table {
+
+ u8 macaddr[6];
+ bool bused;
+ u8 key_buf[16];
+ u16 key_type;
+ u8 useDK;
+ u8 key_index;
+
+};
+#define TOTAL_CAM_ENTRY 32
+struct rate_adaptive {
+ u8 rate_adaptive_disabled;
+ u8 ratr_state;
+ u16 reserve;
+
+ u32 high_rssi_thresh_for_ra;
+ u32 high2low_rssi_thresh_for_ra;
+ u8 low2high_rssi_thresh_for_ra40M;
+ u32 low_rssi_thresh_for_ra40M;
+ u8 low2high_rssi_thresh_for_ra20M;
+ u32 low_rssi_thresh_for_ra20M;
+ u32 upper_rssi_threshold_ratr;
+ u32 middle_rssi_threshold_ratr;
+ u32 low_rssi_threshold_ratr;
+ u32 low_rssi_threshold_ratr_40M;
+ u32 low_rssi_threshold_ratr_20M;
+ u8 ping_rssi_enable;
+ u32 ping_rssi_ratr;
+ u32 ping_rssi_thresh_for_ra;
+ u32 last_ratr;
+ u8 PreRATRState;
+
+};
+enum ratr_table_mode_8192s {
+ RATR_INX_WIRELESS_NGB = 0,
+ RATR_INX_WIRELESS_NG = 1,
+ RATR_INX_WIRELESS_NB = 2,
+ RATR_INX_WIRELESS_N = 3,
+ RATR_INX_WIRELESS_GB = 4,
+ RATR_INX_WIRELESS_G = 5,
+ RATR_INX_WIRELESS_B = 6,
+ RATR_INX_WIRELESS_MC = 7,
+ RATR_INX_WIRELESS_A = 8,
+};
+
+#define NUM_PMKID_CACHE 16
+struct rt_pmkid_list {
+ u8 bUsed;
+ u8 Bssid[6];
+ u8 PMKID[16];
+ u8 SsidBuf[33];
+ u8 *ssid_octet;
+ u16 ssid_length;
+};
+
+struct rt_intel_promisc_mode {
+ bool bPromiscuousOn;
+ bool bFilterSourceStationFrame;
+};
+
+
+/*************** DRIVER STATUS *****/
+#define STATUS_SCANNING 0
+#define STATUS_SCAN_HW 1
+#define STATUS_SCAN_ABORTING 2
+#define STATUS_SETTING_CHAN 3
+/*************** DRIVER STATUS *****/
+
+enum {
+ NO_USE = 0,
+ USED = 1,
+ HW_SEC = 2,
+ SW_SEC = 3,
+};
+
+enum {
+ LPS_IS_WAKE = 0,
+ LPS_IS_SLEEP = 1,
+ LPS_WAIT_NULL_DATA_SEND = 2,
+};
+
+struct rtllib_device {
+ struct pci_dev *pdev;
+ struct net_device *dev;
+ struct rtllib_security sec;
+
+ bool disable_mgnt_queue;
+
+ unsigned long status;
+ short hwscan_ch_bk;
+ enum ht_extchnl_offset chan_offset_bk;
+ enum ht_channel_width bandwidth_bk;
+ u8 hwscan_sem_up;
+ u8 CntAfterLink;
+
+ enum rt_op_mode OpMode;
+
+ u8 VersionID;
+ /* The last AssocReq/Resp IEs */
+ u8 *assocreq_ies, *assocresp_ies;
+ size_t assocreq_ies_len, assocresp_ies_len;
+
+ bool b_customer_lenovo_id;
+ bool bForcedShowRxRate;
+ bool bForcedShowRateStill;
+ u8 SystemQueryDataRateCount;
+ bool bForcedBgMode;
+ bool bUseRAMask;
+ bool b1x1RecvCombine;
+ u8 RF_Type;
+ bool b1SSSupport;
+
+ u8 hwsec_active;
+ bool is_silent_reset;
+ bool force_mic_error;
+ bool is_roaming;
+ bool ieee_up;
+ bool cannot_notify;
+ bool bSupportRemoteWakeUp;
+ enum rt_ps_mode dot11PowerSaveMode;
+ bool actscanning;
+ bool FirstIe_InScan;
+ bool be_scan_inprogress;
+ bool beinretry;
+ enum rt_rf_power_state eRFPowerState;
+ RT_RF_CHANGE_SOURCE RfOffReason;
+ bool is_set_key;
+ bool wx_set_enc;
+ struct rt_hi_throughput *pHTInfo;
+ spinlock_t bw_spinlock;
+
+ spinlock_t reorder_spinlock;
+ u8 Regdot11HTOperationalRateSet[16];
+ u8 Regdot11TxHTOperationalRateSet[16];
+ u8 dot11HTOperationalRateSet[16];
+ u8 RegHTSuppRateSet[16];
+ u8 HTCurrentOperaRate;
+ u8 HTHighestOperaRate;
+ u8 MinSpaceCfg;
+ u8 MaxMssDensity;
+ u8 bTxDisableRateFallBack;
+ u8 bTxUseDriverAssingedRate;
+ u8 bTxEnableFwCalcDur;
+ atomic_t atm_chnlop;
+ atomic_t atm_swbw;
+
+ struct list_head Tx_TS_Admit_List;
+ struct list_head Tx_TS_Pending_List;
+ struct list_head Tx_TS_Unused_List;
+ struct tx_ts_record TxTsRecord[TOTAL_TS_NUM];
+ struct list_head Rx_TS_Admit_List;
+ struct list_head Rx_TS_Pending_List;
+ struct list_head Rx_TS_Unused_List;
+ struct rx_ts_record RxTsRecord[TOTAL_TS_NUM];
+ struct rx_reorder_entry RxReorderEntry[128];
+ struct list_head RxReorder_Unused_List;
+ u8 ForcedPriority;
+
+
+ /* Bookkeeping structures */
+ struct net_device_stats stats;
+ struct rtllib_stats ieee_stats;
+ struct rtllib_softmac_stats softmac_stats;
+
+ /* Probe / Beacon management */
+ struct list_head network_free_list;
+ struct list_head network_list;
+ struct rtllib_network *networks;
+ int scans;
+ int scan_age;
+
+ int iw_mode; /* operating mode (IW_MODE_*) */
+ bool bNetPromiscuousMode;
+ struct rt_intel_promisc_mode IntelPromiscuousModeInfo;
+
+ struct iw_spy_data spy_data;
+
+ spinlock_t lock;
+ spinlock_t wpax_suitlist_lock;
+
+ int tx_headroom; /* Set to size of any additional room needed at front
+ * of allocated Tx SKBs
+ */
+ u32 config;
+
+ /* WEP and other encryption related settings at the device level */
+ int open_wep; /* Set to 1 to allow unencrypted frames */
+ int auth_mode;
+ int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
+ * WEP key changes
+ */
+
+ /* If the host performs {en,de}cryption, then set to 1 */
+ int host_encrypt;
+ int host_encrypt_msdu;
+ int host_decrypt;
+ /* host performs multicast decryption */
+ int host_mc_decrypt;
+
+ /* host should strip IV and ICV from protected frames */
+ /* meaningful only when hardware decryption is being used */
+ int host_strip_iv_icv;
+
+ int host_open_frag;
+ int host_build_iv;
+ int ieee802_1x; /* is IEEE 802.1X used */
+
+ /* WPA data */
+ bool bHalfNMode;
+ bool bHalfWirelessN24GMode;
+ int wpa_enabled;
+ int drop_unencrypted;
+ int tkip_countermeasures;
+ int privacy_invoked;
+ size_t wpa_ie_len;
+ u8 *wpa_ie;
+ size_t wps_ie_len;
+ u8 *wps_ie;
+ u8 ap_mac_addr[6];
+ u16 pairwise_key_type;
+ u16 group_key_type;
+
+ struct lib80211_crypt_info crypt_info;
+
+ struct sw_cam_table swcamtable[TOTAL_CAM_ENTRY];
+ int bcrx_sta_key; /* use individual keys to override default keys even
+ * with RX of broad/multicast frames */
+
+ struct rt_pmkid_list PMKIDList[NUM_PMKID_CACHE];
+
+ /* Fragmentation structures */
+ struct rtllib_frag_entry frag_cache[17][RTLLIB_FRAG_CACHE_LEN];
+ unsigned int frag_next_idx[17];
+ u16 fts; /* Fragmentation Threshold */
+#define DEFAULT_RTS_THRESHOLD 2346U
+#define MIN_RTS_THRESHOLD 1
+#define MAX_RTS_THRESHOLD 2346U
+ u16 rts; /* RTS threshold */
+
+ /* Association info */
+ u8 bssid[ETH_ALEN];
+
+ /* This stores infos for the current network.
+ * Either the network we are associated in INFRASTRUCTURE
+ * or the network that we are creating in MASTER mode.
+ * ad-hoc is a mixture ;-).
+ * Note that in infrastructure mode, even when not associated,
+ * fields bssid and essid may be valid (if wpa_set and essid_set
+ * are true) as thy carry the value set by the user via iwconfig
+ */
+ struct rtllib_network current_network;
+
+ enum rtllib_state state;
+
+ int short_slot;
+ int reg_mode;
+ int mode; /* A, B, G */
+ int modulation; /* CCK, OFDM */
+ int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */
+ int abg_true; /* ABG flag */
+
+ /* used for forcing the ibss workqueue to terminate
+ * without wait for the syncro scan to terminate
+ */
+ short sync_scan_hurryup;
+ u16 scan_watch_dog;
+ int perfect_rssi;
+ int worst_rssi;
+
+ u16 prev_seq_ctl; /* used to drop duplicate frames */
+
+ /* map of allowed channels. 0 is dummy */
+ void *pDot11dInfo;
+ bool bGlobalDomain;
+ u8 active_channel_map[MAX_CHANNEL_NUMBER+1];
+
+ u8 IbssStartChnl;
+ u8 ibss_maxjoin_chal;
+
+ int rate; /* current rate */
+ int basic_rate;
+ u32 currentRate;
+
+ short active_scan;
+
+ /* this contains flags for selectively enable softmac support */
+ u16 softmac_features;
+
+ /* if the sequence control field is not filled by HW */
+ u16 seq_ctrl[5];
+
+ /* association procedure transaction sequence number */
+ u16 associate_seq;
+
+ /* AID for RTXed association responses */
+ u16 assoc_id;
+
+ /* power save mode related*/
+ u8 ack_tx_to_ieee;
+ short ps;
+ short sta_sleep;
+ int ps_timeout;
+ int ps_period;
+ struct tasklet_struct ps_task;
+ u64 ps_time;
+ bool polling;
+
+ short raw_tx;
+ /* used if IEEE_SOFTMAC_TX_QUEUE is set */
+ short queue_stop;
+ short scanning_continue;
+ short proto_started;
+ short proto_stoppping;
+
+ struct semaphore wx_sem;
+ struct semaphore scan_sem;
+ struct semaphore ips_sem;
+
+ spinlock_t mgmt_tx_lock;
+ spinlock_t beacon_lock;
+
+ short beacon_txing;
+
+ short wap_set;
+ short ssid_set;
+
+ /* set on initialization */
+ u8 qos_support;
+ unsigned int wmm_acm;
+
+ /* for discarding duplicated packets in IBSS */
+ struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE];
+
+ /* for discarding duplicated packets in BSS */
+ u16 last_rxseq_num[17]; /* rx seq previous per-tid */
+ u16 last_rxfrag_num[17];/* tx frag previous per-tid */
+ unsigned long last_packet_time[17];
+
+ /* for PS mode */
+ unsigned long last_rx_ps_time;
+ bool bAwakePktSent;
+ u8 LPSDelayCnt;
+
+ /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */
+ struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM];
+ int mgmt_queue_head;
+ int mgmt_queue_tail;
+#define RTLLIB_QUEUE_LIMIT 128
+ u8 AsocRetryCount;
+ unsigned int hw_header;
+ struct sk_buff_head skb_waitQ[MAX_QUEUE_SIZE];
+ struct sk_buff_head skb_aggQ[MAX_QUEUE_SIZE];
+ struct sk_buff_head skb_drv_aggQ[MAX_QUEUE_SIZE];
+ u32 sta_edca_param[4];
+ bool aggregation;
+ bool enable_rx_imm_BA;
+ bool bibsscoordinator;
+
+ bool bdynamic_txpower_enable;
+
+ bool bCTSToSelfEnable;
+ u8 CTSToSelfTH;
+
+ u32 fsync_time_interval;
+ u32 fsync_rate_bitmap;
+ u8 fsync_rssi_threshold;
+ bool bfsync_enable;
+
+ u8 fsync_multiple_timeinterval;
+ u32 fsync_firstdiff_ratethreshold;
+ u32 fsync_seconddiff_ratethreshold;
+ enum fsync_state fsync_state;
+ bool bis_any_nonbepkts;
+ struct bandwidth_autoswitch bandwidth_auto_switch;
+ bool FwRWRF;
+
+ struct rt_link_detect LinkDetectInfo;
+ bool bIsAggregateFrame;
+ struct rt_pwr_save_ctrl PowerSaveControl;
+ u8 amsdu_in_process;
+
+ /* used if IEEE_SOFTMAC_TX_QUEUE is set */
+ struct tx_pending tx_pending;
+
+ /* used if IEEE_SOFTMAC_ASSOCIATE is set */
+ struct timer_list associate_timer;
+
+ /* used if IEEE_SOFTMAC_BEACONS is set */
+ struct timer_list beacon_timer;
+ u8 need_sw_enc;
+ struct work_struct associate_complete_wq;
+ struct work_struct ips_leave_wq;
+ struct delayed_work associate_procedure_wq;
+ struct delayed_work softmac_scan_wq;
+ struct delayed_work softmac_hint11d_wq;
+ struct delayed_work associate_retry_wq;
+ struct delayed_work start_ibss_wq;
+ struct delayed_work hw_wakeup_wq;
+ struct delayed_work hw_sleep_wq;
+ struct delayed_work link_change_wq;
+ struct work_struct wx_sync_scan_wq;
+
+ struct workqueue_struct *wq;
+ union {
+ struct rtllib_rxb *RfdArray[REORDER_WIN_SIZE];
+ struct rtllib_rxb *stats_IndicateArray[REORDER_WIN_SIZE];
+ struct rtllib_rxb *prxbIndicateArray[REORDER_WIN_SIZE];
+ struct {
+ struct sw_chnl_cmd PreCommonCmd[MAX_PRECMD_CNT];
+ struct sw_chnl_cmd PostCommonCmd[MAX_POSTCMD_CNT];
+ struct sw_chnl_cmd RfDependCmd[MAX_RFDEPENDCMD_CNT];
+ };
+ };
+
+ /* Callback functions */
+ void (*set_security)(struct net_device *dev,
+ struct rtllib_security *sec);
+
+ /* Used to TX data frame by using txb structs.
+ * this is not used if in the softmac_features
+ * is set the flag IEEE_SOFTMAC_TX_QUEUE
+ */
+ int (*hard_start_xmit)(struct rtllib_txb *txb,
+ struct net_device *dev);
+
+ int (*reset_port)(struct net_device *dev);
+ int (*is_queue_full)(struct net_device *dev, int pri);
+
+ int (*handle_management)(struct net_device *dev,
+ struct rtllib_network *network, u16 type);
+ int (*is_qos_active)(struct net_device *dev, struct sk_buff *skb);
+
+ /* Softmac-generated frames (management) are TXed via this
+ * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
+ * not set. As some cards may have different HW queues that
+ * one might want to use for data and management frames
+ * the option to have two callbacks might be useful.
+ * This function can't sleep.
+ */
+ int (*softmac_hard_start_xmit)(struct sk_buff *skb,
+ struct net_device *dev);
+
+ /* used instead of hard_start_xmit (not softmac_hard_start_xmit)
+ * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
+ * frames. If the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
+ * then also management frames are sent via this callback.
+ * This function can't sleep.
+ */
+ void (*softmac_data_hard_start_xmit)(struct sk_buff *skb,
+ struct net_device *dev, int rate);
+
+ /* stops the HW queue for DATA frames. Useful to avoid
+ * waste time to TX data frame when we are reassociating
+ * This function can sleep.
+ */
+ void (*data_hard_stop)(struct net_device *dev);
+
+ /* OK this is complementing to data_poll_hard_stop */
+ void (*data_hard_resume)(struct net_device *dev);
+
+ /* ask to the driver to retune the radio.
+ * This function can sleep. the driver should ensure
+ * the radio has been switched before return.
+ */
+ void (*set_chan)(struct net_device *dev, short ch);
+
+ /* These are not used if the ieee stack takes care of
+ * scanning (IEEE_SOFTMAC_SCAN feature set).
+ * In this case only the set_chan is used.
+ *
+ * The syncro version is similar to the start_scan but
+ * does not return until all channels has been scanned.
+ * this is called in user context and should sleep,
+ * it is called in a work_queue when switching to ad-hoc mode
+ * or in behalf of iwlist scan when the card is associated
+ * and root user ask for a scan.
+ * the function stop_scan should stop both the syncro and
+ * background scanning and can sleep.
+ * The function start_scan should initiate the background
+ * scanning and can't sleep.
+ */
+ void (*scan_syncro)(struct net_device *dev);
+ void (*start_scan)(struct net_device *dev);
+ void (*stop_scan)(struct net_device *dev);
+
+ void (*rtllib_start_hw_scan)(struct net_device *dev);
+ void (*rtllib_stop_hw_scan)(struct net_device *dev);
+
+ /* indicate the driver that the link state is changed
+ * for example it may indicate the card is associated now.
+ * Driver might be interested in this to apply RX filter
+ * rules or simply light the LINK led
+ */
+ void (*link_change)(struct net_device *dev);
+
+ /* these two function indicates to the HW when to start
+ * and stop to send beacons. This is used when the
+ * IEEE_SOFTMAC_BEACONS is not set. For now the
+ * stop_send_bacons is NOT guaranteed to be called only
+ * after start_send_beacons.
+ */
+ void (*start_send_beacons)(struct net_device *dev);
+ void (*stop_send_beacons)(struct net_device *dev);
+
+ /* power save mode related */
+ void (*sta_wake_up)(struct net_device *dev);
+ void (*enter_sleep_state)(struct net_device *dev, u64 time);
+ short (*ps_is_queue_empty)(struct net_device *dev);
+ int (*handle_beacon)(struct net_device *dev,
+ struct rtllib_beacon *beacon,
+ struct rtllib_network *network);
+ int (*handle_assoc_response)(struct net_device *dev,
+ struct rtllib_assoc_response_frame *resp,
+ struct rtllib_network *network);
+
+
+ /* check whether Tx hw resource available */
+ short (*check_nic_enough_desc)(struct net_device *dev, int queue_index);
+ short (*get_nic_desc_num)(struct net_device *dev, int queue_index);
+ void (*SetBWModeHandler)(struct net_device *dev,
+ enum ht_channel_width Bandwidth,
+ enum ht_extchnl_offset Offset);
+ bool (*GetNmodeSupportBySecCfg)(struct net_device *dev);
+ void (*SetWirelessMode)(struct net_device *dev, u8 wireless_mode);
+ bool (*GetHalfNmodeSupportByAPsHandler)(struct net_device *dev);
+ u8 (*rtllib_ap_sec_type)(struct rtllib_device *ieee);
+ void (*HalUsbRxAggrHandler)(struct net_device *dev, bool Value);
+ void (*InitialGainHandler)(struct net_device *dev, u8 Operation);
+ bool (*SetFwCmdHandler)(struct net_device *dev,
+ enum fw_cmd_io_type FwCmdIO);
+ void (*UpdateHalRAMaskHandler)(struct net_device *dev, bool bMulticast,
+ u8 macId, u8 MimoPs, u8 WirelessMode,
+ u8 bCurTxBW40MHz, u8 rssi_level);
+ void (*UpdateBeaconInterruptHandler)(struct net_device *dev,
+ bool start);
+ void (*UpdateInterruptMaskHandler)(struct net_device *dev, u32 AddMSR,
+ u32 RemoveMSR);
+ u16 (*rtl_11n_user_show_rates)(struct net_device *dev);
+ void (*ScanOperationBackupHandler)(struct net_device *dev,
+ u8 Operation);
+ void (*LedControlHandler)(struct net_device *dev,
+ enum led_ctl_mode LedAction);
+ void (*SetHwRegHandler)(struct net_device *dev, u8 variable, u8 *val);
+ void (*GetHwRegHandler)(struct net_device *dev, u8 variable, u8 *val);
+
+ void (*AllowAllDestAddrHandler)(struct net_device *dev,
+ bool bAllowAllDA, bool WriteIntoReg);
+
+ void (*rtllib_ips_leave_wq)(struct net_device *dev);
+ void (*rtllib_ips_leave)(struct net_device *dev);
+ void (*LeisurePSLeave)(struct net_device *dev);
+ void (*rtllib_rfkill_poll)(struct net_device *dev);
+
+ /* This must be the last item so that it points to the data
+ * allocated beyond this structure by alloc_rtllib
+ */
+ u8 priv[0];
+};
+
+#define IEEE_A (1<<0)
+#define IEEE_B (1<<1)
+#define IEEE_G (1<<2)
+#define IEEE_N_24G (1<<4)
+#define IEEE_N_5G (1<<5)
+#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G)
+
+/* Generate a 802.11 header */
+
+/* Uses the channel change callback directly
+ * instead of [start/stop] scan callbacks
+ */
+#define IEEE_SOFTMAC_SCAN (1<<2)
+
+/* Perform authentication and association handshake */
+#define IEEE_SOFTMAC_ASSOCIATE (1<<3)
+
+/* Generate probe requests */
+#define IEEE_SOFTMAC_PROBERQ (1<<4)
+
+/* Generate response to probe requests */
+#define IEEE_SOFTMAC_PROBERS (1<<5)
+
+/* The ieee802.11 stack will manage the netif queue
+ * wake/stop for the driver, taking care of 802.11
+ * fragmentation. See softmac.c for details.
+ */
+#define IEEE_SOFTMAC_TX_QUEUE (1<<7)
+
+/* Uses only the softmac_data_hard_start_xmit
+ * even for TX management frames.
+ */
+#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8)
+
+/* Generate beacons. The stack will enqueue beacons
+ * to the card
+ */
+#define IEEE_SOFTMAC_BEACONS (1<<6)
+
+
+static inline void *rtllib_priv(struct net_device *dev)
+{
+ return ((struct rtllib_device *)netdev_priv(dev))->priv;
+}
+
+static inline int rtllib_is_empty_essid(const char *essid, int essid_len)
+{
+ /* Single white space is for Linksys APs */
+ if (essid_len == 1 && essid[0] == ' ')
+ return 1;
+
+ /* Otherwise, if the entire essid is 0, we assume it is hidden */
+ while (essid_len) {
+ essid_len--;
+ if (essid[essid_len] != '\0')
+ return 0;
+ }
+
+ return 1;
+}
+
+static inline int rtllib_is_valid_mode(struct rtllib_device *ieee, int mode)
+{
+ /* It is possible for both access points and our device to support
+ * combinations of modes, so as long as there is one valid combination
+ * of ap/device supported modes, then return success
+ */
+ if ((mode & IEEE_A) &&
+ (ieee->modulation & RTLLIB_OFDM_MODULATION) &&
+ (ieee->freq_band & RTLLIB_52GHZ_BAND))
+ return 1;
+
+ if ((mode & IEEE_G) &&
+ (ieee->modulation & RTLLIB_OFDM_MODULATION) &&
+ (ieee->freq_band & RTLLIB_24GHZ_BAND))
+ return 1;
+
+ if ((mode & IEEE_B) &&
+ (ieee->modulation & RTLLIB_CCK_MODULATION) &&
+ (ieee->freq_band & RTLLIB_24GHZ_BAND))
+ return 1;
+
+ return 0;
+}
+
+static inline int rtllib_get_hdrlen(u16 fc)
+{
+ int hdrlen = RTLLIB_3ADDR_LEN;
+
+ switch (WLAN_FC_GET_TYPE(fc)) {
+ case RTLLIB_FTYPE_DATA:
+ if ((fc & RTLLIB_FCTL_FROMDS) && (fc & RTLLIB_FCTL_TODS))
+ hdrlen = RTLLIB_4ADDR_LEN; /* Addr4 */
+ if (RTLLIB_QOS_HAS_SEQ(fc))
+ hdrlen += 2; /* QOS ctrl*/
+ break;
+ case RTLLIB_FTYPE_CTL:
+ switch (WLAN_FC_GET_STYPE(fc)) {
+ case RTLLIB_STYPE_CTS:
+ case RTLLIB_STYPE_ACK:
+ hdrlen = RTLLIB_1ADDR_LEN;
+ break;
+ default:
+ hdrlen = RTLLIB_2ADDR_LEN;
+ break;
+ }
+ break;
+ }
+
+ return hdrlen;
+}
+
+static inline u8 *rtllib_get_payload(struct rtllib_hdr *hdr)
+{
+ switch (rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) {
+ case RTLLIB_1ADDR_LEN:
+ return ((struct rtllib_hdr_1addr *)hdr)->payload;
+ case RTLLIB_2ADDR_LEN:
+ return ((struct rtllib_hdr_2addr *)hdr)->payload;
+ case RTLLIB_3ADDR_LEN:
+ return ((struct rtllib_hdr_3addr *)hdr)->payload;
+ case RTLLIB_4ADDR_LEN:
+ return ((struct rtllib_hdr_4addr *)hdr)->payload;
+ }
+ return NULL;
+}
+
+static inline int rtllib_is_ofdm_rate(u8 rate)
+{
+ switch (rate & ~RTLLIB_BASIC_RATE_MASK) {
+ case RTLLIB_OFDM_RATE_6MB:
+ case RTLLIB_OFDM_RATE_9MB:
+ case RTLLIB_OFDM_RATE_12MB:
+ case RTLLIB_OFDM_RATE_18MB:
+ case RTLLIB_OFDM_RATE_24MB:
+ case RTLLIB_OFDM_RATE_36MB:
+ case RTLLIB_OFDM_RATE_48MB:
+ case RTLLIB_OFDM_RATE_54MB:
+ return 1;
+ }
+ return 0;
+}
+
+static inline int rtllib_is_cck_rate(u8 rate)
+{
+ switch (rate & ~RTLLIB_BASIC_RATE_MASK) {
+ case RTLLIB_CCK_RATE_1MB:
+ case RTLLIB_CCK_RATE_2MB:
+ case RTLLIB_CCK_RATE_5MB:
+ case RTLLIB_CCK_RATE_11MB:
+ return 1;
+ }
+ return 0;
+}
+
+
+/* rtllib.c */
+extern void free_rtllib(struct net_device *dev);
+extern struct net_device *alloc_rtllib(int sizeof_priv);
+
+extern int rtllib_set_encryption(struct rtllib_device *ieee);
+
+/* rtllib_tx.c */
+
+extern int rtllib_encrypt_fragment(
+ struct rtllib_device *ieee,
+ struct sk_buff *frag,
+ int hdr_len);
+
+extern int rtllib_xmit(struct sk_buff *skb, struct net_device *dev);
+extern int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev);
+extern void rtllib_txb_free(struct rtllib_txb *);
+
+/* rtllib_rx.c */
+extern int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats);
+extern void rtllib_rx_mgt(struct rtllib_device *ieee,
+ struct sk_buff *skb,
+ struct rtllib_rx_stats *stats);
+extern void rtllib_rx_probe_rq(struct rtllib_device *ieee,
+ struct sk_buff *skb);
+extern int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel);
+
+/* rtllib_wx.c */
+extern int rtllib_wx_get_scan(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key);
+extern int rtllib_wx_set_encode(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key);
+extern int rtllib_wx_get_encode(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key);
+#if WIRELESS_EXT >= 18
+extern int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+extern int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+#endif
+extern int rtllib_wx_set_auth(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra);
+extern int rtllib_wx_set_mlme(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+extern int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len);
+
+/* rtllib_softmac.c */
+extern short rtllib_is_54g(struct rtllib_network *net);
+extern short rtllib_is_shortslot(const struct rtllib_network *net);
+extern int rtllib_rx_frame_softmac(struct rtllib_device *ieee,
+ struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats, u16 type,
+ u16 stype);
+extern void rtllib_softmac_new_net(struct rtllib_device *ieee,
+ struct rtllib_network *net);
+
+void SendDisassociation(struct rtllib_device *ieee, bool deauth, u16 asRsn);
+extern void rtllib_softmac_xmit(struct rtllib_txb *txb,
+ struct rtllib_device *ieee);
+
+extern void rtllib_stop_send_beacons(struct rtllib_device *ieee);
+extern void notify_wx_assoc_event(struct rtllib_device *ieee);
+extern void rtllib_softmac_check_all_nets(struct rtllib_device *ieee);
+extern void rtllib_start_bss(struct rtllib_device *ieee);
+extern void rtllib_start_master_bss(struct rtllib_device *ieee);
+extern void rtllib_start_ibss(struct rtllib_device *ieee);
+extern void rtllib_softmac_init(struct rtllib_device *ieee);
+extern void rtllib_softmac_free(struct rtllib_device *ieee);
+extern void rtllib_associate_abort(struct rtllib_device *ieee);
+extern void rtllib_disassociate(struct rtllib_device *ieee);
+extern void rtllib_stop_scan(struct rtllib_device *ieee);
+extern bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan);
+extern void rtllib_stop_scan_syncro(struct rtllib_device *ieee);
+extern void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh);
+extern void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee,
+ short pwr);
+extern void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl);
+extern void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee);
+extern void rtllib_check_all_nets(struct rtllib_device *ieee);
+extern void rtllib_start_protocol(struct rtllib_device *ieee);
+extern void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown);
+
+extern void rtllib_EnableNetMonitorMode(struct net_device *dev,
+ bool bInitState);
+extern void rtllib_DisableNetMonitorMode(struct net_device *dev,
+ bool bInitState);
+extern void rtllib_EnableIntelPromiscuousMode(struct net_device *dev,
+ bool bInitState);
+extern void rtllib_DisableIntelPromiscuousMode(struct net_device *dev,
+ bool bInitState);
+extern void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh);
+
+extern void rtllib_softmac_stop_protocol(struct rtllib_device *ieee,
+ u8 mesh_flag, u8 shutdown);
+extern void rtllib_softmac_start_protocol(struct rtllib_device *ieee,
+ u8 mesh_flag);
+
+extern void rtllib_reset_queue(struct rtllib_device *ieee);
+extern void rtllib_wake_queue(struct rtllib_device *ieee);
+extern void rtllib_stop_queue(struct rtllib_device *ieee);
+extern void rtllib_wake_all_queues(struct rtllib_device *ieee);
+extern void rtllib_stop_all_queues(struct rtllib_device *ieee);
+extern struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee);
+extern void rtllib_start_send_beacons(struct rtllib_device *ieee);
+extern void rtllib_stop_send_beacons(struct rtllib_device *ieee);
+extern int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee,
+ struct iw_point *p, u8 is_mesh);
+
+extern void notify_wx_assoc_event(struct rtllib_device *ieee);
+extern void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success);
+
+extern void softmac_mgmt_xmit(struct sk_buff *skb,
+ struct rtllib_device *ieee);
+extern u16 rtllib_query_seqnum(struct rtllib_device *ieee,
+ struct sk_buff *skb, u8 *dst);
+extern u8 rtllib_ap_sec_type(struct rtllib_device *ieee);
+
+/* rtllib_crypt_ccmp&tkip&wep.c */
+extern void rtllib_tkip_null(void);
+extern void rtllib_wep_null(void);
+extern void rtllib_ccmp_null(void);
+
+/* rtllib_softmac_wx.c */
+
+extern int rtllib_wx_get_wap(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *ext);
+
+extern int rtllib_wx_set_wap(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *awrq,
+ char *extra);
+
+extern int rtllib_wx_get_essid(struct rtllib_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
+
+extern int rtllib_wx_set_rate(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_get_rate(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_set_mode(struct rtllib_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
+
+extern int rtllib_wx_set_scan(struct rtllib_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
+
+extern int rtllib_wx_set_essid(struct rtllib_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_get_mode(struct rtllib_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
+
+extern int rtllib_wx_set_freq(struct rtllib_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
+
+extern int rtllib_wx_get_freq(struct rtllib_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
+extern void rtllib_wx_sync_scan_wq(void *data);
+
+extern int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_get_name(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_set_power(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_get_power(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_set_rts(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+
+extern int rtllib_wx_get_rts(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+#define MAX_RECEIVE_BUFFER_SIZE 9100
+
+void HTSetConnectBwMode(struct rtllib_device *ieee,
+ enum ht_channel_width Bandwidth,
+ enum ht_extchnl_offset Offset);
+extern void HTUpdateDefaultSetting(struct rtllib_device *ieee);
+extern void HTConstructCapabilityElement(struct rtllib_device *ieee,
+ u8 *posHTCap, u8 *len,
+ u8 isEncrypt, bool bAssoc);
+extern void HTConstructInfoElement(struct rtllib_device *ieee,
+ u8 *posHTInfo, u8 *len, u8 isEncrypt);
+extern void HTConstructRT2RTAggElement(struct rtllib_device *ieee,
+ u8 *posRT2RTAgg, u8 *len);
+extern void HTOnAssocRsp(struct rtllib_device *ieee);
+extern void HTInitializeHTInfo(struct rtllib_device *ieee);
+extern void HTInitializeBssDesc(struct bss_ht *pBssHT);
+extern void HTResetSelfAndSavePeerSetting(struct rtllib_device *ieee,
+ struct rtllib_network *pNetwork);
+extern void HT_update_self_and_peer_setting(struct rtllib_device *ieee,
+ struct rtllib_network *pNetwork);
+extern u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
+ u8 *pMCSFilter);
+extern u8 MCS_FILTER_ALL[];
+extern u16 MCS_DATA_RATE[2][2][77];
+extern u8 HTCCheck(struct rtllib_device *ieee, u8 *pFrame);
+extern void HTResetIOTSetting(struct rt_hi_throughput *pHTInfo);
+extern bool IsHTHalfNmodeAPs(struct rtllib_device *ieee);
+extern u16 HTMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate);
+extern u16 TxCountToDataRate(struct rtllib_device *ieee, u8 nDataRate);
+extern int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb);
+extern int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb);
+extern int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb);
+extern void TsInitAddBA(struct rtllib_device *ieee, struct tx_ts_record *pTS,
+ u8 Policy, u8 bOverwritePending);
+extern void TsInitDelBA(struct rtllib_device *ieee,
+ struct ts_common_info *pTsCommonInfo,
+ enum tr_select TxRxSelect);
+extern void BaSetupTimeOut(unsigned long data);
+extern void TxBaInactTimeout(unsigned long data);
+extern void RxBaInactTimeout(unsigned long data);
+extern void ResetBaEntry(struct ba_record *pBA);
+extern bool GetTs(
+ struct rtllib_device *ieee,
+ struct ts_common_info **ppTS,
+ u8 *Addr,
+ u8 TID,
+ enum tr_select TxRxSelect,
+ bool bAddNewTs
+);
+extern void TSInitialize(struct rtllib_device *ieee);
+extern void TsStartAddBaProcess(struct rtllib_device *ieee,
+ struct tx_ts_record *pTxTS);
+extern void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr);
+extern void RemoveAllTS(struct rtllib_device *ieee);
+void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh);
+
+extern const long rtllib_wlan_frequencies[];
+
+static inline void rtllib_increment_scans(struct rtllib_device *ieee)
+{
+ ieee->scans++;
+}
+
+static inline int rtllib_get_scans(struct rtllib_device *ieee)
+{
+ return ieee->scans;
+}
+
+static inline const char *escape_essid(const char *essid, u8 essid_len)
+{
+ static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
+
+ if (rtllib_is_empty_essid(essid, essid_len)) {
+ memcpy(escaped, "<hidden>", sizeof("<hidden>"));
+ return escaped;
+ }
+
+ snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid);
+ return escaped;
+}
+
+#define CONVERT_RATE(_ieee, _MGN_RATE) \
+ ((_MGN_RATE < MGN_MCS0) ? (_MGN_RATE) : \
+ (HTMcsToDataRate(_ieee, (u8)_MGN_RATE)))
+
+/* fun with the built-in rtllib stack... */
+bool rtllib_MgntDisconnect(struct rtllib_device *rtllib, u8 asRsn);
+
+
+/* For the function is more related to hardware setting, it's better to use the
+ * ieee handler to refer to it.
+ */
+extern void rtllib_update_active_chan_map(struct rtllib_device *ieee);
+extern void rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee,
+ struct rx_ts_record *pTS);
+extern int rtllib_data_xmit(struct sk_buff *skb, struct net_device *dev);
+extern int rtllib_parse_info_param(struct rtllib_device *ieee,
+ struct rtllib_info_element *info_element,
+ u16 length,
+ struct rtllib_network *network,
+ struct rtllib_rx_stats *stats);
+
+void rtllib_indicate_packets(struct rtllib_device *ieee,
+ struct rtllib_rxb **prxbIndicateArray, u8 index);
+extern u8 HTFilterMCSRate(struct rtllib_device *ieee, u8 *pSupportMCS,
+ u8 *pOperateMCS);
+extern void HTUseDefaultSetting(struct rtllib_device *ieee);
+#define RT_ASOC_RETRY_LIMIT 5
+u8 MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee);
+extern void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p);
+#ifndef ENABLE_LOCK_DEBUG
+#define SPIN_LOCK_IEEE(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_IEEE(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_IEEE_REORDER(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_IEEE_REORDER(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_IEEE_WPAX(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_IEEE_WPAX(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_IEEE_MGNTTX(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_IEEE_MGNTTX(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_IEEE_BCN(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_IEEE_BCN(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_MSH_STAINFO(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_MSH_STAINFO(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_MSH_PREQ(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_MSH_PREQ(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_MSH_QUEUE(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_MSH_QUEUE(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_RFPS(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_RFPS(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_IRQTH(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_IRQTH(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_TX(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_TX(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_D3(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_D3(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_RF(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_RF(plock) spin_unlock_irqrestore((plock), flags)
+#define SPIN_LOCK_PRIV_PS(plock) spin_lock_irqsave((plock), flags)
+#define SPIN_UNLOCK_PRIV_PS(plock) spin_unlock_irqrestore((plock), flags)
+#define SEM_DOWN_IEEE_WX(psem) down(psem)
+#define SEM_UP_IEEE_WX(psem) up(psem)
+#define SEM_DOWN_IEEE_SCAN(psem) down(psem)
+#define SEM_UP_IEEE_SCAN(psem) up(psem)
+#define SEM_DOWN_IEEE_IPS(psem) down(psem)
+#define SEM_UP_IEEE_IPS(psem) up(psem)
+#define SEM_DOWN_PRIV_WX(psem) down(psem)
+#define SEM_UP_PRIV_WX(psem) up(psem)
+#define SEM_DOWN_PRIV_RF(psem) down(psem)
+#define SEM_UP_PRIV_RF(psem) up(psem)
+#define MUTEX_LOCK_PRIV(pmutex) mutex_lock(pmutex)
+#define MUTEX_UNLOCK_PRIV(pmutex) mutex_unlock(pmutex)
+#endif
+
+#endif /* RTLLIB_H */
diff --git a/drivers/staging/rtl8192e/rtllib_crypt.c b/drivers/staging/rtl8192e/rtllib_crypt.c
new file mode 100644
index 000000000..1e6ae9bea
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_crypt.c
@@ -0,0 +1,254 @@
+/*
+ * Host AP crypto routines
+ *
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#include "rtllib.h"
+
+struct rtllib_crypto_alg {
+ struct list_head list;
+ struct lib80211_crypto_ops *ops;
+};
+
+
+struct rtllib_crypto {
+ struct list_head algs;
+ spinlock_t lock;
+};
+
+static struct rtllib_crypto *hcrypt;
+
+void rtllib_crypt_deinit_entries(struct lib80211_crypt_info *info,
+ int force)
+{
+ struct list_head *ptr, *n;
+ struct lib80211_crypt_data *entry;
+
+ for (ptr = info->crypt_deinit_list.next, n = ptr->next;
+ ptr != &info->crypt_deinit_list; ptr = n, n = ptr->next) {
+ entry = list_entry(ptr, struct lib80211_crypt_data, list);
+
+ if (atomic_read(&entry->refcnt) != 0 && !force)
+ continue;
+
+ list_del(ptr);
+
+ if (entry->ops)
+ entry->ops->deinit(entry->priv);
+ kfree(entry);
+ }
+}
+EXPORT_SYMBOL(rtllib_crypt_deinit_entries);
+
+void rtllib_crypt_deinit_handler(unsigned long data)
+{
+ struct lib80211_crypt_info *info = (struct lib80211_crypt_info *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(info->lock, flags);
+ rtllib_crypt_deinit_entries(info, 0);
+ if (!list_empty(&info->crypt_deinit_list)) {
+ printk(KERN_DEBUG
+ "%s: entries remaining in delayed crypt deletion list\n",
+ info->name);
+ info->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&info->crypt_deinit_timer);
+ }
+ spin_unlock_irqrestore(info->lock, flags);
+
+}
+EXPORT_SYMBOL(rtllib_crypt_deinit_handler);
+
+void rtllib_crypt_delayed_deinit(struct lib80211_crypt_info *info,
+ struct lib80211_crypt_data **crypt)
+{
+ struct lib80211_crypt_data *tmp;
+ unsigned long flags;
+
+ if (*crypt == NULL)
+ return;
+
+ tmp = *crypt;
+ *crypt = NULL;
+
+ /* must not run ops->deinit() while there may be pending encrypt or
+ * decrypt operations. Use a list of delayed deinits to avoid needing
+ * locking.
+ */
+
+ spin_lock_irqsave(info->lock, flags);
+ list_add(&tmp->list, &info->crypt_deinit_list);
+ if (!timer_pending(&info->crypt_deinit_timer)) {
+ info->crypt_deinit_timer.expires = jiffies + HZ;
+ add_timer(&info->crypt_deinit_timer);
+ }
+ spin_unlock_irqrestore(info->lock, flags);
+}
+EXPORT_SYMBOL(rtllib_crypt_delayed_deinit);
+
+int rtllib_register_crypto_ops(struct lib80211_crypto_ops *ops)
+{
+ unsigned long flags;
+ struct rtllib_crypto_alg *alg;
+
+ if (hcrypt == NULL)
+ return -1;
+
+ alg = kzalloc(sizeof(*alg), GFP_KERNEL);
+ if (alg == NULL)
+ return -ENOMEM;
+
+ alg->ops = ops;
+
+ spin_lock_irqsave(&hcrypt->lock, flags);
+ list_add(&alg->list, &hcrypt->algs);
+ spin_unlock_irqrestore(&hcrypt->lock, flags);
+
+ printk(KERN_DEBUG "rtllib_crypt: registered algorithm '%s'\n",
+ ops->name);
+
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_register_crypto_ops);
+
+int rtllib_unregister_crypto_ops(struct lib80211_crypto_ops *ops)
+{
+ unsigned long flags;
+ struct list_head *ptr;
+ struct rtllib_crypto_alg *del_alg = NULL;
+
+ if (hcrypt == NULL)
+ return -1;
+
+ spin_lock_irqsave(&hcrypt->lock, flags);
+ for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
+ struct rtllib_crypto_alg *alg =
+ (struct rtllib_crypto_alg *) ptr;
+ if (alg->ops == ops) {
+ list_del(&alg->list);
+ del_alg = alg;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&hcrypt->lock, flags);
+
+ if (del_alg) {
+ printk(KERN_DEBUG "rtllib_crypt: unregistered algorithm '%s'\n",
+ ops->name);
+ kfree(del_alg);
+ }
+
+ return del_alg ? 0 : -1;
+}
+EXPORT_SYMBOL(rtllib_unregister_crypto_ops);
+
+
+struct lib80211_crypto_ops *rtllib_get_crypto_ops(const char *name)
+{
+ unsigned long flags;
+ struct list_head *ptr;
+ struct rtllib_crypto_alg *found_alg = NULL;
+
+ if (hcrypt == NULL)
+ return NULL;
+
+ spin_lock_irqsave(&hcrypt->lock, flags);
+ for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
+ struct rtllib_crypto_alg *alg =
+ (struct rtllib_crypto_alg *) ptr;
+ if (strcmp(alg->ops->name, name) == 0) {
+ found_alg = alg;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&hcrypt->lock, flags);
+
+ if (found_alg)
+ return found_alg->ops;
+ else
+ return NULL;
+}
+EXPORT_SYMBOL(rtllib_get_crypto_ops);
+
+
+static void *rtllib_crypt_null_init(int keyidx) { return (void *) 1; }
+static void rtllib_crypt_null_deinit(void *priv) {}
+
+static struct lib80211_crypto_ops rtllib_crypt_null = {
+ .name = "NULL",
+ .init = rtllib_crypt_null_init,
+ .deinit = rtllib_crypt_null_deinit,
+ .encrypt_mpdu = NULL,
+ .decrypt_mpdu = NULL,
+ .encrypt_msdu = NULL,
+ .decrypt_msdu = NULL,
+ .set_key = NULL,
+ .get_key = NULL,
+ .extra_mpdu_prefix_len = 0,
+ .extra_mpdu_postfix_len = 0,
+ .extra_msdu_prefix_len = 0,
+ .extra_msdu_postfix_len = 0,
+ .owner = THIS_MODULE,
+};
+
+
+int __init rtllib_crypto_init(void)
+{
+ int ret = -ENOMEM;
+
+ hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL);
+ if (!hcrypt)
+ goto out;
+
+ INIT_LIST_HEAD(&hcrypt->algs);
+ spin_lock_init(&hcrypt->lock);
+
+ ret = lib80211_register_crypto_ops(&rtllib_crypt_null);
+ if (ret < 0) {
+ kfree(hcrypt);
+ hcrypt = NULL;
+ }
+out:
+ return ret;
+}
+
+
+void __exit rtllib_crypto_deinit(void)
+{
+ struct list_head *ptr, *n;
+
+ if (hcrypt == NULL)
+ return;
+
+ for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
+ ptr = n, n = ptr->next) {
+ struct rtllib_crypto_alg *alg =
+ (struct rtllib_crypto_alg *) ptr;
+ list_del(ptr);
+ printk(KERN_DEBUG
+ "rtllib_crypt: unregistered algorithm '%s' (deinit)\n",
+ alg->ops->name);
+ kfree(alg);
+ }
+
+ kfree(hcrypt);
+}
+
+module_init(rtllib_crypto_init);
+module_exit(rtllib_crypto_deinit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/rtl8192e/rtllib_crypt.h b/drivers/staging/rtl8192e/rtllib_crypt.h
new file mode 100644
index 000000000..b8cf59f39
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_crypt.h
@@ -0,0 +1,34 @@
+/*
+ * Original code based on Host AP (software wireless LAN access point) driver
+ * for Intersil Prism2/2.5/3.
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * Adaption to a generic IEEE 802.11 stack by James Ketrenos
+ * <jketreno@linux.intel.com>
+ *
+ * Copyright (c) 2004, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+/* This file defines the interface to the rtllib crypto module.
+ */
+#ifndef RTLLIB_CRYPT_H
+#define RTLLIB_CRYPT_H
+
+#include <linux/skbuff.h>
+
+int rtllib_register_crypto_ops(struct lib80211_crypto_ops *ops);
+int rtllib_unregister_crypto_ops(struct lib80211_crypto_ops *ops);
+struct lib80211_crypto_ops *rtllib_get_crypto_ops(const char *name);
+void rtllib_crypt_deinit_entries(struct lib80211_crypt_info *info, int force);
+void rtllib_crypt_deinit_handler(unsigned long data);
+void rtllib_crypt_delayed_deinit(struct lib80211_crypt_info *info,
+ struct lib80211_crypt_data **crypt);
+#endif
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
new file mode 100644
index 000000000..7d486e888
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_crypt_ccmp.c
@@ -0,0 +1,457 @@
+/*
+ * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
+ *
+ * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <linux/string.h>
+#include <linux/wireless.h>
+#include "rtllib.h"
+
+#include <linux/crypto.h>
+
+#include <linux/scatterlist.h>
+
+#define AES_BLOCK_LEN 16
+#define CCMP_HDR_LEN 8
+#define CCMP_MIC_LEN 8
+#define CCMP_TK_LEN 16
+#define CCMP_PN_LEN 6
+
+struct rtllib_ccmp_data {
+ u8 key[CCMP_TK_LEN];
+ int key_set;
+
+ u8 tx_pn[CCMP_PN_LEN];
+ u8 rx_pn[CCMP_PN_LEN];
+
+ u32 dot11RSNAStatsCCMPFormatErrors;
+ u32 dot11RSNAStatsCCMPReplays;
+ u32 dot11RSNAStatsCCMPDecryptErrors;
+
+ int key_idx;
+
+ struct crypto_tfm *tfm;
+
+ /* scratch buffers for virt_to_page() (crypto API) */
+ u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
+ tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
+ u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
+};
+
+static void rtllib_ccmp_aes_encrypt(struct crypto_tfm *tfm,
+ const u8 pt[16], u8 ct[16])
+{
+ crypto_cipher_encrypt_one((void *)tfm, ct, pt);
+}
+
+static void *rtllib_ccmp_init(int key_idx)
+{
+ struct rtllib_ccmp_data *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
+ if (priv == NULL)
+ goto fail;
+ priv->key_idx = key_idx;
+
+ priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(priv->tfm)) {
+ pr_debug("rtllib_crypt_ccmp: could not allocate crypto API aes\n");
+ priv->tfm = NULL;
+ goto fail;
+ }
+ return priv;
+
+fail:
+ if (priv) {
+ if (priv->tfm)
+ crypto_free_cipher((void *)priv->tfm);
+ kfree(priv);
+ }
+
+ return NULL;
+}
+
+
+static void rtllib_ccmp_deinit(void *priv)
+{
+ struct rtllib_ccmp_data *_priv = priv;
+
+ if (_priv && _priv->tfm)
+ crypto_free_cipher((void *)_priv->tfm);
+ kfree(priv);
+}
+
+
+static inline void xor_block(u8 *b, u8 *a, size_t len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ b[i] ^= a[i];
+}
+
+
+
+static void ccmp_init_blocks(struct crypto_tfm *tfm,
+ struct rtllib_hdr_4addr *hdr,
+ u8 *pn, size_t dlen, u8 *b0, u8 *auth,
+ u8 *s0)
+{
+ u8 *pos, qc = 0;
+ size_t aad_len;
+ u16 fc;
+ int a4_included, qc_included;
+ u8 aad[2 * AES_BLOCK_LEN];
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ a4_included = ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
+ (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS));
+
+ qc_included = ((WLAN_FC_GET_TYPE(fc) == RTLLIB_FTYPE_DATA) &&
+ (WLAN_FC_GET_STYPE(fc) & 0x80));
+ aad_len = 22;
+ if (a4_included)
+ aad_len += 6;
+ if (qc_included) {
+ pos = (u8 *) &hdr->addr4;
+ if (a4_included)
+ pos += 6;
+ qc = *pos & 0x0f;
+ aad_len += 2;
+ }
+ /* CCM Initial Block:
+ * Flag (Include authentication header, M=3 (8-octet MIC),
+ * L=1 (2-octet Dlen))
+ * Nonce: 0x00 | A2 | PN
+ * Dlen
+ */
+ b0[0] = 0x59;
+ b0[1] = qc;
+ memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
+ memcpy(b0 + 8, pn, CCMP_PN_LEN);
+ b0[14] = (dlen >> 8) & 0xff;
+ b0[15] = dlen & 0xff;
+
+ /* AAD:
+ * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
+ * A1 | A2 | A3
+ * SC with bits 4..15 (seq#) masked to zero
+ * A4 (if present)
+ * QC (if present)
+ */
+ pos = (u8 *) hdr;
+ aad[0] = 0; /* aad_len >> 8 */
+ aad[1] = aad_len & 0xff;
+ aad[2] = pos[0] & 0x8f;
+ aad[3] = pos[1] & 0xc7;
+ memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
+ pos = (u8 *) &hdr->seq_ctl;
+ aad[22] = pos[0] & 0x0f;
+ aad[23] = 0; /* all bits masked */
+ memset(aad + 24, 0, 8);
+ if (a4_included)
+ memcpy(aad + 24, hdr->addr4, ETH_ALEN);
+ if (qc_included) {
+ aad[a4_included ? 30 : 24] = qc;
+ /* rest of QC masked */
+ }
+
+ /* Start with the first block and AAD */
+ rtllib_ccmp_aes_encrypt(tfm, b0, auth);
+ xor_block(auth, aad, AES_BLOCK_LEN);
+ rtllib_ccmp_aes_encrypt(tfm, auth, auth);
+ xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
+ rtllib_ccmp_aes_encrypt(tfm, auth, auth);
+ b0[0] &= 0x07;
+ b0[14] = b0[15] = 0;
+ rtllib_ccmp_aes_encrypt(tfm, b0, s0);
+}
+
+
+
+static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct rtllib_ccmp_data *key = priv;
+ int data_len, i;
+ u8 *pos;
+ struct rtllib_hdr_4addr *hdr;
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
+ MAX_DEV_ADDR_SIZE);
+ if (skb_headroom(skb) < CCMP_HDR_LEN ||
+ skb_tailroom(skb) < CCMP_MIC_LEN ||
+ skb->len < hdr_len)
+ return -1;
+
+ data_len = skb->len - hdr_len;
+ pos = skb_push(skb, CCMP_HDR_LEN);
+ memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
+ pos += hdr_len;
+
+ i = CCMP_PN_LEN - 1;
+ while (i >= 0) {
+ key->tx_pn[i]++;
+ if (key->tx_pn[i] != 0)
+ break;
+ i--;
+ }
+
+ *pos++ = key->tx_pn[5];
+ *pos++ = key->tx_pn[4];
+ *pos++ = 0;
+ *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */;
+ *pos++ = key->tx_pn[3];
+ *pos++ = key->tx_pn[2];
+ *pos++ = key->tx_pn[1];
+ *pos++ = key->tx_pn[0];
+
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ if (!tcb_desc->bHwSec) {
+ int blocks, last, len;
+ u8 *mic;
+ u8 *b0 = key->tx_b0;
+ u8 *b = key->tx_b;
+ u8 *e = key->tx_e;
+ u8 *s0 = key->tx_s0;
+
+ mic = skb_put(skb, CCMP_MIC_LEN);
+
+ ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len,
+ b0, b, s0);
+
+ blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
+ last = data_len % AES_BLOCK_LEN;
+
+ for (i = 1; i <= blocks; i++) {
+ len = (i == blocks && last) ? last : AES_BLOCK_LEN;
+ /* Authentication */
+ xor_block(b, pos, len);
+ rtllib_ccmp_aes_encrypt(key->tfm, b, b);
+ /* Encryption, with counter */
+ b0[14] = (i >> 8) & 0xff;
+ b0[15] = i & 0xff;
+ rtllib_ccmp_aes_encrypt(key->tfm, b0, e);
+ xor_block(pos, e, len);
+ pos += len;
+ }
+
+ for (i = 0; i < CCMP_MIC_LEN; i++)
+ mic[i] = b[i] ^ s0[i];
+ }
+ return 0;
+}
+
+
+static int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct rtllib_ccmp_data *key = priv;
+ u8 keyidx, *pos;
+ struct rtllib_hdr_4addr *hdr;
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
+ MAX_DEV_ADDR_SIZE);
+ u8 pn[6];
+
+ if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
+ key->dot11RSNAStatsCCMPFormatErrors++;
+ return -1;
+ }
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ pos = skb->data + hdr_len;
+ keyidx = pos[3];
+ if (!(keyidx & (1 << 5))) {
+ if (net_ratelimit()) {
+ pr_debug("CCMP: received packet without ExtIV flag from %pM\n",
+ hdr->addr2);
+ }
+ key->dot11RSNAStatsCCMPFormatErrors++;
+ return -2;
+ }
+ keyidx >>= 6;
+ if (key->key_idx != keyidx) {
+ pr_debug("CCMP: RX tkey->key_idx=%d frame keyidx=%d priv=%p\n",
+ key->key_idx, keyidx, priv);
+ return -6;
+ }
+ if (!key->key_set) {
+ if (net_ratelimit()) {
+ pr_debug("CCMP: received packet from %pM with keyid=%d that does not have a configured key\n",
+ hdr->addr2, keyidx);
+ }
+ return -3;
+ }
+
+ pn[0] = pos[7];
+ pn[1] = pos[6];
+ pn[2] = pos[5];
+ pn[3] = pos[4];
+ pn[4] = pos[1];
+ pn[5] = pos[0];
+ pos += 8;
+ if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
+ key->dot11RSNAStatsCCMPReplays++;
+ return -4;
+ }
+ if (!tcb_desc->bHwSec) {
+ size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN -
+ CCMP_MIC_LEN;
+ u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
+ u8 *b0 = key->rx_b0;
+ u8 *b = key->rx_b;
+ u8 *a = key->rx_a;
+ int i, blocks, last, len;
+
+
+ ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
+ xor_block(mic, b, CCMP_MIC_LEN);
+
+ blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
+ last = data_len % AES_BLOCK_LEN;
+
+ for (i = 1; i <= blocks; i++) {
+ len = (i == blocks && last) ? last : AES_BLOCK_LEN;
+ /* Decrypt, with counter */
+ b0[14] = (i >> 8) & 0xff;
+ b0[15] = i & 0xff;
+ rtllib_ccmp_aes_encrypt(key->tfm, b0, b);
+ xor_block(pos, b, len);
+ /* Authentication */
+ xor_block(a, pos, len);
+ rtllib_ccmp_aes_encrypt(key->tfm, a, a);
+ pos += len;
+ }
+
+ if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
+ if (net_ratelimit()) {
+ pr_debug("CCMP: decrypt failed: STA= %pM\n",
+ hdr->addr2);
+ }
+ key->dot11RSNAStatsCCMPDecryptErrors++;
+ return -5;
+ }
+
+ memcpy(key->rx_pn, pn, CCMP_PN_LEN);
+ }
+ /* Remove hdr and MIC */
+ memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
+ skb_pull(skb, CCMP_HDR_LEN);
+ skb_trim(skb, skb->len - CCMP_MIC_LEN);
+
+ return keyidx;
+}
+
+
+static int rtllib_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
+{
+ struct rtllib_ccmp_data *data = priv;
+ int keyidx;
+ struct crypto_tfm *tfm = data->tfm;
+
+ keyidx = data->key_idx;
+ memset(data, 0, sizeof(*data));
+ data->key_idx = keyidx;
+ data->tfm = tfm;
+ if (len == CCMP_TK_LEN) {
+ memcpy(data->key, key, CCMP_TK_LEN);
+ data->key_set = 1;
+ if (seq) {
+ data->rx_pn[0] = seq[5];
+ data->rx_pn[1] = seq[4];
+ data->rx_pn[2] = seq[3];
+ data->rx_pn[3] = seq[2];
+ data->rx_pn[4] = seq[1];
+ data->rx_pn[5] = seq[0];
+ }
+ crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN);
+ } else if (len == 0)
+ data->key_set = 0;
+ else
+ return -1;
+
+ return 0;
+}
+
+
+static int rtllib_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
+{
+ struct rtllib_ccmp_data *data = priv;
+
+ if (len < CCMP_TK_LEN)
+ return -1;
+
+ if (!data->key_set)
+ return 0;
+ memcpy(key, data->key, CCMP_TK_LEN);
+
+ if (seq) {
+ seq[0] = data->tx_pn[5];
+ seq[1] = data->tx_pn[4];
+ seq[2] = data->tx_pn[3];
+ seq[3] = data->tx_pn[2];
+ seq[4] = data->tx_pn[1];
+ seq[5] = data->tx_pn[0];
+ }
+
+ return CCMP_TK_LEN;
+}
+
+
+static void rtllib_ccmp_print_stats(struct seq_file *m, void *priv)
+{
+ struct rtllib_ccmp_data *ccmp = priv;
+
+ seq_printf(m,
+ "key[%d] alg=CCMP key_set=%d tx_pn=%pM rx_pn=%pM format_errors=%d replays=%d decrypt_errors=%d\n",
+ ccmp->key_idx, ccmp->key_set,
+ ccmp->tx_pn, ccmp->rx_pn,
+ ccmp->dot11RSNAStatsCCMPFormatErrors,
+ ccmp->dot11RSNAStatsCCMPReplays,
+ ccmp->dot11RSNAStatsCCMPDecryptErrors);
+}
+
+static struct lib80211_crypto_ops rtllib_crypt_ccmp = {
+ .name = "R-CCMP",
+ .init = rtllib_ccmp_init,
+ .deinit = rtllib_ccmp_deinit,
+ .encrypt_mpdu = rtllib_ccmp_encrypt,
+ .decrypt_mpdu = rtllib_ccmp_decrypt,
+ .encrypt_msdu = NULL,
+ .decrypt_msdu = NULL,
+ .set_key = rtllib_ccmp_set_key,
+ .get_key = rtllib_ccmp_get_key,
+ .print_stats = rtllib_ccmp_print_stats,
+ .extra_mpdu_prefix_len = CCMP_HDR_LEN,
+ .extra_mpdu_postfix_len = CCMP_MIC_LEN,
+ .owner = THIS_MODULE,
+};
+
+
+static int __init rtllib_crypto_ccmp_init(void)
+{
+ return lib80211_register_crypto_ops(&rtllib_crypt_ccmp);
+}
+
+
+static void __exit rtllib_crypto_ccmp_exit(void)
+{
+ lib80211_unregister_crypto_ops(&rtllib_crypt_ccmp);
+}
+
+module_init(rtllib_crypto_ccmp_init);
+module_exit(rtllib_crypto_ccmp_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_tkip.c b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
new file mode 100644
index 000000000..656b4b359
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_crypt_tkip.c
@@ -0,0 +1,779 @@
+/*
+ * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
+ *
+ * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <linux/string.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <linux/crc32.h>
+
+#include "rtllib.h"
+
+struct rtllib_tkip_data {
+#define TKIP_KEY_LEN 32
+ u8 key[TKIP_KEY_LEN];
+ int key_set;
+
+ u32 tx_iv32;
+ u16 tx_iv16;
+ u16 tx_ttak[5];
+ int tx_phase1_done;
+
+ u32 rx_iv32;
+ u16 rx_iv16;
+ bool initialized;
+ u16 rx_ttak[5];
+ int rx_phase1_done;
+ u32 rx_iv32_new;
+ u16 rx_iv16_new;
+
+ u32 dot11RSNAStatsTKIPReplays;
+ u32 dot11RSNAStatsTKIPICVErrors;
+ u32 dot11RSNAStatsTKIPLocalMICFailures;
+
+ int key_idx;
+ struct crypto_blkcipher *rx_tfm_arc4;
+ struct crypto_hash *rx_tfm_michael;
+ struct crypto_blkcipher *tx_tfm_arc4;
+ struct crypto_hash *tx_tfm_michael;
+ /* scratch buffers for virt_to_page() (crypto API) */
+ u8 rx_hdr[16], tx_hdr[16];
+};
+
+static void *rtllib_tkip_init(int key_idx)
+{
+ struct rtllib_tkip_data *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
+ if (priv == NULL)
+ goto fail;
+ priv->key_idx = key_idx;
+ priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(priv->tx_tfm_arc4)) {
+ printk(KERN_DEBUG
+ "rtllib_crypt_tkip: could not allocate crypto API arc4\n");
+ priv->tx_tfm_arc4 = NULL;
+ goto fail;
+ }
+
+ priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(priv->tx_tfm_michael)) {
+ printk(KERN_DEBUG
+ "rtllib_crypt_tkip: could not allocate crypto API michael_mic\n");
+ priv->tx_tfm_michael = NULL;
+ goto fail;
+ }
+
+ priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(priv->rx_tfm_arc4)) {
+ printk(KERN_DEBUG
+ "rtllib_crypt_tkip: could not allocate crypto API arc4\n");
+ priv->rx_tfm_arc4 = NULL;
+ goto fail;
+ }
+
+ priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(priv->rx_tfm_michael)) {
+ printk(KERN_DEBUG
+ "rtllib_crypt_tkip: could not allocate crypto API michael_mic\n");
+ priv->rx_tfm_michael = NULL;
+ goto fail;
+ }
+ return priv;
+
+fail:
+ if (priv) {
+ if (priv->tx_tfm_michael)
+ crypto_free_hash(priv->tx_tfm_michael);
+ if (priv->tx_tfm_arc4)
+ crypto_free_blkcipher(priv->tx_tfm_arc4);
+ if (priv->rx_tfm_michael)
+ crypto_free_hash(priv->rx_tfm_michael);
+ if (priv->rx_tfm_arc4)
+ crypto_free_blkcipher(priv->rx_tfm_arc4);
+ kfree(priv);
+ }
+
+ return NULL;
+}
+
+
+static void rtllib_tkip_deinit(void *priv)
+{
+ struct rtllib_tkip_data *_priv = priv;
+
+ if (_priv) {
+ if (_priv->tx_tfm_michael)
+ crypto_free_hash(_priv->tx_tfm_michael);
+ if (_priv->tx_tfm_arc4)
+ crypto_free_blkcipher(_priv->tx_tfm_arc4);
+ if (_priv->rx_tfm_michael)
+ crypto_free_hash(_priv->rx_tfm_michael);
+ if (_priv->rx_tfm_arc4)
+ crypto_free_blkcipher(_priv->rx_tfm_arc4);
+ }
+ kfree(priv);
+}
+
+
+static inline u16 RotR1(u16 val)
+{
+ return (val >> 1) | (val << 15);
+}
+
+
+static inline u8 Lo8(u16 val)
+{
+ return val & 0xff;
+}
+
+
+static inline u8 Hi8(u16 val)
+{
+ return val >> 8;
+}
+
+
+static inline u16 Lo16(u32 val)
+{
+ return val & 0xffff;
+}
+
+
+static inline u16 Hi16(u32 val)
+{
+ return val >> 16;
+}
+
+
+static inline u16 Mk16(u8 hi, u8 lo)
+{
+ return lo | (((u16) hi) << 8);
+}
+
+
+static inline u16 Mk16_le(u16 *v)
+{
+ return *v;
+}
+
+
+static const u16 Sbox[256] = {
+ 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
+ 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
+ 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
+ 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
+ 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
+ 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
+ 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
+ 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
+ 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
+ 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
+ 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
+ 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
+ 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
+ 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
+ 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
+ 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
+ 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
+ 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
+ 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
+ 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
+ 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
+ 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
+ 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
+ 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
+ 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
+ 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
+ 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
+ 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
+ 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
+ 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
+ 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
+ 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
+};
+
+
+static inline u16 _S_(u16 v)
+{
+ u16 t = Sbox[Hi8(v)];
+ return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
+}
+
+
+#define PHASE1_LOOP_COUNT 8
+
+
+static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
+{
+ int i, j;
+
+ /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
+ TTAK[0] = Lo16(IV32);
+ TTAK[1] = Hi16(IV32);
+ TTAK[2] = Mk16(TA[1], TA[0]);
+ TTAK[3] = Mk16(TA[3], TA[2]);
+ TTAK[4] = Mk16(TA[5], TA[4]);
+
+ for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
+ j = 2 * (i & 1);
+ TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
+ TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
+ TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
+ TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
+ TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
+ }
+}
+
+
+static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
+ u16 IV16)
+{
+ /* Make temporary area overlap WEP seed so that the final copy can be
+ * avoided on little endian hosts.
+ */
+ u16 *PPK = (u16 *) &WEPSeed[4];
+
+ /* Step 1 - make copy of TTAK and bring in TSC */
+ PPK[0] = TTAK[0];
+ PPK[1] = TTAK[1];
+ PPK[2] = TTAK[2];
+ PPK[3] = TTAK[3];
+ PPK[4] = TTAK[4];
+ PPK[5] = TTAK[4] + IV16;
+
+ /* Step 2 - 96-bit bijective mixing using S-box */
+ PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
+ PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
+ PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
+ PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
+ PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
+ PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
+
+ PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
+ PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
+ PPK[2] += RotR1(PPK[1]);
+ PPK[3] += RotR1(PPK[2]);
+ PPK[4] += RotR1(PPK[3]);
+ PPK[5] += RotR1(PPK[4]);
+
+ /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
+ * WEPSeed[0..2] is transmitted as WEP IV
+ */
+ WEPSeed[0] = Hi8(IV16);
+ WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
+ WEPSeed[2] = Lo8(IV16);
+ WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
+
+#ifdef __BIG_ENDIAN
+ {
+ int i;
+
+ for (i = 0; i < 6; i++)
+ PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
+ }
+#endif
+}
+
+
+static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct rtllib_tkip_data *tkey = priv;
+ int len;
+ u8 *pos;
+ struct rtllib_hdr_4addr *hdr;
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
+ MAX_DEV_ADDR_SIZE);
+ struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4};
+ int ret = 0;
+ u8 rc4key[16], *icv;
+ u32 crc;
+ struct scatterlist sg;
+
+ if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
+ skb->len < hdr_len)
+ return -1;
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+
+ if (!tcb_desc->bHwSec) {
+ if (!tkey->tx_phase1_done) {
+ tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
+ tkey->tx_iv32);
+ tkey->tx_phase1_done = 1;
+ }
+ tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak,
+ tkey->tx_iv16);
+ } else
+ tkey->tx_phase1_done = 1;
+
+
+ len = skb->len - hdr_len;
+ pos = skb_push(skb, 8);
+ memmove(pos, pos + 8, hdr_len);
+ pos += hdr_len;
+
+ if (tcb_desc->bHwSec) {
+ *pos++ = Hi8(tkey->tx_iv16);
+ *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F;
+ *pos++ = Lo8(tkey->tx_iv16);
+ } else {
+ *pos++ = rc4key[0];
+ *pos++ = rc4key[1];
+ *pos++ = rc4key[2];
+ }
+
+ *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
+ *pos++ = tkey->tx_iv32 & 0xff;
+ *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
+ *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
+ *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
+
+ if (!tcb_desc->bHwSec) {
+ icv = skb_put(skb, 4);
+ crc = ~crc32_le(~0, pos, len);
+ icv[0] = crc;
+ icv[1] = crc >> 8;
+ icv[2] = crc >> 16;
+ icv[3] = crc >> 24;
+
+ sg_init_one(&sg, pos, len+4);
+
+
+ crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
+ ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
+ }
+
+ tkey->tx_iv16++;
+ if (tkey->tx_iv16 == 0) {
+ tkey->tx_phase1_done = 0;
+ tkey->tx_iv32++;
+ }
+
+ if (!tcb_desc->bHwSec)
+ return ret;
+ else
+ return 0;
+
+
+}
+
+static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct rtllib_tkip_data *tkey = priv;
+ u8 keyidx, *pos;
+ u32 iv32;
+ u16 iv16;
+ struct rtllib_hdr_4addr *hdr;
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
+ MAX_DEV_ADDR_SIZE);
+ struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4};
+ u8 rc4key[16];
+ u8 icv[4];
+ u32 crc;
+ struct scatterlist sg;
+ int plen;
+
+ if (skb->len < hdr_len + 8 + 4)
+ return -1;
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ pos = skb->data + hdr_len;
+ keyidx = pos[3];
+ if (!(keyidx & (1 << 5))) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG
+ "TKIP: received packet without ExtIV flag from %pM\n",
+ hdr->addr2);
+ }
+ return -2;
+ }
+ keyidx >>= 6;
+ if (tkey->key_idx != keyidx) {
+ printk(KERN_DEBUG
+ "TKIP: RX tkey->key_idx=%d frame keyidx=%d priv=%p\n",
+ tkey->key_idx, keyidx, priv);
+ return -6;
+ }
+ if (!tkey->key_set) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG
+ "TKIP: received packet from %pM with keyid=%d that does not have a configured key\n",
+ hdr->addr2, keyidx);
+ }
+ return -3;
+ }
+ iv16 = (pos[0] << 8) | pos[2];
+ iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
+ pos += 8;
+
+ if (!tcb_desc->bHwSec || (skb->cb[0] == 1)) {
+ if ((iv32 < tkey->rx_iv32 ||
+ (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) &&
+ tkey->initialized) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG
+ "TKIP: replay detected: STA= %pM previous TSC %08x%04x received TSC %08x%04x\n",
+ hdr->addr2, tkey->rx_iv32, tkey->rx_iv16,
+ iv32, iv16);
+ }
+ tkey->dot11RSNAStatsTKIPReplays++;
+ return -4;
+ }
+ tkey->initialized = true;
+
+ if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
+ tkip_mixing_phase1(tkey->rx_ttak, tkey->key,
+ hdr->addr2, iv32);
+ tkey->rx_phase1_done = 1;
+ }
+ tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
+
+ plen = skb->len - hdr_len - 12;
+
+ sg_init_one(&sg, pos, plen+4);
+
+ crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
+ if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG
+ ": TKIP: failed to decrypt received packet from %pM\n",
+ hdr->addr2);
+ }
+ return -7;
+ }
+
+ crc = ~crc32_le(~0, pos, plen);
+ icv[0] = crc;
+ icv[1] = crc >> 8;
+ icv[2] = crc >> 16;
+ icv[3] = crc >> 24;
+
+ if (memcmp(icv, pos + plen, 4) != 0) {
+ if (iv32 != tkey->rx_iv32) {
+ /* Previously cached Phase1 result was already
+ * lost, so it needs to be recalculated for the
+ * next packet.
+ */
+ tkey->rx_phase1_done = 0;
+ }
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG
+ "TKIP: ICV error detected: STA= %pM\n",
+ hdr->addr2);
+ }
+ tkey->dot11RSNAStatsTKIPICVErrors++;
+ return -5;
+ }
+
+ }
+
+ /* Update real counters only after Michael MIC verification has
+ * completed
+ */
+ tkey->rx_iv32_new = iv32;
+ tkey->rx_iv16_new = iv16;
+
+ /* Remove IV and ICV */
+ memmove(skb->data + 8, skb->data, hdr_len);
+ skb_pull(skb, 8);
+ skb_trim(skb, skb->len - 4);
+
+ return keyidx;
+}
+
+
+static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr,
+ u8 *data, size_t data_len, u8 *mic)
+{
+ struct hash_desc desc;
+ struct scatterlist sg[2];
+
+ if (tfm_michael == NULL) {
+ pr_warn("michael_mic: tfm_michael == NULL\n");
+ return -1;
+ }
+ sg_init_table(sg, 2);
+ sg_set_buf(&sg[0], hdr, 16);
+ sg_set_buf(&sg[1], data, data_len);
+
+ if (crypto_hash_setkey(tfm_michael, key, 8))
+ return -1;
+
+ desc.tfm = tfm_michael;
+ desc.flags = 0;
+ return crypto_hash_digest(&desc, sg, data_len + 16, mic);
+}
+
+static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
+{
+ struct rtllib_hdr_4addr *hdr11;
+
+ hdr11 = (struct rtllib_hdr_4addr *) skb->data;
+ switch (le16_to_cpu(hdr11->frame_ctl) &
+ (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) {
+ case RTLLIB_FCTL_TODS:
+ memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
+ memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
+ break;
+ case RTLLIB_FCTL_FROMDS:
+ memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
+ memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
+ break;
+ case RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS:
+ memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
+ memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
+ break;
+ case 0:
+ memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
+ memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
+ break;
+ }
+
+ hdr[12] = 0; /* priority */
+
+ hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
+}
+
+
+static int rtllib_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct rtllib_tkip_data *tkey = priv;
+ u8 *pos;
+ struct rtllib_hdr_4addr *hdr;
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+
+ if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
+ printk(KERN_DEBUG
+ "Invalid packet for Michael MIC add (tailroom=%d hdr_len=%d skb->len=%d)\n",
+ skb_tailroom(skb), hdr_len, skb->len);
+ return -1;
+ }
+
+ michael_mic_hdr(skb, tkey->tx_hdr);
+
+ if (RTLLIB_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
+ tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
+ pos = skb_put(skb, 8);
+ if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
+ skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
+ return -1;
+
+ return 0;
+}
+
+
+static void rtllib_michael_mic_failure(struct net_device *dev,
+ struct rtllib_hdr_4addr *hdr,
+ int keyidx)
+{
+ union iwreq_data wrqu;
+ struct iw_michaelmicfailure ev;
+
+ /* TODO: needed parameters: count, keyid, key type, TSC */
+ memset(&ev, 0, sizeof(ev));
+ ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
+ if (hdr->addr1[0] & 0x01)
+ ev.flags |= IW_MICFAILURE_GROUP;
+ else
+ ev.flags |= IW_MICFAILURE_PAIRWISE;
+ ev.src_addr.sa_family = ARPHRD_ETHER;
+ memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
+ memset(&wrqu, 0, sizeof(wrqu));
+ wrqu.data.length = sizeof(ev);
+ wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev);
+}
+
+static int rtllib_michael_mic_verify(struct sk_buff *skb, int keyidx,
+ int hdr_len, void *priv)
+{
+ struct rtllib_tkip_data *tkey = priv;
+ u8 mic[8];
+ struct rtllib_hdr_4addr *hdr;
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+
+ if (!tkey->key_set)
+ return -1;
+
+ michael_mic_hdr(skb, tkey->rx_hdr);
+ if (RTLLIB_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl)))
+ tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
+
+ if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
+ skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
+ return -1;
+
+ if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
+ struct rtllib_hdr_4addr *hdr;
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ printk(KERN_DEBUG
+ "%s: Michael MIC verification failed for MSDU from %pM keyidx=%d\n",
+ skb->dev ? skb->dev->name : "N/A", hdr->addr2,
+ keyidx);
+ printk(KERN_DEBUG "%d\n",
+ memcmp(mic, skb->data + skb->len - 8, 8) != 0);
+ if (skb->dev) {
+ pr_info("skb->dev != NULL\n");
+ rtllib_michael_mic_failure(skb->dev, hdr, keyidx);
+ }
+ tkey->dot11RSNAStatsTKIPLocalMICFailures++;
+ return -1;
+ }
+
+ /* Update TSC counters for RX now that the packet verification has
+ * completed.
+ */
+ tkey->rx_iv32 = tkey->rx_iv32_new;
+ tkey->rx_iv16 = tkey->rx_iv16_new;
+
+ skb_trim(skb, skb->len - 8);
+
+ return 0;
+}
+
+
+static int rtllib_tkip_set_key(void *key, int len, u8 *seq, void *priv)
+{
+ struct rtllib_tkip_data *tkey = priv;
+ int keyidx;
+ struct crypto_hash *tfm = tkey->tx_tfm_michael;
+ struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
+ struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
+ struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
+
+ keyidx = tkey->key_idx;
+ memset(tkey, 0, sizeof(*tkey));
+ tkey->key_idx = keyidx;
+ tkey->tx_tfm_michael = tfm;
+ tkey->tx_tfm_arc4 = tfm2;
+ tkey->rx_tfm_michael = tfm3;
+ tkey->rx_tfm_arc4 = tfm4;
+
+ if (len == TKIP_KEY_LEN) {
+ memcpy(tkey->key, key, TKIP_KEY_LEN);
+ tkey->key_set = 1;
+ tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
+ if (seq) {
+ tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
+ (seq[3] << 8) | seq[2];
+ tkey->rx_iv16 = (seq[1] << 8) | seq[0];
+ }
+ } else if (len == 0)
+ tkey->key_set = 0;
+ else
+ return -1;
+
+ return 0;
+}
+
+
+static int rtllib_tkip_get_key(void *key, int len, u8 *seq, void *priv)
+{
+ struct rtllib_tkip_data *tkey = priv;
+
+ if (len < TKIP_KEY_LEN)
+ return -1;
+
+ if (!tkey->key_set)
+ return 0;
+ memcpy(key, tkey->key, TKIP_KEY_LEN);
+
+ if (seq) {
+ /* Return the sequence number of the last transmitted frame. */
+ u16 iv16 = tkey->tx_iv16;
+ u32 iv32 = tkey->tx_iv32;
+
+ if (iv16 == 0)
+ iv32--;
+ iv16--;
+ seq[0] = tkey->tx_iv16;
+ seq[1] = tkey->tx_iv16 >> 8;
+ seq[2] = tkey->tx_iv32;
+ seq[3] = tkey->tx_iv32 >> 8;
+ seq[4] = tkey->tx_iv32 >> 16;
+ seq[5] = tkey->tx_iv32 >> 24;
+ }
+
+ return TKIP_KEY_LEN;
+}
+
+
+static void rtllib_tkip_print_stats(struct seq_file *m, void *priv)
+{
+ struct rtllib_tkip_data *tkip = priv;
+
+ seq_printf(m,
+ "key[%d] alg=TKIP key_set=%d tx_pn=%02x%02x%02x%02x%02x%02x rx_pn=%02x%02x%02x%02x%02x%02x replays=%d icv_errors=%d local_mic_failures=%d\n",
+ tkip->key_idx, tkip->key_set,
+ (tkip->tx_iv32 >> 24) & 0xff,
+ (tkip->tx_iv32 >> 16) & 0xff,
+ (tkip->tx_iv32 >> 8) & 0xff,
+ tkip->tx_iv32 & 0xff,
+ (tkip->tx_iv16 >> 8) & 0xff,
+ tkip->tx_iv16 & 0xff,
+ (tkip->rx_iv32 >> 24) & 0xff,
+ (tkip->rx_iv32 >> 16) & 0xff,
+ (tkip->rx_iv32 >> 8) & 0xff,
+ tkip->rx_iv32 & 0xff,
+ (tkip->rx_iv16 >> 8) & 0xff,
+ tkip->rx_iv16 & 0xff,
+ tkip->dot11RSNAStatsTKIPReplays,
+ tkip->dot11RSNAStatsTKIPICVErrors,
+ tkip->dot11RSNAStatsTKIPLocalMICFailures);
+}
+
+static struct lib80211_crypto_ops rtllib_crypt_tkip = {
+ .name = "R-TKIP",
+ .init = rtllib_tkip_init,
+ .deinit = rtllib_tkip_deinit,
+ .encrypt_mpdu = rtllib_tkip_encrypt,
+ .decrypt_mpdu = rtllib_tkip_decrypt,
+ .encrypt_msdu = rtllib_michael_mic_add,
+ .decrypt_msdu = rtllib_michael_mic_verify,
+ .set_key = rtllib_tkip_set_key,
+ .get_key = rtllib_tkip_get_key,
+ .print_stats = rtllib_tkip_print_stats,
+ .extra_mpdu_prefix_len = 4 + 4, /* IV + ExtIV */
+ .extra_mpdu_postfix_len = 4, /* ICV */
+ .extra_msdu_postfix_len = 8, /* MIC */
+ .owner = THIS_MODULE,
+};
+
+
+static int __init rtllib_crypto_tkip_init(void)
+{
+ return lib80211_register_crypto_ops(&rtllib_crypt_tkip);
+}
+
+
+static void __exit rtllib_crypto_tkip_exit(void)
+{
+ lib80211_unregister_crypto_ops(&rtllib_crypt_tkip);
+}
+
+module_init(rtllib_crypto_tkip_init);
+module_exit(rtllib_crypto_tkip_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/rtl8192e/rtllib_crypt_wep.c b/drivers/staging/rtl8192e/rtllib_crypt_wep.c
new file mode 100644
index 000000000..21d7eee4c
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_crypt_wep.c
@@ -0,0 +1,289 @@
+/*
+ * Host AP crypt: host-based WEP encryption implementation for Host AP driver
+ *
+ * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include "rtllib.h"
+
+#include <linux/crypto.h>
+
+#include <linux/scatterlist.h>
+#include <linux/crc32.h>
+
+struct prism2_wep_data {
+ u32 iv;
+#define WEP_KEY_LEN 13
+ u8 key[WEP_KEY_LEN + 1];
+ u8 key_len;
+ u8 key_idx;
+ struct crypto_blkcipher *tx_tfm;
+ struct crypto_blkcipher *rx_tfm;
+};
+
+
+static void *prism2_wep_init(int keyidx)
+{
+ struct prism2_wep_data *priv;
+
+ priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
+ if (priv == NULL)
+ goto fail;
+ priv->key_idx = keyidx;
+
+ priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(priv->tx_tfm)) {
+ pr_debug("rtllib_crypt_wep: could not allocate crypto API arc4\n");
+ priv->tx_tfm = NULL;
+ goto fail;
+ }
+ priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
+ if (IS_ERR(priv->rx_tfm)) {
+ pr_debug("rtllib_crypt_wep: could not allocate crypto API arc4\n");
+ priv->rx_tfm = NULL;
+ goto fail;
+ }
+
+ /* start WEP IV from a random value */
+ get_random_bytes(&priv->iv, 4);
+
+ return priv;
+
+fail:
+ if (priv) {
+ if (priv->tx_tfm)
+ crypto_free_blkcipher(priv->tx_tfm);
+ if (priv->rx_tfm)
+ crypto_free_blkcipher(priv->rx_tfm);
+ kfree(priv);
+ }
+ return NULL;
+}
+
+
+static void prism2_wep_deinit(void *priv)
+{
+ struct prism2_wep_data *_priv = priv;
+
+ if (_priv) {
+ if (_priv->tx_tfm)
+ crypto_free_blkcipher(_priv->tx_tfm);
+ if (_priv->rx_tfm)
+ crypto_free_blkcipher(_priv->rx_tfm);
+ }
+ kfree(priv);
+}
+
+/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
+ * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
+ * so the payload length increases with 8 bytes.
+ *
+ * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
+ */
+static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct prism2_wep_data *wep = priv;
+ u32 klen, len;
+ u8 key[WEP_KEY_LEN + 3];
+ u8 *pos;
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
+ MAX_DEV_ADDR_SIZE);
+ struct blkcipher_desc desc = {.tfm = wep->tx_tfm};
+ u32 crc;
+ u8 *icv;
+ struct scatterlist sg;
+
+ if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
+ skb->len < hdr_len){
+ pr_err("Error!!! headroom=%d tailroom=%d skblen=%d hdr_len=%d\n",
+ skb_headroom(skb), skb_tailroom(skb), skb->len, hdr_len);
+ return -1;
+ }
+ len = skb->len - hdr_len;
+ pos = skb_push(skb, 4);
+ memmove(pos, pos + 4, hdr_len);
+ pos += hdr_len;
+
+ klen = 3 + wep->key_len;
+
+ wep->iv++;
+
+ /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
+ * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
+ * can be used to speedup attacks, so avoid using them.
+ */
+ if ((wep->iv & 0xff00) == 0xff00) {
+ u8 B = (wep->iv >> 16) & 0xff;
+
+ if (B >= 3 && B < klen)
+ wep->iv += 0x0100;
+ }
+
+ /* Prepend 24-bit IV to RC4 key and TX frame */
+ *pos++ = key[0] = (wep->iv >> 16) & 0xff;
+ *pos++ = key[1] = (wep->iv >> 8) & 0xff;
+ *pos++ = key[2] = wep->iv & 0xff;
+ *pos++ = wep->key_idx << 6;
+
+ /* Copy rest of the WEP key (the secret part) */
+ memcpy(key + 3, wep->key, wep->key_len);
+
+ if (!tcb_desc->bHwSec) {
+
+ /* Append little-endian CRC32 and encrypt it to produce ICV */
+ crc = ~crc32_le(~0, pos, len);
+ icv = skb_put(skb, 4);
+ icv[0] = crc;
+ icv[1] = crc >> 8;
+ icv[2] = crc >> 16;
+ icv[3] = crc >> 24;
+
+ sg_init_one(&sg, pos, len+4);
+ crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
+ return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
+ }
+
+ return 0;
+}
+
+
+/* Perform WEP decryption on given struct buffer. Buffer includes whole WEP
+ * part of the frame: IV (4 bytes), encrypted payload (including SNAP header),
+ * ICV (4 bytes). len includes both IV and ICV.
+ *
+ * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
+ * failure. If frame is OK, IV and ICV will be removed.
+ */
+static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
+{
+ struct prism2_wep_data *wep = priv;
+ u32 klen, plen;
+ u8 key[WEP_KEY_LEN + 3];
+ u8 keyidx, *pos;
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb +
+ MAX_DEV_ADDR_SIZE);
+ struct blkcipher_desc desc = {.tfm = wep->rx_tfm};
+ u32 crc;
+ u8 icv[4];
+ struct scatterlist sg;
+
+ if (skb->len < hdr_len + 8)
+ return -1;
+
+ pos = skb->data + hdr_len;
+ key[0] = *pos++;
+ key[1] = *pos++;
+ key[2] = *pos++;
+ keyidx = *pos++ >> 6;
+ if (keyidx != wep->key_idx)
+ return -1;
+
+ klen = 3 + wep->key_len;
+
+ /* Copy rest of the WEP key (the secret part) */
+ memcpy(key + 3, wep->key, wep->key_len);
+
+ /* Apply RC4 to data and compute CRC32 over decrypted data */
+ plen = skb->len - hdr_len - 8;
+
+ if (!tcb_desc->bHwSec) {
+ sg_init_one(&sg, pos, plen+4);
+ crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
+ if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
+ return -7;
+ crc = ~crc32_le(~0, pos, plen);
+ icv[0] = crc;
+ icv[1] = crc >> 8;
+ icv[2] = crc >> 16;
+ icv[3] = crc >> 24;
+ if (memcmp(icv, pos + plen, 4) != 0) {
+ /* ICV mismatch - drop frame */
+ return -2;
+ }
+ }
+ /* Remove IV and ICV */
+ memmove(skb->data + 4, skb->data, hdr_len);
+ skb_pull(skb, 4);
+ skb_trim(skb, skb->len - 4);
+
+ return 0;
+}
+
+
+static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
+{
+ struct prism2_wep_data *wep = priv;
+
+ if (len < 0 || len > WEP_KEY_LEN)
+ return -1;
+
+ memcpy(wep->key, key, len);
+ wep->key_len = len;
+
+ return 0;
+}
+
+
+static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
+{
+ struct prism2_wep_data *wep = priv;
+
+ if (len < wep->key_len)
+ return -1;
+
+ memcpy(key, wep->key, wep->key_len);
+
+ return wep->key_len;
+}
+
+
+static void prism2_wep_print_stats(struct seq_file *m, void *priv)
+{
+ struct prism2_wep_data *wep = priv;
+
+ seq_printf(m, "key[%d] alg=WEP len=%d\n", wep->key_idx, wep->key_len);
+}
+
+static struct lib80211_crypto_ops rtllib_crypt_wep = {
+ .name = "R-WEP",
+ .init = prism2_wep_init,
+ .deinit = prism2_wep_deinit,
+ .encrypt_mpdu = prism2_wep_encrypt,
+ .decrypt_mpdu = prism2_wep_decrypt,
+ .encrypt_msdu = NULL,
+ .decrypt_msdu = NULL,
+ .set_key = prism2_wep_set_key,
+ .get_key = prism2_wep_get_key,
+ .print_stats = prism2_wep_print_stats,
+ .extra_mpdu_prefix_len = 4, /* IV */
+ .extra_mpdu_postfix_len = 4, /* ICV */
+ .owner = THIS_MODULE,
+};
+
+
+static int __init rtllib_crypto_wep_init(void)
+{
+ return lib80211_register_crypto_ops(&rtllib_crypt_wep);
+}
+
+
+static void __exit rtllib_crypto_wep_exit(void)
+{
+ lib80211_unregister_crypto_ops(&rtllib_crypt_wep);
+}
+
+module_init(rtllib_crypto_wep_init);
+module_exit(rtllib_crypto_wep_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/rtl8192e/rtllib_debug.h b/drivers/staging/rtl8192e/rtllib_debug.h
new file mode 100644
index 000000000..119729d31
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_debug.h
@@ -0,0 +1,88 @@
+/******************************************************************************
+ * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andrea.merello@gmail.com>, et al.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+******************************************************************************/
+#ifndef _RTL_DEBUG_H
+#define _RTL_DEBUG_H
+
+/* Allow files to override DRV_NAME */
+#ifndef DRV_NAME
+#define DRV_NAME "rtllib_92e"
+#endif
+
+#define DMESG(x, a...)
+
+extern u32 rt_global_debug_component;
+
+/* These are the defines for rt_global_debug_component */
+enum RTL_DEBUG {
+ COMP_TRACE = (1 << 0),
+ COMP_DBG = (1 << 1),
+ COMP_INIT = (1 << 2),
+ COMP_RECV = (1 << 3),
+ COMP_SEND = (1 << 4),
+ COMP_CMD = (1 << 5),
+ COMP_POWER = (1 << 6),
+ COMP_EPROM = (1 << 7),
+ COMP_SWBW = (1 << 8),
+ COMP_SEC = (1 << 9),
+ COMP_LPS = (1 << 10),
+ COMP_QOS = (1 << 11),
+ COMP_RATE = (1 << 12),
+ COMP_RXDESC = (1 << 13),
+ COMP_PHY = (1 << 14),
+ COMP_DIG = (1 << 15),
+ COMP_TXAGC = (1 << 16),
+ COMP_HALDM = (1 << 17),
+ COMP_POWER_TRACKING = (1 << 18),
+ COMP_CH = (1 << 19),
+ COMP_RF = (1 << 20),
+ COMP_FIRMWARE = (1 << 21),
+ COMP_HT = (1 << 22),
+ COMP_RESET = (1 << 23),
+ COMP_CMDPKT = (1 << 24),
+ COMP_SCAN = (1 << 25),
+ COMP_PS = (1 << 26),
+ COMP_DOWN = (1 << 27),
+ COMP_INTR = (1 << 28),
+ COMP_LED = (1 << 29),
+ COMP_MLME = (1 << 30),
+ COMP_ERR = (1 << 31)
+};
+
+#define RT_TRACE(component, x, args...) \
+do { \
+ if (rt_global_debug_component & component) \
+ printk(KERN_DEBUG DRV_NAME ":" x "\n" , \
+ ##args);\
+} while (0)
+
+#define assert(expr) \
+do { \
+ if (!(expr)) { \
+ pr_info("Assertion failed! %s,%s,%s,line=%d\n", \
+ #expr, __FILE__, __func__, __LINE__); \
+ } \
+} while (0)
+
+#endif
diff --git a/drivers/staging/rtl8192e/rtllib_module.c b/drivers/staging/rtl8192e/rtllib_module.c
new file mode 100644
index 000000000..32cc8df9d
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_module.c
@@ -0,0 +1,268 @@
+/*******************************************************************************
+
+ Copyright(c) 2004 Intel Corporation. All rights reserved.
+
+ Portions of this file are based on the WEP enablement code provided by the
+ Host AP project hostap-drivers v0.1.3
+ Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ <jkmaline@cc.hut.fi>
+ Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <linux/uaccess.h>
+#include <net/arp.h>
+
+#include "rtllib.h"
+
+
+u32 rt_global_debug_component = COMP_ERR;
+EXPORT_SYMBOL(rt_global_debug_component);
+
+
+void _setup_timer(struct timer_list *ptimer, void *fun, unsigned long data)
+{
+ ptimer->function = fun;
+ ptimer->data = data;
+ init_timer(ptimer);
+}
+
+static inline int rtllib_networks_allocate(struct rtllib_device *ieee)
+{
+ if (ieee->networks)
+ return 0;
+
+ ieee->networks = kzalloc(
+ MAX_NETWORK_COUNT * sizeof(struct rtllib_network),
+ GFP_KERNEL);
+ if (!ieee->networks)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static inline void rtllib_networks_free(struct rtllib_device *ieee)
+{
+ if (!ieee->networks)
+ return;
+ kfree(ieee->networks);
+ ieee->networks = NULL;
+}
+
+static inline void rtllib_networks_initialize(struct rtllib_device *ieee)
+{
+ int i;
+
+ INIT_LIST_HEAD(&ieee->network_free_list);
+ INIT_LIST_HEAD(&ieee->network_list);
+ for (i = 0; i < MAX_NETWORK_COUNT; i++)
+ list_add_tail(&ieee->networks[i].list,
+ &ieee->network_free_list);
+}
+
+struct net_device *alloc_rtllib(int sizeof_priv)
+{
+ struct rtllib_device *ieee = NULL;
+ struct net_device *dev;
+ int i, err;
+
+ RTLLIB_DEBUG_INFO("Initializing...\n");
+
+ dev = alloc_etherdev(sizeof(struct rtllib_device) + sizeof_priv);
+ if (!dev) {
+ RTLLIB_ERROR("Unable to network device.\n");
+ return NULL;
+ }
+ ieee = (struct rtllib_device *)netdev_priv_rsl(dev);
+ memset(ieee, 0, sizeof(struct rtllib_device)+sizeof_priv);
+ ieee->dev = dev;
+
+ err = rtllib_networks_allocate(ieee);
+ if (err) {
+ RTLLIB_ERROR("Unable to allocate beacon storage: %d\n",
+ err);
+ goto failed;
+ }
+ rtllib_networks_initialize(ieee);
+
+
+ /* Default fragmentation threshold is maximum payload size */
+ ieee->fts = DEFAULT_FTS;
+ ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
+ ieee->open_wep = 1;
+
+ /* Default to enabling full open WEP with host based encrypt/decrypt */
+ ieee->host_encrypt = 1;
+ ieee->host_decrypt = 1;
+ ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
+
+ ieee->rtllib_ap_sec_type = rtllib_ap_sec_type;
+
+ spin_lock_init(&ieee->lock);
+ spin_lock_init(&ieee->wpax_suitlist_lock);
+ spin_lock_init(&ieee->bw_spinlock);
+ spin_lock_init(&ieee->reorder_spinlock);
+ atomic_set(&(ieee->atm_chnlop), 0);
+ atomic_set(&(ieee->atm_swbw), 0);
+
+ /* SAM FIXME */
+ lib80211_crypt_info_init(&ieee->crypt_info, "RTLLIB", &ieee->lock);
+
+ ieee->bHalfNMode = false;
+ ieee->wpa_enabled = 0;
+ ieee->tkip_countermeasures = 0;
+ ieee->drop_unencrypted = 0;
+ ieee->privacy_invoked = 0;
+ ieee->ieee802_1x = 1;
+ ieee->raw_tx = 0;
+ ieee->hwsec_active = 0;
+
+ memset(ieee->swcamtable, 0, sizeof(struct sw_cam_table) * 32);
+ rtllib_softmac_init(ieee);
+
+ ieee->pHTInfo = kzalloc(sizeof(struct rt_hi_throughput), GFP_KERNEL);
+ if (ieee->pHTInfo == NULL)
+ return NULL;
+
+ HTUpdateDefaultSetting(ieee);
+ HTInitializeHTInfo(ieee);
+ TSInitialize(ieee);
+ for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
+ INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
+
+ for (i = 0; i < 17; i++) {
+ ieee->last_rxseq_num[i] = -1;
+ ieee->last_rxfrag_num[i] = -1;
+ ieee->last_packet_time[i] = 0;
+ }
+
+ return dev;
+
+ failed:
+ free_netdev(dev);
+ return NULL;
+}
+EXPORT_SYMBOL(alloc_rtllib);
+
+void free_rtllib(struct net_device *dev)
+{
+ struct rtllib_device *ieee = (struct rtllib_device *)
+ netdev_priv_rsl(dev);
+
+ kfree(ieee->pHTInfo);
+ ieee->pHTInfo = NULL;
+ rtllib_softmac_free(ieee);
+
+ lib80211_crypt_info_free(&ieee->crypt_info);
+
+ rtllib_networks_free(ieee);
+ free_netdev(dev);
+}
+EXPORT_SYMBOL(free_rtllib);
+
+u32 rtllib_debug_level;
+static int debug = RTLLIB_DL_ERR;
+static struct proc_dir_entry *rtllib_proc;
+
+static int show_debug_level(struct seq_file *m, void *v)
+{
+ seq_printf(m, "0x%08X\n", rtllib_debug_level);
+
+ return 0;
+}
+
+static ssize_t write_debug_level(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ unsigned long val;
+ int err = kstrtoul_from_user(buffer, count, 0, &val);
+
+ if (err)
+ return err;
+ rtllib_debug_level = val;
+ return count;
+}
+
+static int open_debug_level(struct inode *inode, struct file *file)
+{
+ return single_open(file, show_debug_level, NULL);
+}
+
+static const struct file_operations fops = {
+ .open = open_debug_level,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = write_debug_level,
+ .release = single_release,
+};
+
+static int __init rtllib_init(void)
+{
+ struct proc_dir_entry *e;
+
+ rtllib_debug_level = debug;
+ rtllib_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
+ if (rtllib_proc == NULL) {
+ RTLLIB_ERROR("Unable to create " DRV_NAME
+ " proc directory\n");
+ return -EIO;
+ }
+ e = proc_create("debug_level", S_IRUGO | S_IWUSR, rtllib_proc, &fops);
+ if (!e) {
+ remove_proc_entry(DRV_NAME, init_net.proc_net);
+ rtllib_proc = NULL;
+ return -EIO;
+ }
+ return 0;
+}
+
+static void __exit rtllib_exit(void)
+{
+ if (rtllib_proc) {
+ remove_proc_entry("debug_level", rtllib_proc);
+ remove_proc_entry(DRV_NAME, init_net.proc_net);
+ rtllib_proc = NULL;
+ }
+}
+
+module_init(rtllib_init);
+module_exit(rtllib_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
new file mode 100644
index 000000000..fe3e7e127
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -0,0 +1,2678 @@
+/*
+ * Original code based Host AP (software wireless LAN access point) driver
+ * for Intersil Prism2/2.5/3 - hostap.o module, common routines
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <jkmaline@cc.hut.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+ * Copyright (c) 2004, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ ******************************************************************************
+
+ Few modifications for Realtek's Wi-Fi drivers by
+ Andrea Merello <andrea.merello@gmail.com>
+
+ A special thanks goes to Realtek for their support !
+
+******************************************************************************/
+
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <linux/uaccess.h>
+#include <linux/ctype.h>
+
+#include "rtllib.h"
+#include "dot11d.h"
+
+static inline void rtllib_monitor_rx(struct rtllib_device *ieee,
+ struct sk_buff *skb, struct rtllib_rx_stats *rx_status,
+ size_t hdr_length)
+{
+ skb->dev = ieee->dev;
+ skb_reset_mac_header(skb);
+ skb_pull(skb, hdr_length);
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = htons(ETH_P_80211_RAW);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx(skb);
+}
+
+/* Called only as a tasklet (software IRQ) */
+static struct rtllib_frag_entry *
+rtllib_frag_cache_find(struct rtllib_device *ieee, unsigned int seq,
+ unsigned int frag, u8 tid, u8 *src, u8 *dst)
+{
+ struct rtllib_frag_entry *entry;
+ int i;
+
+ for (i = 0; i < RTLLIB_FRAG_CACHE_LEN; i++) {
+ entry = &ieee->frag_cache[tid][i];
+ if (entry->skb != NULL &&
+ time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
+ RTLLIB_DEBUG_FRAG(
+ "expiring fragment cache entry seq=%u last_frag=%u\n",
+ entry->seq, entry->last_frag);
+ dev_kfree_skb_any(entry->skb);
+ entry->skb = NULL;
+ }
+
+ if (entry->skb != NULL && entry->seq == seq &&
+ (entry->last_frag + 1 == frag || frag == -1) &&
+ memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
+ memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
+ return entry;
+ }
+
+ return NULL;
+}
+
+/* Called only as a tasklet (software IRQ) */
+static struct sk_buff *
+rtllib_frag_cache_get(struct rtllib_device *ieee,
+ struct rtllib_hdr_4addr *hdr)
+{
+ struct sk_buff *skb = NULL;
+ u16 fc = le16_to_cpu(hdr->frame_ctl);
+ u16 sc = le16_to_cpu(hdr->seq_ctl);
+ unsigned int frag = WLAN_GET_SEQ_FRAG(sc);
+ unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
+ struct rtllib_frag_entry *entry;
+ struct rtllib_hdr_3addrqos *hdr_3addrqos;
+ struct rtllib_hdr_4addrqos *hdr_4addrqos;
+ u8 tid;
+
+ if (((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS) && RTLLIB_QOS_HAS_SEQ(fc)) {
+ hdr_4addrqos = (struct rtllib_hdr_4addrqos *)hdr;
+ tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+ tid = UP2AC(tid);
+ tid++;
+ } else if (RTLLIB_QOS_HAS_SEQ(fc)) {
+ hdr_3addrqos = (struct rtllib_hdr_3addrqos *)hdr;
+ tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+ tid = UP2AC(tid);
+ tid++;
+ } else {
+ tid = 0;
+ }
+
+ if (frag == 0) {
+ /* Reserve enough space to fit maximum frame length */
+ skb = dev_alloc_skb(ieee->dev->mtu +
+ sizeof(struct rtllib_hdr_4addr) +
+ 8 /* LLC */ +
+ 2 /* alignment */ +
+ 8 /* WEP */ +
+ ETH_ALEN /* WDS */ +
+ (RTLLIB_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */);
+ if (skb == NULL)
+ return NULL;
+
+ entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]];
+ ieee->frag_next_idx[tid]++;
+ if (ieee->frag_next_idx[tid] >= RTLLIB_FRAG_CACHE_LEN)
+ ieee->frag_next_idx[tid] = 0;
+
+ if (entry->skb != NULL)
+ dev_kfree_skb_any(entry->skb);
+
+ entry->first_frag_time = jiffies;
+ entry->seq = seq;
+ entry->last_frag = frag;
+ entry->skb = skb;
+ memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
+ memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
+ } else {
+ /* received a fragment of a frame for which the head fragment
+ * should have already been received
+ */
+ entry = rtllib_frag_cache_find(ieee, seq, frag, tid, hdr->addr2,
+ hdr->addr1);
+ if (entry != NULL) {
+ entry->last_frag = frag;
+ skb = entry->skb;
+ }
+ }
+
+ return skb;
+}
+
+
+/* Called only as a tasklet (software IRQ) */
+static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee,
+ struct rtllib_hdr_4addr *hdr)
+{
+ u16 fc = le16_to_cpu(hdr->frame_ctl);
+ u16 sc = le16_to_cpu(hdr->seq_ctl);
+ unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
+ struct rtllib_frag_entry *entry;
+ struct rtllib_hdr_3addrqos *hdr_3addrqos;
+ struct rtllib_hdr_4addrqos *hdr_4addrqos;
+ u8 tid;
+
+ if (((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS) && RTLLIB_QOS_HAS_SEQ(fc)) {
+ hdr_4addrqos = (struct rtllib_hdr_4addrqos *)hdr;
+ tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+ tid = UP2AC(tid);
+ tid++;
+ } else if (RTLLIB_QOS_HAS_SEQ(fc)) {
+ hdr_3addrqos = (struct rtllib_hdr_3addrqos *)hdr;
+ tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+ tid = UP2AC(tid);
+ tid++;
+ } else {
+ tid = 0;
+ }
+
+ entry = rtllib_frag_cache_find(ieee, seq, -1, tid, hdr->addr2,
+ hdr->addr1);
+
+ if (entry == NULL) {
+ RTLLIB_DEBUG_FRAG(
+ "could not invalidate fragment cache entry (seq=%u)\n", seq);
+ return -1;
+ }
+
+ entry->skb = NULL;
+ return 0;
+}
+
+/* rtllib_rx_frame_mgtmt
+ *
+ * Responsible for handling management control frames
+ *
+ * Called by rtllib_rx
+ */
+static inline int
+rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats, u16 type,
+ u16 stype)
+{
+ /* On the struct stats definition there is written that
+ * this is not mandatory.... but seems that the probe
+ * response parser uses it
+ */
+ struct rtllib_hdr_3addr *hdr = (struct rtllib_hdr_3addr *)skb->data;
+
+ rx_stats->len = skb->len;
+ rtllib_rx_mgt(ieee, skb, rx_stats);
+ if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN))) {
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+ rtllib_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
+
+ dev_kfree_skb_any(skb);
+
+ return 0;
+}
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation
+ * Ethernet-II snap header (RFC1042 for most EtherTypes)
+ */
+static unsigned char rfc1042_header[] = {
+ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00
+};
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] = {
+ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8
+};
+/* No encapsulation header if EtherType < 0x600 (=length) */
+
+/* Called by rtllib_rx_frame_decrypt */
+static int rtllib_is_eapol_frame(struct rtllib_device *ieee,
+ struct sk_buff *skb, size_t hdrlen)
+{
+ struct net_device *dev = ieee->dev;
+ u16 fc, ethertype;
+ struct rtllib_hdr_4addr *hdr;
+ u8 *pos;
+
+ if (skb->len < 24)
+ return 0;
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ /* check that the frame is unicast frame to us */
+ if ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
+ RTLLIB_FCTL_TODS &&
+ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
+ memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
+ /* ToDS frame with own addr BSSID and DA */
+ } else if ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) ==
+ RTLLIB_FCTL_FROMDS &&
+ memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
+ /* FromDS frame with own addr as DA */
+ } else
+ return 0;
+
+ if (skb->len < 24 + 8)
+ return 0;
+
+ /* check for port access entity Ethernet type */
+ pos = skb->data + hdrlen;
+ ethertype = (pos[6] << 8) | pos[7];
+ if (ethertype == ETH_P_PAE)
+ return 1;
+
+ return 0;
+}
+
+/* Called only as a tasklet (software IRQ), by rtllib_rx */
+static inline int
+rtllib_rx_frame_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct lib80211_crypt_data *crypt)
+{
+ struct rtllib_hdr_4addr *hdr;
+ int res, hdrlen;
+
+ if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
+ return 0;
+
+ if (ieee->hwsec_active) {
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+
+ tcb_desc->bHwSec = 1;
+
+ if (ieee->need_sw_enc)
+ tcb_desc->bHwSec = 0;
+ }
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+ atomic_inc(&crypt->refcnt);
+ res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ RTLLIB_DEBUG_DROP(
+ "decryption failed (SA= %pM) res=%d\n", hdr->addr2, res);
+ if (res == -2)
+ RTLLIB_DEBUG_DROP("Decryption failed ICV mismatch (key %d)\n",
+ skb->data[hdrlen + 3] >> 6);
+ ieee->ieee_stats.rx_discards_undecryptable++;
+ return -1;
+ }
+
+ return res;
+}
+
+
+/* Called only as a tasklet (software IRQ), by rtllib_rx */
+static inline int
+rtllib_rx_frame_decrypt_msdu(struct rtllib_device *ieee, struct sk_buff *skb,
+ int keyidx, struct lib80211_crypt_data *crypt)
+{
+ struct rtllib_hdr_4addr *hdr;
+ int res, hdrlen;
+
+ if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
+ return 0;
+ if (ieee->hwsec_active) {
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
+
+ tcb_desc->bHwSec = 1;
+
+ if (ieee->need_sw_enc)
+ tcb_desc->bHwSec = 0;
+ }
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+ atomic_inc(&crypt->refcnt);
+ res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed (SA= %pM keyidx=%d)\n",
+ ieee->dev->name, hdr->addr2, keyidx);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* this function is stolen from ipw2200 driver*/
+#define IEEE_PACKET_RETRY_TIME (5*HZ)
+static int is_duplicate_packet(struct rtllib_device *ieee,
+ struct rtllib_hdr_4addr *header)
+{
+ u16 fc = le16_to_cpu(header->frame_ctl);
+ u16 sc = le16_to_cpu(header->seq_ctl);
+ u16 seq = WLAN_GET_SEQ_SEQ(sc);
+ u16 frag = WLAN_GET_SEQ_FRAG(sc);
+ u16 *last_seq, *last_frag;
+ unsigned long *last_time;
+ struct rtllib_hdr_3addrqos *hdr_3addrqos;
+ struct rtllib_hdr_4addrqos *hdr_4addrqos;
+ u8 tid;
+
+ if (((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS) && RTLLIB_QOS_HAS_SEQ(fc)) {
+ hdr_4addrqos = (struct rtllib_hdr_4addrqos *)header;
+ tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+ tid = UP2AC(tid);
+ tid++;
+ } else if (RTLLIB_QOS_HAS_SEQ(fc)) {
+ hdr_3addrqos = (struct rtllib_hdr_3addrqos *)header;
+ tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID;
+ tid = UP2AC(tid);
+ tid++;
+ } else {
+ tid = 0;
+ }
+
+ switch (ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ {
+ struct list_head *p;
+ struct ieee_ibss_seq *entry = NULL;
+ u8 *mac = header->addr2;
+ int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
+
+ list_for_each(p, &ieee->ibss_mac_hash[index]) {
+ entry = list_entry(p, struct ieee_ibss_seq, list);
+ if (!memcmp(entry->mac, mac, ETH_ALEN))
+ break;
+ }
+ if (p == &ieee->ibss_mac_hash[index]) {
+ entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
+ if (!entry)
+ return 0;
+
+ memcpy(entry->mac, mac, ETH_ALEN);
+ entry->seq_num[tid] = seq;
+ entry->frag_num[tid] = frag;
+ entry->packet_time[tid] = jiffies;
+ list_add(&entry->list, &ieee->ibss_mac_hash[index]);
+ return 0;
+ }
+ last_seq = &entry->seq_num[tid];
+ last_frag = &entry->frag_num[tid];
+ last_time = &entry->packet_time[tid];
+ break;
+ }
+
+ case IW_MODE_INFRA:
+ last_seq = &ieee->last_rxseq_num[tid];
+ last_frag = &ieee->last_rxfrag_num[tid];
+ last_time = &ieee->last_packet_time[tid];
+ break;
+ default:
+ return 0;
+ }
+
+ if ((*last_seq == seq) &&
+ time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
+ if (*last_frag == frag)
+ goto drop;
+ if (*last_frag + 1 != frag)
+ /* out-of-order fragment */
+ goto drop;
+ } else
+ *last_seq = seq;
+
+ *last_frag = frag;
+ *last_time = jiffies;
+ return 0;
+
+drop:
+
+ return 1;
+}
+
+static bool AddReorderEntry(struct rx_ts_record *pTS,
+ struct rx_reorder_entry *pReorderEntry)
+{
+ struct list_head *pList = &pTS->RxPendingPktList;
+
+ while (pList->next != &pTS->RxPendingPktList) {
+ if (SN_LESS(pReorderEntry->SeqNum, ((struct rx_reorder_entry *)
+ list_entry(pList->next, struct rx_reorder_entry,
+ List))->SeqNum))
+ pList = pList->next;
+ else if (SN_EQUAL(pReorderEntry->SeqNum,
+ ((struct rx_reorder_entry *)list_entry(pList->next,
+ struct rx_reorder_entry, List))->SeqNum))
+ return false;
+ else
+ break;
+ }
+ pReorderEntry->List.next = pList->next;
+ pReorderEntry->List.next->prev = &pReorderEntry->List;
+ pReorderEntry->List.prev = pList;
+ pList->next = &pReorderEntry->List;
+
+ return true;
+}
+
+void rtllib_indicate_packets(struct rtllib_device *ieee, struct rtllib_rxb **prxbIndicateArray, u8 index)
+{
+ struct net_device_stats *stats = &ieee->stats;
+ u8 i = 0 , j = 0;
+ u16 ethertype;
+
+ for (j = 0; j < index; j++) {
+ struct rtllib_rxb *prxb = prxbIndicateArray[j];
+
+ for (i = 0; i < prxb->nr_subframes; i++) {
+ struct sk_buff *sub_skb = prxb->subframes[i];
+
+ /* convert hdr + possible LLC headers into Ethernet header */
+ ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
+ if (sub_skb->len >= 8 &&
+ ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
+ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+ memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
+ /* remove RFC1042 or Bridge-Tunnel encapsulation
+ * and replace EtherType
+ */
+ skb_pull(sub_skb, SNAP_SIZE);
+ memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
+ memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
+ } else {
+ u16 len;
+ /* Leave Ethernet header part of hdr and full payload */
+ len = sub_skb->len;
+ memcpy(skb_push(sub_skb, 2), &len, 2);
+ memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
+ memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
+ }
+
+ /* Indicate the packets to upper layer */
+ if (sub_skb) {
+ stats->rx_packets++;
+ stats->rx_bytes += sub_skb->len;
+
+ memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
+ sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev);
+ sub_skb->dev = ieee->dev;
+ sub_skb->dev->stats.rx_packets++;
+ sub_skb->dev->stats.rx_bytes += sub_skb->len;
+ sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
+ ieee->last_rx_ps_time = jiffies;
+ netif_rx(sub_skb);
+ }
+ }
+ kfree(prxb);
+ prxb = NULL;
+ }
+}
+
+void rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee, struct rx_ts_record *pTS)
+{
+ struct rx_reorder_entry *pRxReorderEntry;
+ u8 RfdCnt = 0;
+
+ del_timer_sync(&pTS->RxPktPendingTimer);
+ while (!list_empty(&pTS->RxPendingPktList)) {
+ if (RfdCnt >= REORDER_WIN_SIZE) {
+ netdev_info(ieee->dev,
+ "-------------->%s() error! RfdCnt >= REORDER_WIN_SIZE\n",
+ __func__);
+ break;
+ }
+
+ pRxReorderEntry = (struct rx_reorder_entry *)list_entry(pTS->RxPendingPktList.prev, struct rx_reorder_entry, List);
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate SeqNum %d!\n", __func__, pRxReorderEntry->SeqNum);
+ list_del_init(&pRxReorderEntry->List);
+
+ ieee->RfdArray[RfdCnt] = pRxReorderEntry->prxb;
+
+ RfdCnt = RfdCnt + 1;
+ list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List);
+ }
+ rtllib_indicate_packets(ieee, ieee->RfdArray, RfdCnt);
+
+ pTS->RxIndicateSeq = 0xffff;
+}
+
+static void RxReorderIndicatePacket(struct rtllib_device *ieee,
+ struct rtllib_rxb *prxb,
+ struct rx_ts_record *pTS, u16 SeqNum)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+ struct rx_reorder_entry *pReorderEntry = NULL;
+ u8 WinSize = pHTInfo->RxReorderWinSize;
+ u16 WinEnd = 0;
+ u8 index = 0;
+ bool bMatchWinStart = false, bPktInBuf = false;
+ unsigned long flags;
+
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Seq is %d, pTS->RxIndicateSeq is %d, WinSize is %d\n", __func__, SeqNum,
+ pTS->RxIndicateSeq, WinSize);
+
+ spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
+
+ WinEnd = (pTS->RxIndicateSeq + WinSize - 1) % 4096;
+ /* Rx Reorder initialize condition.*/
+ if (pTS->RxIndicateSeq == 0xffff)
+ pTS->RxIndicateSeq = SeqNum;
+
+ /* Drop out the packet which SeqNum is smaller than WinStart */
+ if (SN_LESS(SeqNum, pTS->RxIndicateSeq)) {
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packet Drop! IndicateSeq: %d, NewSeq: %d\n",
+ pTS->RxIndicateSeq, SeqNum);
+ pHTInfo->RxReorderDropCounter++;
+ {
+ int i;
+
+ for (i = 0; i < prxb->nr_subframes; i++)
+ dev_kfree_skb(prxb->subframes[i]);
+ kfree(prxb);
+ prxb = NULL;
+ }
+ spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+ return;
+ }
+
+ /* Sliding window manipulation. Conditions includes:
+ * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
+ * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
+ */
+ if (SN_EQUAL(SeqNum, pTS->RxIndicateSeq)) {
+ pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
+ bMatchWinStart = true;
+ } else if (SN_LESS(WinEnd, SeqNum)) {
+ if (SeqNum >= (WinSize - 1))
+ pTS->RxIndicateSeq = SeqNum + 1 - WinSize;
+ else
+ pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum + 1)) + 1;
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum);
+ }
+
+ /* Indication process.
+ * After Packet dropping and Sliding Window shifting as above, we can
+ * now just indicate the packets with the SeqNum smaller than latest
+ * WinStart and struct buffer other packets.
+ *
+ * For Rx Reorder condition:
+ * 1. All packets with SeqNum smaller than WinStart => Indicate
+ * 2. All packets with SeqNum larger than or equal to
+ * WinStart => Buffer it.
+ */
+ if (bMatchWinStart) {
+ /* Current packet is going to be indicated.*/
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",
+ pTS->RxIndicateSeq, SeqNum);
+ ieee->prxbIndicateArray[0] = prxb;
+ index = 1;
+ } else {
+ /* Current packet is going to be inserted into pending list.*/
+ if (!list_empty(&ieee->RxReorder_Unused_List)) {
+ pReorderEntry = (struct rx_reorder_entry *)
+ list_entry(ieee->RxReorder_Unused_List.next,
+ struct rx_reorder_entry, List);
+ list_del_init(&pReorderEntry->List);
+
+ /* Make a reorder entry and insert into a the packet list.*/
+ pReorderEntry->SeqNum = SeqNum;
+ pReorderEntry->prxb = prxb;
+
+ if (!AddReorderEntry(pTS, pReorderEntry)) {
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER,
+ "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n",
+ __func__, pTS->RxIndicateSeq,
+ SeqNum);
+ list_add_tail(&pReorderEntry->List,
+ &ieee->RxReorder_Unused_List); {
+ int i;
+
+ for (i = 0; i < prxb->nr_subframes; i++)
+ dev_kfree_skb(prxb->subframes[i]);
+ kfree(prxb);
+ prxb = NULL;
+ }
+ } else {
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER,
+ "Pkt insert into struct buffer!! IndicateSeq: %d, NewSeq: %d\n",
+ pTS->RxIndicateSeq, SeqNum);
+ }
+ } else {
+ /* Packets are dropped if there are not enough reorder
+ * entries. This part should be modified!! We can just
+ * indicate all the packets in struct buffer and get
+ * reorder entries.
+ */
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n");
+ {
+ int i;
+
+ for (i = 0; i < prxb->nr_subframes; i++)
+ dev_kfree_skb(prxb->subframes[i]);
+ kfree(prxb);
+ prxb = NULL;
+ }
+ }
+ }
+
+ /* Check if there is any packet need indicate.*/
+ while (!list_empty(&pTS->RxPendingPktList)) {
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): start RREORDER indicate\n", __func__);
+
+ pReorderEntry = (struct rx_reorder_entry *)list_entry(pTS->RxPendingPktList.prev,
+ struct rx_reorder_entry, List);
+ if (SN_LESS(pReorderEntry->SeqNum, pTS->RxIndicateSeq) ||
+ SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq)) {
+ /* This protect struct buffer from overflow. */
+ if (index >= REORDER_WIN_SIZE) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!!\n");
+ bPktInBuf = true;
+ break;
+ }
+
+ list_del_init(&pReorderEntry->List);
+
+ if (SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
+ pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
+
+ ieee->prxbIndicateArray[index] = pReorderEntry->prxb;
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Indicate SeqNum %d!\n", __func__, pReorderEntry->SeqNum);
+ index++;
+
+ list_add_tail(&pReorderEntry->List,
+ &ieee->RxReorder_Unused_List);
+ } else {
+ bPktInBuf = true;
+ break;
+ }
+ }
+
+ /* Handling pending timer. Set this timer to prevent from long time
+ * Rx buffering.
+ */
+ if (index > 0) {
+ if (timer_pending(&pTS->RxPktPendingTimer))
+ del_timer_sync(&pTS->RxPktPendingTimer);
+ pTS->RxTimeoutIndicateSeq = 0xffff;
+
+ if (index > REORDER_WIN_SIZE) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorder struct buffer full!!\n");
+ spin_unlock_irqrestore(&(ieee->reorder_spinlock),
+ flags);
+ return;
+ }
+ rtllib_indicate_packets(ieee, ieee->prxbIndicateArray, index);
+ bPktInBuf = false;
+ }
+
+ if (bPktInBuf && pTS->RxTimeoutIndicateSeq == 0xffff) {
+ RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): SET rx timeout timer\n",
+ __func__);
+ pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq;
+ mod_timer(&pTS->RxPktPendingTimer, jiffies +
+ msecs_to_jiffies(pHTInfo->RxReorderPendingTime));
+ }
+ spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
+}
+
+static u8 parse_subframe(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats,
+ struct rtllib_rxb *rxb, u8 *src, u8 *dst)
+{
+ struct rtllib_hdr_3addr *hdr = (struct rtllib_hdr_3addr *)skb->data;
+ u16 fc = le16_to_cpu(hdr->frame_ctl);
+
+ u16 LLCOffset = sizeof(struct rtllib_hdr_3addr);
+ u16 ChkLength;
+ bool bIsAggregateFrame = false;
+ u16 nSubframe_Length;
+ u8 nPadding_Length = 0;
+ u16 SeqNum = 0;
+ struct sk_buff *sub_skb;
+ u8 *data_ptr;
+ /* just for debug purpose */
+ SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
+ if ((RTLLIB_QOS_HAS_SEQ(fc)) &&
+ (((union frameqos *)(skb->data + RTLLIB_3ADDR_LEN))->field.reserved))
+ bIsAggregateFrame = true;
+
+ if (RTLLIB_QOS_HAS_SEQ(fc))
+ LLCOffset += 2;
+ if (rx_stats->bContainHTC)
+ LLCOffset += sHTCLng;
+
+ ChkLength = LLCOffset;
+
+ if (skb->len <= ChkLength)
+ return 0;
+
+ skb_pull(skb, LLCOffset);
+ ieee->bIsAggregateFrame = bIsAggregateFrame;
+ if (!bIsAggregateFrame) {
+ rxb->nr_subframes = 1;
+
+ /* altered by clark 3/30/2010
+ * The struct buffer size of the skb indicated to upper layer
+ * must be less than 5000, or the defraged IP datagram
+ * in the IP layer will exceed "ipfrag_high_tresh" and be
+ * discarded. so there must not use the function
+ * "skb_copy" and "skb_clone" for "skb".
+ */
+
+ /* Allocate new skb for releasing to upper layer */
+ sub_skb = dev_alloc_skb(RTLLIB_SKBBUFFER_SIZE);
+ if (!sub_skb)
+ return 0;
+ skb_reserve(sub_skb, 12);
+ data_ptr = (u8 *)skb_put(sub_skb, skb->len);
+ memcpy(data_ptr, skb->data, skb->len);
+ sub_skb->dev = ieee->dev;
+
+ rxb->subframes[0] = sub_skb;
+
+ memcpy(rxb->src, src, ETH_ALEN);
+ memcpy(rxb->dst, dst, ETH_ALEN);
+ rxb->subframes[0]->dev = ieee->dev;
+ return 1;
+ }
+
+ rxb->nr_subframes = 0;
+ memcpy(rxb->src, src, ETH_ALEN);
+ memcpy(rxb->dst, dst, ETH_ALEN);
+ while (skb->len > ETHERNET_HEADER_SIZE) {
+ /* Offset 12 denote 2 mac address */
+ nSubframe_Length = *((u16 *)(skb->data + 12));
+ nSubframe_Length = (nSubframe_Length >> 8) +
+ (nSubframe_Length << 8);
+
+ if (skb->len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
+ netdev_info(ieee->dev,
+ "%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",
+ __func__, rxb->nr_subframes);
+ netdev_info(ieee->dev,
+ "%s: A-MSDU parse error!! Subframe Length: %d\n",
+ __func__, nSubframe_Length);
+ netdev_info(ieee->dev,
+ "nRemain_Length is %d and nSubframe_Length is : %d\n",
+ skb->len, nSubframe_Length);
+ netdev_info(ieee->dev,
+ "The Packet SeqNum is %d\n",
+ SeqNum);
+ return 0;
+ }
+
+ /* move the data point to data content */
+ skb_pull(skb, ETHERNET_HEADER_SIZE);
+
+ /* altered by clark 3/30/2010
+ * The struct buffer size of the skb indicated to upper layer
+ * must be less than 5000, or the defraged IP datagram
+ * in the IP layer will exceed "ipfrag_high_tresh" and be
+ * discarded. so there must not use the function
+ * "skb_copy" and "skb_clone" for "skb".
+ */
+
+ /* Allocate new skb for releasing to upper layer */
+ sub_skb = dev_alloc_skb(nSubframe_Length + 12);
+ if (!sub_skb)
+ return 0;
+ skb_reserve(sub_skb, 12);
+ data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
+ memcpy(data_ptr, skb->data, nSubframe_Length);
+
+ sub_skb->dev = ieee->dev;
+ rxb->subframes[rxb->nr_subframes++] = sub_skb;
+ if (rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
+ RTLLIB_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
+ break;
+ }
+ skb_pull(skb, nSubframe_Length);
+
+ if (skb->len != 0) {
+ nPadding_Length = 4 - ((nSubframe_Length +
+ ETHERNET_HEADER_SIZE) % 4);
+ if (nPadding_Length == 4)
+ nPadding_Length = 0;
+
+ if (skb->len < nPadding_Length)
+ return 0;
+
+ skb_pull(skb, nPadding_Length);
+ }
+ }
+
+ return rxb->nr_subframes;
+}
+
+
+static size_t rtllib_rx_get_hdrlen(struct rtllib_device *ieee,
+ struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats)
+{
+ struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+ u16 fc = le16_to_cpu(hdr->frame_ctl);
+ size_t hdrlen = 0;
+
+ hdrlen = rtllib_get_hdrlen(fc);
+ if (HTCCheck(ieee, skb->data)) {
+ if (net_ratelimit())
+ netdev_info(ieee->dev, "%s: find HTCControl!\n",
+ __func__);
+ hdrlen += 4;
+ rx_stats->bContainHTC = true;
+ }
+
+ if (RTLLIB_QOS_HAS_SEQ(fc))
+ rx_stats->bIsQosData = true;
+
+ return hdrlen;
+}
+
+static int rtllib_rx_check_duplicate(struct rtllib_device *ieee,
+ struct sk_buff *skb, u8 multicast)
+{
+ struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+ u16 fc, sc;
+ u8 frag, type, stype;
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+
+ if ((ieee->pHTInfo->bCurRxReorderEnable == false) ||
+ !ieee->current_network.qos_data.active ||
+ !IsDataFrame(skb->data) ||
+ IsLegacyDataFrame(skb->data)) {
+ if (!((type == RTLLIB_FTYPE_MGMT) && (stype == RTLLIB_STYPE_BEACON))) {
+ if (is_duplicate_packet(ieee, hdr))
+ return -1;
+ }
+ } else {
+ struct rx_ts_record *pRxTS = NULL;
+
+ if (GetTs(ieee, (struct ts_common_info **) &pRxTS, hdr->addr2,
+ (u8)Frame_QoSTID((u8 *)(skb->data)), RX_DIR, true)) {
+ if ((fc & (1<<11)) && (frag == pRxTS->RxLastFragNum) &&
+ (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum))
+ return -1;
+ pRxTS->RxLastFragNum = frag;
+ pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc);
+ } else {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip the check!!\n", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void rtllib_rx_extract_addr(struct rtllib_device *ieee,
+ struct rtllib_hdr_4addr *hdr, u8 *dst,
+ u8 *src, u8 *bssid)
+{
+ u16 fc = le16_to_cpu(hdr->frame_ctl);
+
+ switch (fc & (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) {
+ case RTLLIB_FCTL_FROMDS:
+ memcpy(dst, hdr->addr1, ETH_ALEN);
+ memcpy(src, hdr->addr3, ETH_ALEN);
+ memcpy(bssid, hdr->addr2, ETH_ALEN);
+ break;
+ case RTLLIB_FCTL_TODS:
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr2, ETH_ALEN);
+ memcpy(bssid, hdr->addr1, ETH_ALEN);
+ break;
+ case RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS:
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr4, ETH_ALEN);
+ memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
+ break;
+ case 0:
+ memcpy(dst, hdr->addr1, ETH_ALEN);
+ memcpy(src, hdr->addr2, ETH_ALEN);
+ memcpy(bssid, hdr->addr3, ETH_ALEN);
+ break;
+ }
+}
+
+static int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc,
+ u8 *dst, u8 *src, u8 *bssid, u8 *addr2)
+{
+ u8 type, stype;
+
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+
+ /* Filter frames from different BSS */
+ if (((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS) &&
+ !ether_addr_equal(ieee->current_network.bssid, bssid) &&
+ !is_zero_ether_addr(ieee->current_network.bssid)) {
+ return -1;
+ }
+
+ /* Filter packets sent by an STA that will be forwarded by AP */
+ if (ieee->IntelPromiscuousModeInfo.bPromiscuousOn &&
+ ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame) {
+ if ((fc & RTLLIB_FCTL_TODS) && !(fc & RTLLIB_FCTL_FROMDS) &&
+ !ether_addr_equal(dst, ieee->current_network.bssid) &&
+ ether_addr_equal(bssid, ieee->current_network.bssid)) {
+ return -1;
+ }
+ }
+
+ /* Nullfunc frames may have PS-bit set, so they must be passed to
+ * hostap_handle_sta_rx() before being dropped here.
+ */
+ if (!ieee->IntelPromiscuousModeInfo.bPromiscuousOn) {
+ if (stype != RTLLIB_STYPE_DATA &&
+ stype != RTLLIB_STYPE_DATA_CFACK &&
+ stype != RTLLIB_STYPE_DATA_CFPOLL &&
+ stype != RTLLIB_STYPE_DATA_CFACKPOLL &&
+ stype != RTLLIB_STYPE_QOS_DATA) {
+ if (stype != RTLLIB_STYPE_NULLFUNC)
+ RTLLIB_DEBUG_DROP(
+ "RX: dropped data frame with no data (type=0x%02x, subtype=0x%02x)\n",
+ type, stype);
+ return -1;
+ }
+ }
+
+ if (ieee->iw_mode != IW_MODE_MESH) {
+ /* packets from our adapter are dropped (echo) */
+ if (!memcmp(src, ieee->dev->dev_addr, ETH_ALEN))
+ return -1;
+
+ /* {broad,multi}cast packets to our BSS go through */
+ if (is_multicast_ether_addr(dst)) {
+ if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int rtllib_rx_get_crypt(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct lib80211_crypt_data **crypt, size_t hdrlen)
+{
+ struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+ u16 fc = le16_to_cpu(hdr->frame_ctl);
+ int idx = 0;
+
+ if (ieee->host_decrypt) {
+ if (skb->len >= hdrlen + 3)
+ idx = skb->data[hdrlen + 3] >> 6;
+
+ *crypt = ieee->crypt_info.crypt[idx];
+ /* allow NULL decrypt to indicate an station specific override
+ * for default encryption
+ */
+ if (*crypt && ((*crypt)->ops == NULL ||
+ (*crypt)->ops->decrypt_mpdu == NULL))
+ *crypt = NULL;
+
+ if (!*crypt && (fc & RTLLIB_FCTL_WEP)) {
+ /* This seems to be triggered by some (multicast?)
+ * frames from other than current BSS, so just drop the
+ * frames silently instead of filling system log with
+ * these reports.
+ */
+ RTLLIB_DEBUG_DROP("Decryption failed (not set) (SA= %pM)\n",
+ hdr->addr2);
+ ieee->ieee_stats.rx_discards_undecryptable++;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int rtllib_rx_decrypt(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats,
+ struct lib80211_crypt_data *crypt, size_t hdrlen)
+{
+ struct rtllib_hdr_4addr *hdr;
+ int keyidx = 0;
+ u16 fc, sc;
+ u8 frag;
+
+ hdr = (struct rtllib_hdr_4addr *)skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+
+ if ((!rx_stats->Decrypted))
+ ieee->need_sw_enc = 1;
+ else
+ ieee->need_sw_enc = 0;
+
+ keyidx = rtllib_rx_frame_decrypt(ieee, skb, crypt);
+ if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) && (keyidx < 0)) {
+ netdev_info(ieee->dev, "%s: decrypt frame error\n", __func__);
+ return -1;
+ }
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ if ((frag != 0 || (fc & RTLLIB_FCTL_MOREFRAGS))) {
+ int flen;
+ struct sk_buff *frag_skb = rtllib_frag_cache_get(ieee, hdr);
+
+ RTLLIB_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
+
+ if (!frag_skb) {
+ RTLLIB_DEBUG(RTLLIB_DL_RX | RTLLIB_DL_FRAG,
+ "Rx cannot get skb from fragment cache (morefrag=%d seq=%u frag=%u)\n",
+ (fc & RTLLIB_FCTL_MOREFRAGS) != 0,
+ WLAN_GET_SEQ_SEQ(sc), frag);
+ return -1;
+ }
+ flen = skb->len;
+ if (frag != 0)
+ flen -= hdrlen;
+
+ if (frag_skb->tail + flen > frag_skb->end) {
+ netdev_warn(ieee->dev,
+ "%s: host decrypted and reassembled frame did not fit skb\n",
+ __func__);
+ rtllib_frag_cache_invalidate(ieee, hdr);
+ return -1;
+ }
+
+ if (frag == 0) {
+ /* copy first fragment (including full headers) into
+ * beginning of the fragment cache skb
+ */
+ memcpy(skb_put(frag_skb, flen), skb->data, flen);
+ } else {
+ /* append frame payload to the end of the fragment
+ * cache skb
+ */
+ memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
+ flen);
+ }
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+
+ if (fc & RTLLIB_FCTL_MOREFRAGS) {
+ /* more fragments expected - leave the skb in fragment
+ * cache for now; it will be delivered to upper layers
+ * after all fragments have been received
+ */
+ return -2;
+ }
+
+ /* this was the last fragment and the frame will be
+ * delivered, so remove skb from fragment cache
+ */
+ skb = frag_skb;
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ rtllib_frag_cache_invalidate(ieee, hdr);
+ }
+
+ /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
+ * encrypted/authenticated
+ */
+ if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) &&
+ rtllib_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) {
+ netdev_info(ieee->dev, "%s: ==>decrypt msdu error\n", __func__);
+ return -1;
+ }
+
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep) {
+ if (/*ieee->ieee802_1x &&*/
+ rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+
+ /* pass unencrypted EAPOL frames even if encryption is
+ * configured
+ */
+ struct eapol *eap = (struct eapol *)(skb->data +
+ 24);
+ RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
+ eap_get_type(eap->type));
+ } else {
+ RTLLIB_DEBUG_DROP(
+ "encryption configured, but RX frame not encrypted (SA= %pM)\n",
+ hdr->addr2);
+ return -1;
+ }
+ }
+
+ if (crypt && !(fc & RTLLIB_FCTL_WEP) &&
+ rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+ struct eapol *eap = (struct eapol *)(skb->data +
+ 24);
+ RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
+ eap_get_type(eap->type));
+ }
+
+ if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep &&
+ !rtllib_is_eapol_frame(ieee, skb, hdrlen)) {
+ RTLLIB_DEBUG_DROP(
+ "dropped unencrypted RX data frame from %pM (drop_unencrypted=1)\n",
+ hdr->addr2);
+ return -1;
+ }
+
+ if (rtllib_is_eapol_frame(ieee, skb, hdrlen))
+ netdev_warn(ieee->dev, "RX: IEEE802.1X EAPOL frame!\n");
+
+ return 0;
+}
+
+static void rtllib_rx_check_leave_lps(struct rtllib_device *ieee, u8 unicast, u8 nr_subframes)
+{
+ if (unicast) {
+
+ if (ieee->state == RTLLIB_LINKED) {
+ if (((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +
+ ieee->LinkDetectInfo.NumTxOkInPeriod) > 8) ||
+ (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2)) {
+ if (ieee->LeisurePSLeave)
+ ieee->LeisurePSLeave(ieee->dev);
+ }
+ }
+ }
+ ieee->last_rx_ps_time = jiffies;
+}
+
+static void rtllib_rx_indicate_pkt_legacy(struct rtllib_device *ieee,
+ struct rtllib_rx_stats *rx_stats,
+ struct rtllib_rxb *rxb,
+ u8 *dst,
+ u8 *src)
+{
+ struct net_device *dev = ieee->dev;
+ u16 ethertype;
+ int i = 0;
+
+ if (rxb == NULL) {
+ netdev_info(dev, "%s: rxb is NULL!!\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < rxb->nr_subframes; i++) {
+ struct sk_buff *sub_skb = rxb->subframes[i];
+
+ if (sub_skb) {
+ /* convert hdr + possible LLC headers into Ethernet header */
+ ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
+ if (sub_skb->len >= 8 &&
+ ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
+ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+ memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
+ /* remove RFC1042 or Bridge-Tunnel encapsulation and
+ * replace EtherType
+ */
+ skb_pull(sub_skb, SNAP_SIZE);
+ memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
+ } else {
+ u16 len;
+ /* Leave Ethernet header part of hdr and full payload */
+ len = sub_skb->len;
+ memcpy(skb_push(sub_skb, 2), &len, 2);
+ memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
+ }
+
+ ieee->stats.rx_packets++;
+ ieee->stats.rx_bytes += sub_skb->len;
+
+ if (is_multicast_ether_addr(dst))
+ ieee->stats.multicast++;
+
+ /* Indicate the packets to upper layer */
+ memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
+ sub_skb->protocol = eth_type_trans(sub_skb, dev);
+ sub_skb->dev = dev;
+ sub_skb->dev->stats.rx_packets++;
+ sub_skb->dev->stats.rx_bytes += sub_skb->len;
+ sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
+ netif_rx(sub_skb);
+ }
+ }
+ kfree(rxb);
+}
+
+static int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats)
+{
+ struct net_device *dev = ieee->dev;
+ struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+ struct lib80211_crypt_data *crypt = NULL;
+ struct rtllib_rxb *rxb = NULL;
+ struct rx_ts_record *pTS = NULL;
+ u16 fc, sc, SeqNum = 0;
+ u8 type, stype, multicast = 0, unicast = 0, nr_subframes = 0, TID = 0;
+ u8 dst[ETH_ALEN], src[ETH_ALEN], bssid[ETH_ALEN] = {0}, *payload;
+ size_t hdrlen = 0;
+ bool bToOtherSTA = false;
+ int ret = 0, i = 0;
+
+ hdr = (struct rtllib_hdr_4addr *)skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+ sc = le16_to_cpu(hdr->seq_ctl);
+
+ /*Filter pkt not to me*/
+ multicast = is_multicast_ether_addr(hdr->addr1);
+ unicast = !multicast;
+ if (unicast && !ether_addr_equal(dev->dev_addr, hdr->addr1)) {
+ if (ieee->bNetPromiscuousMode)
+ bToOtherSTA = true;
+ else
+ goto rx_dropped;
+ }
+
+ /*Filter pkt has too small length */
+ hdrlen = rtllib_rx_get_hdrlen(ieee, skb, rx_stats);
+ if (skb->len < hdrlen) {
+ netdev_info(dev, "%s():ERR!!! skb->len is smaller than hdrlen\n",
+ __func__);
+ goto rx_dropped;
+ }
+
+ /* Filter Duplicate pkt */
+ ret = rtllib_rx_check_duplicate(ieee, skb, multicast);
+ if (ret < 0)
+ goto rx_dropped;
+
+ /* Filter CTRL Frame */
+ if (type == RTLLIB_FTYPE_CTL)
+ goto rx_dropped;
+
+ /* Filter MGNT Frame */
+ if (type == RTLLIB_FTYPE_MGMT) {
+ if (bToOtherSTA)
+ goto rx_dropped;
+ if (rtllib_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
+ goto rx_dropped;
+ else
+ goto rx_exit;
+ }
+
+ /* Filter WAPI DATA Frame */
+
+ /* Update statstics for AP roaming */
+ if (!bToOtherSTA) {
+ ieee->LinkDetectInfo.NumRecvDataInPeriod++;
+ ieee->LinkDetectInfo.NumRxOkInPeriod++;
+ }
+ dev->last_rx = jiffies;
+
+ /* Data frame - extract src/dst addresses */
+ rtllib_rx_extract_addr(ieee, hdr, dst, src, bssid);
+
+ /* Filter Data frames */
+ ret = rtllib_rx_data_filter(ieee, fc, dst, src, bssid, hdr->addr2);
+ if (ret < 0)
+ goto rx_dropped;
+
+ if (skb->len == hdrlen)
+ goto rx_dropped;
+
+ /* Send pspoll based on moredata */
+ if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->sta_sleep == LPS_IS_SLEEP)
+ && (ieee->polling) && (!bToOtherSTA)) {
+ if (WLAN_FC_MORE_DATA(fc)) {
+ /* more data bit is set, let's request a new frame from the AP */
+ rtllib_sta_ps_send_pspoll_frame(ieee);
+ } else {
+ ieee->polling = false;
+ }
+ }
+
+ /* Get crypt if encrypted */
+ ret = rtllib_rx_get_crypt(ieee, skb, &crypt, hdrlen);
+ if (ret == -1)
+ goto rx_dropped;
+
+ /* Decrypt data frame (including reassemble) */
+ ret = rtllib_rx_decrypt(ieee, skb, rx_stats, crypt, hdrlen);
+ if (ret == -1)
+ goto rx_dropped;
+ else if (ret == -2)
+ goto rx_exit;
+
+ /* Get TS for Rx Reorder */
+ hdr = (struct rtllib_hdr_4addr *) skb->data;
+ if (ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
+ && !is_multicast_ether_addr(hdr->addr1)
+ && (!bToOtherSTA)) {
+ TID = Frame_QoSTID(skb->data);
+ SeqNum = WLAN_GET_SEQ_SEQ(sc);
+ GetTs(ieee, (struct ts_common_info **) &pTS, hdr->addr2, TID, RX_DIR, true);
+ if (TID != 0 && TID != 3)
+ ieee->bis_any_nonbepkts = true;
+ }
+
+ /* Parse rx data frame (For AMSDU) */
+ /* skb: hdr + (possible reassembled) full plaintext payload */
+ payload = skb->data + hdrlen;
+ rxb = kmalloc(sizeof(struct rtllib_rxb), GFP_ATOMIC);
+ if (rxb == NULL)
+ goto rx_dropped;
+
+ /* to parse amsdu packets */
+ /* qos data packets & reserved bit is 1 */
+ if (parse_subframe(ieee, skb, rx_stats, rxb, src, dst) == 0) {
+ /* only to free rxb, and not submit the packets to upper layer */
+ for (i = 0; i < rxb->nr_subframes; i++)
+ dev_kfree_skb(rxb->subframes[i]);
+ kfree(rxb);
+ rxb = NULL;
+ goto rx_dropped;
+ }
+
+ /* Update WAPI PN */
+
+ /* Check if leave LPS */
+ if (!bToOtherSTA) {
+ if (ieee->bIsAggregateFrame)
+ nr_subframes = rxb->nr_subframes;
+ else
+ nr_subframes = 1;
+ if (unicast)
+ ieee->LinkDetectInfo.NumRxUnicastOkInPeriod += nr_subframes;
+ rtllib_rx_check_leave_lps(ieee, unicast, nr_subframes);
+ }
+
+ /* Indicate packets to upper layer or Rx Reorder */
+ if (ieee->pHTInfo->bCurRxReorderEnable == false || pTS == NULL || bToOtherSTA)
+ rtllib_rx_indicate_pkt_legacy(ieee, rx_stats, rxb, dst, src);
+ else
+ RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum);
+
+ dev_kfree_skb(skb);
+
+ rx_exit:
+ return 1;
+
+ rx_dropped:
+ ieee->stats.rx_dropped++;
+
+ /* Returning 0 indicates to caller that we have not handled the SKB--
+ * so it is still allocated and can be used again by underlying
+ * hardware as a DMA target
+ */
+ return 0;
+}
+
+static int rtllib_rx_Master(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats)
+{
+ return 0;
+}
+
+static int rtllib_rx_Monitor(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats)
+{
+ struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data;
+ u16 fc = le16_to_cpu(hdr->frame_ctl);
+ size_t hdrlen = rtllib_get_hdrlen(fc);
+
+ if (skb->len < hdrlen) {
+ netdev_info(ieee->dev,
+ "%s():ERR!!! skb->len is smaller than hdrlen\n",
+ __func__);
+ return 0;
+ }
+
+ if (HTCCheck(ieee, skb->data)) {
+ if (net_ratelimit())
+ netdev_info(ieee->dev, "%s: Find HTCControl!\n",
+ __func__);
+ hdrlen += 4;
+ }
+
+ rtllib_monitor_rx(ieee, skb, rx_stats, hdrlen);
+ ieee->stats.rx_packets++;
+ ieee->stats.rx_bytes += skb->len;
+
+ return 1;
+}
+
+static int rtllib_rx_Mesh(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats)
+{
+ return 0;
+}
+
+/* All received frames are sent to this function. @skb contains the frame in
+ * IEEE 802.11 format, i.e., in the format it was sent over air.
+ * This function is called only as a tasklet (software IRQ).
+ */
+int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats)
+{
+ int ret = 0;
+
+ if ((NULL == ieee) || (NULL == skb) || (NULL == rx_stats)) {
+ pr_info("%s: Input parameters NULL!\n", __func__);
+ goto rx_dropped;
+ }
+ if (skb->len < 10) {
+ netdev_info(ieee->dev, "%s: SKB length < 10\n", __func__);
+ goto rx_dropped;
+ }
+
+ switch (ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ case IW_MODE_INFRA:
+ ret = rtllib_rx_InfraAdhoc(ieee, skb, rx_stats);
+ break;
+ case IW_MODE_MASTER:
+ case IW_MODE_REPEAT:
+ ret = rtllib_rx_Master(ieee, skb, rx_stats);
+ break;
+ case IW_MODE_MONITOR:
+ ret = rtllib_rx_Monitor(ieee, skb, rx_stats);
+ break;
+ case IW_MODE_MESH:
+ ret = rtllib_rx_Mesh(ieee, skb, rx_stats);
+ break;
+ default:
+ netdev_info(ieee->dev, "%s: ERR iw mode!!!\n", __func__);
+ break;
+ }
+
+ return ret;
+
+ rx_dropped:
+ if (ieee)
+ ieee->stats.rx_dropped++;
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_rx);
+
+static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
+
+/* Make ther structure we read from the beacon packet has the right values */
+static int rtllib_verify_qos_info(struct rtllib_qos_information_element
+ *info_element, int sub_type)
+{
+
+ if (info_element->qui_subtype != sub_type)
+ return -1;
+ if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
+ return -1;
+ if (info_element->qui_type != QOS_OUI_TYPE)
+ return -1;
+ if (info_element->version != QOS_VERSION_1)
+ return -1;
+
+ return 0;
+}
+
+
+/* Parse a QoS parameter element */
+static int rtllib_read_qos_param_element(struct rtllib_qos_parameter_info
+ *element_param, struct rtllib_info_element
+ *info_element)
+{
+ int ret = 0;
+ u16 size = sizeof(struct rtllib_qos_parameter_info) - 2;
+
+ if ((info_element == NULL) || (element_param == NULL))
+ return -1;
+
+ if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
+ memcpy(element_param->info_element.qui, info_element->data,
+ info_element->len);
+ element_param->info_element.elementID = info_element->id;
+ element_param->info_element.length = info_element->len;
+ } else
+ ret = -1;
+ if (ret == 0)
+ ret = rtllib_verify_qos_info(&element_param->info_element,
+ QOS_OUI_PARAM_SUB_TYPE);
+ return ret;
+}
+
+/* Parse a QoS information element */
+static int rtllib_read_qos_info_element(struct
+ rtllib_qos_information_element
+ *element_info, struct rtllib_info_element
+ *info_element)
+{
+ int ret = 0;
+ u16 size = sizeof(struct rtllib_qos_information_element) - 2;
+
+ if (element_info == NULL)
+ return -1;
+ if (info_element == NULL)
+ return -1;
+
+ if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
+ memcpy(element_info->qui, info_element->data,
+ info_element->len);
+ element_info->elementID = info_element->id;
+ element_info->length = info_element->len;
+ } else
+ ret = -1;
+
+ if (ret == 0)
+ ret = rtllib_verify_qos_info(element_info,
+ QOS_OUI_INFO_SUB_TYPE);
+ return ret;
+}
+
+
+/* Write QoS parameters from the ac parameters. */
+static int rtllib_qos_convert_ac_to_parameters(struct rtllib_qos_parameter_info *param_elm,
+ struct rtllib_qos_data *qos_data)
+{
+ struct rtllib_qos_ac_parameter *ac_params;
+ struct rtllib_qos_parameters *qos_param = &(qos_data->parameters);
+ int i;
+ u8 aci;
+ u8 acm;
+
+ qos_data->wmm_acm = 0;
+ for (i = 0; i < QOS_QUEUE_NUM; i++) {
+ ac_params = &(param_elm->ac_params_record[i]);
+
+ aci = (ac_params->aci_aifsn & 0x60) >> 5;
+ acm = (ac_params->aci_aifsn & 0x10) >> 4;
+
+ if (aci >= QOS_QUEUE_NUM)
+ continue;
+ switch (aci) {
+ case 1:
+ /* BIT(0) | BIT(3) */
+ if (acm)
+ qos_data->wmm_acm |= (0x01<<0)|(0x01<<3);
+ break;
+ case 2:
+ /* BIT(4) | BIT(5) */
+ if (acm)
+ qos_data->wmm_acm |= (0x01<<4)|(0x01<<5);
+ break;
+ case 3:
+ /* BIT(6) | BIT(7) */
+ if (acm)
+ qos_data->wmm_acm |= (0x01<<6)|(0x01<<7);
+ break;
+ case 0:
+ default:
+ /* BIT(1) | BIT(2) */
+ if (acm)
+ qos_data->wmm_acm |= (0x01<<1)|(0x01<<2);
+ break;
+ }
+
+ qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f;
+
+ /* WMM spec P.11: The minimum value for AIFSN shall be 2 */
+ qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2 : qos_param->aifs[aci];
+
+ qos_param->cw_min[aci] = cpu_to_le16(ac_params->ecw_min_max & 0x0F);
+
+ qos_param->cw_max[aci] = cpu_to_le16((ac_params->ecw_min_max & 0xF0) >> 4);
+
+ qos_param->flag[aci] =
+ (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
+ qos_param->tx_op_limit[aci] = ac_params->tx_op_limit;
+ }
+ return 0;
+}
+
+/* we have a generic data element which it may contain QoS information or
+ * parameters element. check the information element length to decide
+ * which type to read
+ */
+static int rtllib_parse_qos_info_param_IE(struct rtllib_info_element
+ *info_element,
+ struct rtllib_network *network)
+{
+ int rc = 0;
+ struct rtllib_qos_information_element qos_info_element;
+
+ rc = rtllib_read_qos_info_element(&qos_info_element, info_element);
+
+ if (rc == 0) {
+ network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
+ network->flags |= NETWORK_HAS_QOS_INFORMATION;
+ } else {
+ struct rtllib_qos_parameter_info param_element;
+
+ rc = rtllib_read_qos_param_element(&param_element,
+ info_element);
+ if (rc == 0) {
+ rtllib_qos_convert_ac_to_parameters(&param_element,
+ &(network->qos_data));
+ network->flags |= NETWORK_HAS_QOS_PARAMETERS;
+ network->qos_data.param_count =
+ param_element.info_element.ac_info & 0x0F;
+ }
+ }
+
+ if (rc == 0) {
+ RTLLIB_DEBUG_QOS("QoS is supported\n");
+ network->qos_data.supported = 1;
+ }
+ return rc;
+}
+
+#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
+
+static const char *get_info_element_string(u16 id)
+{
+ switch (id) {
+ MFIE_STRING(SSID);
+ MFIE_STRING(RATES);
+ MFIE_STRING(FH_SET);
+ MFIE_STRING(DS_SET);
+ MFIE_STRING(CF_SET);
+ MFIE_STRING(TIM);
+ MFIE_STRING(IBSS_SET);
+ MFIE_STRING(COUNTRY);
+ MFIE_STRING(HOP_PARAMS);
+ MFIE_STRING(HOP_TABLE);
+ MFIE_STRING(REQUEST);
+ MFIE_STRING(CHALLENGE);
+ MFIE_STRING(POWER_CONSTRAINT);
+ MFIE_STRING(POWER_CAPABILITY);
+ MFIE_STRING(TPC_REQUEST);
+ MFIE_STRING(TPC_REPORT);
+ MFIE_STRING(SUPP_CHANNELS);
+ MFIE_STRING(CSA);
+ MFIE_STRING(MEASURE_REQUEST);
+ MFIE_STRING(MEASURE_REPORT);
+ MFIE_STRING(QUIET);
+ MFIE_STRING(IBSS_DFS);
+ MFIE_STRING(RSN);
+ MFIE_STRING(RATES_EX);
+ MFIE_STRING(GENERIC);
+ MFIE_STRING(QOS_PARAMETER);
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static inline void rtllib_extract_country_ie(
+ struct rtllib_device *ieee,
+ struct rtllib_info_element *info_element,
+ struct rtllib_network *network,
+ u8 *addr2)
+{
+ if (IS_DOT11D_ENABLE(ieee)) {
+ if (info_element->len != 0) {
+ memcpy(network->CountryIeBuf, info_element->data, info_element->len);
+ network->CountryIeLen = info_element->len;
+
+ if (!IS_COUNTRY_IE_VALID(ieee)) {
+ if (rtllib_act_scanning(ieee, false) && ieee->FirstIe_InScan)
+ netdev_info(ieee->dev,
+ "Received beacon ContryIE, SSID: <%s>\n",
+ network->ssid);
+ Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
+ }
+ }
+
+ if (IS_EQUAL_CIE_SRC(ieee, addr2))
+ UPDATE_CIE_WATCHDOG(ieee);
+ }
+
+}
+
+int rtllib_parse_info_param(struct rtllib_device *ieee,
+ struct rtllib_info_element *info_element,
+ u16 length,
+ struct rtllib_network *network,
+ struct rtllib_rx_stats *stats)
+{
+ u8 i;
+ short offset;
+ u16 tmp_htcap_len = 0;
+ u16 tmp_htinfo_len = 0;
+ u16 ht_realtek_agg_len = 0;
+ u8 ht_realtek_agg_buf[MAX_IE_LEN];
+ char rates_str[64];
+ char *p;
+
+ while (length >= sizeof(*info_element)) {
+ if (sizeof(*info_element) + info_element->len > length) {
+ RTLLIB_DEBUG_MGMT("Info elem: parse failed: info_element->len + 2 > left : info_element->len+2=%zd left=%d, id=%d.\n",
+ info_element->len +
+ sizeof(*info_element),
+ length, info_element->id);
+ /* We stop processing but don't return an error here
+ * because some misbehaviour APs break this rule. ie.
+ * Orinoco AP1000.
+ */
+ break;
+ }
+
+ switch (info_element->id) {
+ case MFIE_TYPE_SSID:
+ if (rtllib_is_empty_essid(info_element->data,
+ info_element->len)) {
+ network->flags |= NETWORK_EMPTY_ESSID;
+ break;
+ }
+
+ network->ssid_len = min(info_element->len,
+ (u8) IW_ESSID_MAX_SIZE);
+ memcpy(network->ssid, info_element->data, network->ssid_len);
+ if (network->ssid_len < IW_ESSID_MAX_SIZE)
+ memset(network->ssid + network->ssid_len, 0,
+ IW_ESSID_MAX_SIZE - network->ssid_len);
+
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
+ network->ssid, network->ssid_len);
+ break;
+
+ case MFIE_TYPE_RATES:
+ p = rates_str;
+ network->rates_len = min(info_element->len,
+ MAX_RATES_LENGTH);
+ for (i = 0; i < network->rates_len; i++) {
+ network->rates[i] = info_element->data[i];
+ p += snprintf(p, sizeof(rates_str) -
+ (p - rates_str), "%02X ",
+ network->rates[i]);
+ if (rtllib_is_ofdm_rate
+ (info_element->data[i])) {
+ network->flags |= NETWORK_HAS_OFDM;
+ if (info_element->data[i] &
+ RTLLIB_BASIC_RATE_MASK)
+ network->flags &=
+ ~NETWORK_HAS_CCK;
+ }
+
+ if (rtllib_is_cck_rate
+ (info_element->data[i])) {
+ network->flags |= NETWORK_HAS_CCK;
+ }
+ }
+
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
+ rates_str, network->rates_len);
+ break;
+
+ case MFIE_TYPE_RATES_EX:
+ p = rates_str;
+ network->rates_ex_len = min(info_element->len,
+ MAX_RATES_EX_LENGTH);
+ for (i = 0; i < network->rates_ex_len; i++) {
+ network->rates_ex[i] = info_element->data[i];
+ p += snprintf(p, sizeof(rates_str) -
+ (p - rates_str), "%02X ",
+ network->rates_ex[i]);
+ if (rtllib_is_ofdm_rate
+ (info_element->data[i])) {
+ network->flags |= NETWORK_HAS_OFDM;
+ if (info_element->data[i] &
+ RTLLIB_BASIC_RATE_MASK)
+ network->flags &=
+ ~NETWORK_HAS_CCK;
+ }
+ }
+
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
+ rates_str, network->rates_ex_len);
+ break;
+
+ case MFIE_TYPE_DS_SET:
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
+ info_element->data[0]);
+ network->channel = info_element->data[0];
+ break;
+
+ case MFIE_TYPE_FH_SET:
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
+ break;
+
+ case MFIE_TYPE_CF_SET:
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
+ break;
+
+ case MFIE_TYPE_TIM:
+ if (info_element->len < 4)
+ break;
+
+ network->tim.tim_count = info_element->data[0];
+ network->tim.tim_period = info_element->data[1];
+
+ network->dtim_period = info_element->data[1];
+ if (ieee->state != RTLLIB_LINKED)
+ break;
+ network->last_dtim_sta_time = jiffies;
+
+ network->dtim_data = RTLLIB_DTIM_VALID;
+
+
+ if (info_element->data[2] & 1)
+ network->dtim_data |= RTLLIB_DTIM_MBCAST;
+
+ offset = (info_element->data[2] >> 1)*2;
+
+
+ if (ieee->assoc_id < 8*offset ||
+ ieee->assoc_id > 8*(offset + info_element->len - 3))
+ break;
+
+ offset = (ieee->assoc_id / 8) - offset;
+ if (info_element->data[3 + offset] &
+ (1 << (ieee->assoc_id % 8)))
+ network->dtim_data |= RTLLIB_DTIM_UCAST;
+
+ network->listen_interval = network->dtim_period;
+ break;
+
+ case MFIE_TYPE_ERP:
+ network->erp_value = info_element->data[0];
+ network->flags |= NETWORK_HAS_ERP_VALUE;
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
+ network->erp_value);
+ break;
+ case MFIE_TYPE_IBSS_SET:
+ network->atim_window = info_element->data[0];
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
+ network->atim_window);
+ break;
+
+ case MFIE_TYPE_CHALLENGE:
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
+ break;
+
+ case MFIE_TYPE_GENERIC:
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
+ info_element->len);
+ if (!rtllib_parse_qos_info_param_IE(info_element,
+ network))
+ break;
+ if (info_element->len >= 4 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x50 &&
+ info_element->data[2] == 0xf2 &&
+ info_element->data[3] == 0x01) {
+ network->wpa_ie_len = min(info_element->len + 2,
+ MAX_WPA_IE_LEN);
+ memcpy(network->wpa_ie, info_element,
+ network->wpa_ie_len);
+ break;
+ }
+ if (info_element->len == 7 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0xe0 &&
+ info_element->data[2] == 0x4c &&
+ info_element->data[3] == 0x01 &&
+ info_element->data[4] == 0x02)
+ network->Turbo_Enable = 1;
+
+ if (tmp_htcap_len == 0) {
+ if (info_element->len >= 4 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x90 &&
+ info_element->data[2] == 0x4c &&
+ info_element->data[3] == 0x033) {
+
+ tmp_htcap_len = min_t(u8, info_element->len, MAX_IE_LEN);
+ if (tmp_htcap_len != 0) {
+ network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
+ network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ?
+ sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len;
+ memcpy(network->bssht.bdHTCapBuf, info_element->data, network->bssht.bdHTCapLen);
+ }
+ }
+ if (tmp_htcap_len != 0) {
+ network->bssht.bdSupportHT = true;
+ network->bssht.bdHT1R = ((((struct ht_capab_ele *)(network->bssht.bdHTCapBuf))->MCS[1]) == 0);
+ } else {
+ network->bssht.bdSupportHT = false;
+ network->bssht.bdHT1R = false;
+ }
+ }
+
+
+ if (tmp_htinfo_len == 0) {
+ if (info_element->len >= 4 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x90 &&
+ info_element->data[2] == 0x4c &&
+ info_element->data[3] == 0x034) {
+ tmp_htinfo_len = min_t(u8, info_element->len, MAX_IE_LEN);
+ if (tmp_htinfo_len != 0) {
+ network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
+ if (tmp_htinfo_len) {
+ network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf) ?
+ sizeof(network->bssht.bdHTInfoBuf) : tmp_htinfo_len;
+ memcpy(network->bssht.bdHTInfoBuf, info_element->data, network->bssht.bdHTInfoLen);
+ }
+
+ }
+
+ }
+ }
+
+ if (ieee->aggregation) {
+ if (network->bssht.bdSupportHT) {
+ if (info_element->len >= 4 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0xe0 &&
+ info_element->data[2] == 0x4c &&
+ info_element->data[3] == 0x02) {
+ ht_realtek_agg_len = min_t(u8, info_element->len, MAX_IE_LEN);
+ memcpy(ht_realtek_agg_buf, info_element->data, info_element->len);
+ }
+ if (ht_realtek_agg_len >= 5) {
+ network->realtek_cap_exit = true;
+ network->bssht.bdRT2RTAggregation = true;
+
+ if ((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02))
+ network->bssht.bdRT2RTLongSlotTime = true;
+
+ if ((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & RT_HT_CAP_USE_92SE))
+ network->bssht.RT2RT_HT_Mode |= RT_HT_CAP_USE_92SE;
+ }
+ }
+ if (ht_realtek_agg_len >= 5) {
+ if ((ht_realtek_agg_buf[5] & RT_HT_CAP_USE_SOFTAP))
+ network->bssht.RT2RT_HT_Mode |= RT_HT_CAP_USE_SOFTAP;
+ }
+ }
+
+ if ((info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x05 &&
+ info_element->data[2] == 0xb5) ||
+ (info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x0a &&
+ info_element->data[2] == 0xf7) ||
+ (info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x10 &&
+ info_element->data[2] == 0x18)) {
+ network->broadcom_cap_exist = true;
+ }
+ if (info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x0c &&
+ info_element->data[2] == 0x43)
+ network->ralink_cap_exist = true;
+ if ((info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x03 &&
+ info_element->data[2] == 0x7f) ||
+ (info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x13 &&
+ info_element->data[2] == 0x74))
+ network->atheros_cap_exist = true;
+
+ if ((info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x50 &&
+ info_element->data[2] == 0x43))
+ network->marvell_cap_exist = true;
+ if (info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x40 &&
+ info_element->data[2] == 0x96)
+ network->cisco_cap_exist = true;
+
+
+ if (info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x0a &&
+ info_element->data[2] == 0xf5)
+ network->airgo_cap_exist = true;
+
+ if (info_element->len > 4 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x40 &&
+ info_element->data[2] == 0x96 &&
+ info_element->data[3] == 0x01) {
+ if (info_element->len == 6) {
+ memcpy(network->CcxRmState, &info_element[4], 2);
+ if (network->CcxRmState[0] != 0)
+ network->bCcxRmEnable = true;
+ else
+ network->bCcxRmEnable = false;
+ network->MBssidMask = network->CcxRmState[1] & 0x07;
+ if (network->MBssidMask != 0) {
+ network->bMBssidValid = true;
+ network->MBssidMask = 0xff << (network->MBssidMask);
+ memcpy(network->MBssid, network->bssid, ETH_ALEN);
+ network->MBssid[5] &= network->MBssidMask;
+ } else {
+ network->bMBssidValid = false;
+ }
+ } else {
+ network->bCcxRmEnable = false;
+ }
+ }
+ if (info_element->len > 4 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x40 &&
+ info_element->data[2] == 0x96 &&
+ info_element->data[3] == 0x03) {
+ if (info_element->len == 5) {
+ network->bWithCcxVerNum = true;
+ network->BssCcxVerNumber = info_element->data[4];
+ } else {
+ network->bWithCcxVerNum = false;
+ network->BssCcxVerNumber = 0;
+ }
+ }
+ if (info_element->len > 4 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x50 &&
+ info_element->data[2] == 0xf2 &&
+ info_element->data[3] == 0x04) {
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_WZC: %d bytes\n",
+ info_element->len);
+ network->wzc_ie_len = min(info_element->len+2,
+ MAX_WZC_IE_LEN);
+ memcpy(network->wzc_ie, info_element,
+ network->wzc_ie_len);
+ }
+ break;
+
+ case MFIE_TYPE_RSN:
+ RTLLIB_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
+ info_element->len);
+ network->rsn_ie_len = min(info_element->len + 2,
+ MAX_WPA_IE_LEN);
+ memcpy(network->rsn_ie, info_element,
+ network->rsn_ie_len);
+ break;
+
+ case MFIE_TYPE_HT_CAP:
+ RTLLIB_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n",
+ info_element->len);
+ tmp_htcap_len = min_t(u8, info_element->len, MAX_IE_LEN);
+ if (tmp_htcap_len != 0) {
+ network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
+ network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf) ?
+ sizeof(network->bssht.bdHTCapBuf) : tmp_htcap_len;
+ memcpy(network->bssht.bdHTCapBuf,
+ info_element->data,
+ network->bssht.bdHTCapLen);
+
+ network->bssht.bdSupportHT = true;
+ network->bssht.bdHT1R = ((((struct ht_capab_ele *)
+ network->bssht.bdHTCapBuf))->MCS[1]) == 0;
+
+ network->bssht.bdBandWidth = (enum ht_channel_width)
+ (((struct ht_capab_ele *)
+ (network->bssht.bdHTCapBuf))->ChlWidth);
+ } else {
+ network->bssht.bdSupportHT = false;
+ network->bssht.bdHT1R = false;
+ network->bssht.bdBandWidth = HT_CHANNEL_WIDTH_20;
+ }
+ break;
+
+
+ case MFIE_TYPE_HT_INFO:
+ RTLLIB_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n",
+ info_element->len);
+ tmp_htinfo_len = min_t(u8, info_element->len, MAX_IE_LEN);
+ if (tmp_htinfo_len) {
+ network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE;
+ network->bssht.bdHTInfoLen = tmp_htinfo_len >
+ sizeof(network->bssht.bdHTInfoBuf) ?
+ sizeof(network->bssht.bdHTInfoBuf) :
+ tmp_htinfo_len;
+ memcpy(network->bssht.bdHTInfoBuf,
+ info_element->data,
+ network->bssht.bdHTInfoLen);
+ }
+ break;
+
+ case MFIE_TYPE_AIRONET:
+ RTLLIB_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n",
+ info_element->len);
+ if (info_element->len > IE_CISCO_FLAG_POSITION) {
+ network->bWithAironetIE = true;
+
+ if ((info_element->data[IE_CISCO_FLAG_POSITION]
+ & SUPPORT_CKIP_MIC) ||
+ (info_element->data[IE_CISCO_FLAG_POSITION]
+ & SUPPORT_CKIP_PK))
+ network->bCkipSupported = true;
+ else
+ network->bCkipSupported = false;
+ } else {
+ network->bWithAironetIE = false;
+ network->bCkipSupported = false;
+ }
+ break;
+ case MFIE_TYPE_QOS_PARAMETER:
+ netdev_err(ieee->dev,
+ "QoS Error need to parse QOS_PARAMETER IE\n");
+ break;
+
+ case MFIE_TYPE_COUNTRY:
+ RTLLIB_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
+ info_element->len);
+ rtllib_extract_country_ie(ieee, info_element, network,
+ network->bssid);
+ break;
+/* TODO */
+ default:
+ RTLLIB_DEBUG_MGMT
+ ("Unsupported info element: %s (%d)\n",
+ get_info_element_string(info_element->id),
+ info_element->id);
+ break;
+ }
+
+ length -= sizeof(*info_element) + info_element->len;
+ info_element =
+ (struct rtllib_info_element *)&info_element->
+ data[info_element->len];
+ }
+
+ if (!network->atheros_cap_exist && !network->broadcom_cap_exist &&
+ !network->cisco_cap_exist && !network->ralink_cap_exist &&
+ !network->bssht.bdRT2RTAggregation)
+ network->unknown_cap_exist = true;
+ else
+ network->unknown_cap_exist = false;
+ return 0;
+}
+
+static long rtllib_translate_todbm(u8 signal_strength_index)
+{
+ long signal_power;
+
+ signal_power = (long)((signal_strength_index + 1) >> 1);
+ signal_power -= 95;
+
+ return signal_power;
+}
+
+static inline int rtllib_network_init(
+ struct rtllib_device *ieee,
+ struct rtllib_probe_response *beacon,
+ struct rtllib_network *network,
+ struct rtllib_rx_stats *stats)
+{
+ memset(&network->qos_data, 0, sizeof(struct rtllib_qos_data));
+
+ /* Pull out fixed field data */
+ memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
+ network->capability = le16_to_cpu(beacon->capability);
+ network->last_scanned = jiffies;
+ network->time_stamp[0] = beacon->time_stamp[0];
+ network->time_stamp[1] = beacon->time_stamp[1];
+ network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
+ /* Where to pull this? beacon->listen_interval;*/
+ network->listen_interval = 0x0A;
+ network->rates_len = network->rates_ex_len = 0;
+ network->last_associate = 0;
+ network->ssid_len = 0;
+ network->hidden_ssid_len = 0;
+ memset(network->hidden_ssid, 0, sizeof(network->hidden_ssid));
+ network->flags = 0;
+ network->atim_window = 0;
+ network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
+ 0x3 : 0x0;
+ network->berp_info_valid = false;
+ network->broadcom_cap_exist = false;
+ network->ralink_cap_exist = false;
+ network->atheros_cap_exist = false;
+ network->cisco_cap_exist = false;
+ network->unknown_cap_exist = false;
+ network->realtek_cap_exit = false;
+ network->marvell_cap_exist = false;
+ network->airgo_cap_exist = false;
+ network->Turbo_Enable = 0;
+ network->SignalStrength = stats->SignalStrength;
+ network->RSSI = stats->SignalStrength;
+ network->CountryIeLen = 0;
+ memset(network->CountryIeBuf, 0, MAX_IE_LEN);
+ HTInitializeBssDesc(&network->bssht);
+ if (stats->freq == RTLLIB_52GHZ_BAND) {
+ /* for A band (No DS info) */
+ network->channel = stats->received_channel;
+ } else
+ network->flags |= NETWORK_HAS_CCK;
+
+ network->wpa_ie_len = 0;
+ network->rsn_ie_len = 0;
+ network->wzc_ie_len = 0;
+
+ if (rtllib_parse_info_param(ieee,
+ beacon->info_element,
+ (stats->len - sizeof(*beacon)),
+ network,
+ stats))
+ return 1;
+
+ network->mode = 0;
+ if (stats->freq == RTLLIB_52GHZ_BAND)
+ network->mode = IEEE_A;
+ else {
+ if (network->flags & NETWORK_HAS_OFDM)
+ network->mode |= IEEE_G;
+ if (network->flags & NETWORK_HAS_CCK)
+ network->mode |= IEEE_B;
+ }
+
+ if (network->mode == 0) {
+ RTLLIB_DEBUG_SCAN("Filtered out '%s (%pM)' network.\n",
+ escape_essid(network->ssid,
+ network->ssid_len),
+ network->bssid);
+ return 1;
+ }
+
+ if (network->bssht.bdSupportHT) {
+ if (network->mode == IEEE_A)
+ network->mode = IEEE_N_5G;
+ else if (network->mode & (IEEE_G | IEEE_B))
+ network->mode = IEEE_N_24G;
+ }
+ if (rtllib_is_empty_essid(network->ssid, network->ssid_len))
+ network->flags |= NETWORK_EMPTY_ESSID;
+ stats->signal = 30 + (stats->SignalStrength * 70) / 100;
+ stats->noise = rtllib_translate_todbm((u8)(100-stats->signal)) - 25;
+
+ memcpy(&network->stats, stats, sizeof(network->stats));
+
+ return 0;
+}
+
+static inline int is_same_network(struct rtllib_network *src,
+ struct rtllib_network *dst, u8 ssidbroad)
+{
+ /* A network is only a duplicate if the channel, BSSID, ESSID
+ * and the capability field (in particular IBSS and BSS) all match.
+ * We treat all <hidden> with the same BSSID and channel
+ * as one network
+ */
+ return (((src->ssid_len == dst->ssid_len) || (!ssidbroad)) &&
+ (src->channel == dst->channel) &&
+ !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
+ (!memcmp(src->ssid, dst->ssid, src->ssid_len) ||
+ (!ssidbroad)) &&
+ ((src->capability & WLAN_CAPABILITY_IBSS) ==
+ (dst->capability & WLAN_CAPABILITY_IBSS)) &&
+ ((src->capability & WLAN_CAPABILITY_ESS) ==
+ (dst->capability & WLAN_CAPABILITY_ESS)));
+}
+
+
+static inline void update_network(struct rtllib_network *dst,
+ struct rtllib_network *src)
+{
+ int qos_active;
+ u8 old_param;
+
+ memcpy(&dst->stats, &src->stats, sizeof(struct rtllib_rx_stats));
+ dst->capability = src->capability;
+ memcpy(dst->rates, src->rates, src->rates_len);
+ dst->rates_len = src->rates_len;
+ memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
+ dst->rates_ex_len = src->rates_ex_len;
+ if (src->ssid_len > 0) {
+ if (dst->ssid_len == 0) {
+ memset(dst->hidden_ssid, 0, sizeof(dst->hidden_ssid));
+ dst->hidden_ssid_len = src->ssid_len;
+ memcpy(dst->hidden_ssid, src->ssid, src->ssid_len);
+ } else {
+ memset(dst->ssid, 0, dst->ssid_len);
+ dst->ssid_len = src->ssid_len;
+ memcpy(dst->ssid, src->ssid, src->ssid_len);
+ }
+ }
+ dst->mode = src->mode;
+ dst->flags = src->flags;
+ dst->time_stamp[0] = src->time_stamp[0];
+ dst->time_stamp[1] = src->time_stamp[1];
+ if (src->flags & NETWORK_HAS_ERP_VALUE) {
+ dst->erp_value = src->erp_value;
+ dst->berp_info_valid = src->berp_info_valid = true;
+ }
+ dst->beacon_interval = src->beacon_interval;
+ dst->listen_interval = src->listen_interval;
+ dst->atim_window = src->atim_window;
+ dst->dtim_period = src->dtim_period;
+ dst->dtim_data = src->dtim_data;
+ dst->last_dtim_sta_time = src->last_dtim_sta_time;
+ memcpy(&dst->tim, &src->tim, sizeof(struct rtllib_tim_parameters));
+
+ dst->bssht.bdSupportHT = src->bssht.bdSupportHT;
+ dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation;
+ dst->bssht.bdHTCapLen = src->bssht.bdHTCapLen;
+ memcpy(dst->bssht.bdHTCapBuf, src->bssht.bdHTCapBuf,
+ src->bssht.bdHTCapLen);
+ dst->bssht.bdHTInfoLen = src->bssht.bdHTInfoLen;
+ memcpy(dst->bssht.bdHTInfoBuf, src->bssht.bdHTInfoBuf,
+ src->bssht.bdHTInfoLen);
+ dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer;
+ dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime;
+ dst->broadcom_cap_exist = src->broadcom_cap_exist;
+ dst->ralink_cap_exist = src->ralink_cap_exist;
+ dst->atheros_cap_exist = src->atheros_cap_exist;
+ dst->realtek_cap_exit = src->realtek_cap_exit;
+ dst->marvell_cap_exist = src->marvell_cap_exist;
+ dst->cisco_cap_exist = src->cisco_cap_exist;
+ dst->airgo_cap_exist = src->airgo_cap_exist;
+ dst->unknown_cap_exist = src->unknown_cap_exist;
+ memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
+ dst->wpa_ie_len = src->wpa_ie_len;
+ memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
+ dst->rsn_ie_len = src->rsn_ie_len;
+ memcpy(dst->wzc_ie, src->wzc_ie, src->wzc_ie_len);
+ dst->wzc_ie_len = src->wzc_ie_len;
+
+ dst->last_scanned = jiffies;
+ /* qos related parameters */
+ qos_active = dst->qos_data.active;
+ old_param = dst->qos_data.param_count;
+ dst->qos_data.supported = src->qos_data.supported;
+ if (dst->flags & NETWORK_HAS_QOS_PARAMETERS)
+ memcpy(&dst->qos_data, &src->qos_data,
+ sizeof(struct rtllib_qos_data));
+ if (dst->qos_data.supported == 1) {
+ if (dst->ssid_len)
+ RTLLIB_DEBUG_QOS
+ ("QoS the network %s is QoS supported\n",
+ dst->ssid);
+ else
+ RTLLIB_DEBUG_QOS
+ ("QoS the network is QoS supported\n");
+ }
+ dst->qos_data.active = qos_active;
+ dst->qos_data.old_param_count = old_param;
+
+ /* dst->last_associate is not overwritten */
+ dst->wmm_info = src->wmm_info;
+ if (src->wmm_param[0].ac_aci_acm_aifsn ||
+ src->wmm_param[1].ac_aci_acm_aifsn ||
+ src->wmm_param[2].ac_aci_acm_aifsn ||
+ src->wmm_param[3].ac_aci_acm_aifsn)
+ memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
+
+ dst->SignalStrength = src->SignalStrength;
+ dst->RSSI = src->RSSI;
+ dst->Turbo_Enable = src->Turbo_Enable;
+
+ dst->CountryIeLen = src->CountryIeLen;
+ memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
+
+ dst->bWithAironetIE = src->bWithAironetIE;
+ dst->bCkipSupported = src->bCkipSupported;
+ memcpy(dst->CcxRmState, src->CcxRmState, 2);
+ dst->bCcxRmEnable = src->bCcxRmEnable;
+ dst->MBssidMask = src->MBssidMask;
+ dst->bMBssidValid = src->bMBssidValid;
+ memcpy(dst->MBssid, src->MBssid, 6);
+ dst->bWithCcxVerNum = src->bWithCcxVerNum;
+ dst->BssCcxVerNumber = src->BssCcxVerNumber;
+}
+
+static inline int is_beacon(__le16 fc)
+{
+ return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == RTLLIB_STYPE_BEACON);
+}
+
+static int IsPassiveChannel(struct rtllib_device *rtllib, u8 channel)
+{
+ if (MAX_CHANNEL_NUMBER < channel) {
+ netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__);
+ return 0;
+ }
+
+ if (rtllib->active_channel_map[channel] == 2)
+ return 1;
+
+ return 0;
+}
+
+int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel)
+{
+ if (MAX_CHANNEL_NUMBER < channel) {
+ netdev_info(rtllib->dev, "%s(): Invalid Channel\n", __func__);
+ return 0;
+ }
+ if (rtllib->active_channel_map[channel] > 0)
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_legal_channel);
+
+static inline void rtllib_process_probe_response(
+ struct rtllib_device *ieee,
+ struct rtllib_probe_response *beacon,
+ struct rtllib_rx_stats *stats)
+{
+ struct rtllib_network *target;
+ struct rtllib_network *oldest = NULL;
+ struct rtllib_info_element *info_element = &beacon->info_element[0];
+ unsigned long flags;
+ short renew;
+ struct rtllib_network *network = kzalloc(sizeof(struct rtllib_network),
+ GFP_ATOMIC);
+
+ if (!network)
+ return;
+
+ RTLLIB_DEBUG_SCAN(
+ "'%s' ( %pM ): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+ escape_essid(info_element->data, info_element->len),
+ beacon->header.addr3,
+ (le16_to_cpu(beacon->capability) & (1<<0xf)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0xe)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0xd)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0xc)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0xb)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0xa)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0x9)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0x8)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0x7)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0x6)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0x5)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0x4)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0x3)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0x2)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0x1)) ? '1' : '0',
+ (le16_to_cpu(beacon->capability) & (1<<0x0)) ? '1' : '0');
+
+ if (rtllib_network_init(ieee, beacon, network, stats)) {
+ RTLLIB_DEBUG_SCAN("Dropped '%s' ( %pM) via %s.\n",
+ escape_essid(info_element->data,
+ info_element->len),
+ beacon->header.addr3,
+ WLAN_FC_GET_STYPE(
+ le16_to_cpu(beacon->header.frame_ctl)) ==
+ RTLLIB_STYPE_PROBE_RESP ?
+ "PROBE RESPONSE" : "BEACON");
+ goto free_network;
+ }
+
+
+ if (!rtllib_legal_channel(ieee, network->channel))
+ goto free_network;
+
+ if (WLAN_FC_GET_STYPE(le16_to_cpu(beacon->header.frame_ctl)) ==
+ RTLLIB_STYPE_PROBE_RESP) {
+ if (IsPassiveChannel(ieee, network->channel)) {
+ netdev_info(ieee->dev,
+ "GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n",
+ network->channel);
+ goto free_network;
+ }
+ }
+
+ /* The network parsed correctly -- so now we scan our known networks
+ * to see if we can find it in our list.
+ *
+ * NOTE: This search is definitely not optimized. Once its doing
+ * the "right thing" we'll optimize it for efficiency if
+ * necessary
+ */
+
+ /* Search for this entry in the list and update it if it is
+ * already there.
+ */
+
+ spin_lock_irqsave(&ieee->lock, flags);
+ if (is_same_network(&ieee->current_network, network,
+ (network->ssid_len ? 1 : 0))) {
+ update_network(&ieee->current_network, network);
+ if ((ieee->current_network.mode == IEEE_N_24G ||
+ ieee->current_network.mode == IEEE_G)
+ && ieee->current_network.berp_info_valid) {
+ if (ieee->current_network.erp_value & ERP_UseProtection)
+ ieee->current_network.buseprotection = true;
+ else
+ ieee->current_network.buseprotection = false;
+ }
+ if (is_beacon(beacon->header.frame_ctl)) {
+ if (ieee->state >= RTLLIB_LINKED)
+ ieee->LinkDetectInfo.NumRecvBcnInPeriod++;
+ }
+ }
+ list_for_each_entry(target, &ieee->network_list, list) {
+ if (is_same_network(target, network,
+ (target->ssid_len ? 1 : 0)))
+ break;
+ if ((oldest == NULL) ||
+ (target->last_scanned < oldest->last_scanned))
+ oldest = target;
+ }
+
+ /* If we didn't find a match, then get a new network slot to initialize
+ * with this beacon's information
+ */
+ if (&target->list == &ieee->network_list) {
+ if (list_empty(&ieee->network_free_list)) {
+ /* If there are no more slots, expire the oldest */
+ list_del(&oldest->list);
+ target = oldest;
+ RTLLIB_DEBUG_SCAN("Expired '%s' ( %pM) from network list.\n",
+ escape_essid(target->ssid,
+ target->ssid_len),
+ target->bssid);
+ } else {
+ /* Otherwise just pull from the free list */
+ target = list_entry(ieee->network_free_list.next,
+ struct rtllib_network, list);
+ list_del(ieee->network_free_list.next);
+ }
+
+
+ RTLLIB_DEBUG_SCAN("Adding '%s' ( %pM) via %s.\n",
+ escape_essid(network->ssid,
+ network->ssid_len), network->bssid,
+ WLAN_FC_GET_STYPE(
+ le16_to_cpu(beacon->header.frame_ctl)) ==
+ RTLLIB_STYPE_PROBE_RESP ?
+ "PROBE RESPONSE" : "BEACON");
+ memcpy(target, network, sizeof(*target));
+ list_add_tail(&target->list, &ieee->network_list);
+ if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
+ rtllib_softmac_new_net(ieee, network);
+ } else {
+ RTLLIB_DEBUG_SCAN("Updating '%s' ( %pM) via %s.\n",
+ escape_essid(target->ssid,
+ target->ssid_len), target->bssid,
+ WLAN_FC_GET_STYPE(
+ le16_to_cpu(beacon->header.frame_ctl)) ==
+ RTLLIB_STYPE_PROBE_RESP ?
+ "PROBE RESPONSE" : "BEACON");
+
+ /* we have an entry and we are going to update it. But this
+ * entry may be already expired. In this case we do the same
+ * as we found a new net and call the new_net handler
+ */
+ renew = !time_after(target->last_scanned + ieee->scan_age,
+ jiffies);
+ if ((!target->ssid_len) &&
+ (((network->ssid_len > 0) && (target->hidden_ssid_len == 0))
+ || ((ieee->current_network.ssid_len == network->ssid_len) &&
+ (strncmp(ieee->current_network.ssid, network->ssid,
+ network->ssid_len) == 0) &&
+ (ieee->state == RTLLIB_NOLINK))))
+ renew = 1;
+ update_network(target, network);
+ if (renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE))
+ rtllib_softmac_new_net(ieee, network);
+ }
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+ if (is_beacon(beacon->header.frame_ctl) &&
+ is_same_network(&ieee->current_network, network,
+ (network->ssid_len ? 1 : 0)) &&
+ (ieee->state == RTLLIB_LINKED)) {
+ if (ieee->handle_beacon != NULL)
+ ieee->handle_beacon(ieee->dev, beacon,
+ &ieee->current_network);
+ }
+free_network:
+ kfree(network);
+}
+
+void rtllib_rx_mgt(struct rtllib_device *ieee,
+ struct sk_buff *skb,
+ struct rtllib_rx_stats *stats)
+{
+ struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data;
+
+ if ((WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) !=
+ RTLLIB_STYPE_PROBE_RESP) &&
+ (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) !=
+ RTLLIB_STYPE_BEACON))
+ ieee->last_rx_ps_time = jiffies;
+
+ switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
+
+ case RTLLIB_STYPE_BEACON:
+ RTLLIB_DEBUG_MGMT("received BEACON (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)));
+ RTLLIB_DEBUG_SCAN("Beacon\n");
+ rtllib_process_probe_response(
+ ieee, (struct rtllib_probe_response *)header,
+ stats);
+
+ if (ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED &&
+ ieee->iw_mode == IW_MODE_INFRA &&
+ ieee->state == RTLLIB_LINKED))
+ tasklet_schedule(&ieee->ps_task);
+
+ break;
+
+ case RTLLIB_STYPE_PROBE_RESP:
+ RTLLIB_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)));
+ RTLLIB_DEBUG_SCAN("Probe response\n");
+ rtllib_process_probe_response(ieee,
+ (struct rtllib_probe_response *)header, stats);
+ break;
+ case RTLLIB_STYPE_PROBE_REQ:
+ RTLLIB_DEBUG_MGMT("received PROBE RESQUEST (%d)\n",
+ WLAN_FC_GET_STYPE(
+ le16_to_cpu(header->frame_ctl)));
+ RTLLIB_DEBUG_SCAN("Probe request\n");
+ if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
+ ((ieee->iw_mode == IW_MODE_ADHOC ||
+ ieee->iw_mode == IW_MODE_MASTER) &&
+ ieee->state == RTLLIB_LINKED))
+ rtllib_rx_probe_rq(ieee, skb);
+ break;
+ }
+}
diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
new file mode 100644
index 000000000..23b7a4c3b
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_softmac.c
@@ -0,0 +1,3758 @@
+/* IEEE 802.11 SoftMAC layer
+ * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
+ *
+ * Mostly extracted from the rtl8180-sa2400 driver for the
+ * in-kernel generic ieee802.11 stack.
+ *
+ * Few lines might be stolen from other part of the rtllib
+ * stack. Copyright who own it's copyright
+ *
+ * WPA code stolen from the ipw2200 driver.
+ * Copyright who own it's copyright.
+ *
+ * released under the GPL
+ */
+
+
+#include "rtllib.h"
+
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/etherdevice.h>
+#include "dot11d.h"
+
+short rtllib_is_54g(struct rtllib_network *net)
+{
+ return (net->rates_ex_len > 0) || (net->rates_len > 4);
+}
+
+short rtllib_is_shortslot(const struct rtllib_network *net)
+{
+ return net->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME;
+}
+
+/* returns the total length needed for placing the RATE MFIE
+ * tag and the EXTENDED RATE MFIE tag if needed.
+ * It encludes two bytes per tag for the tag itself and its len
+ */
+static unsigned int rtllib_MFIE_rate_len(struct rtllib_device *ieee)
+{
+ unsigned int rate_len = 0;
+
+ if (ieee->modulation & RTLLIB_CCK_MODULATION)
+ rate_len = RTLLIB_CCK_RATE_LEN + 2;
+
+ if (ieee->modulation & RTLLIB_OFDM_MODULATION)
+
+ rate_len += RTLLIB_OFDM_RATE_LEN + 2;
+
+ return rate_len;
+}
+
+/* place the MFIE rate, tag to the memory (double) pointed.
+ * Then it updates the pointer so that
+ * it points after the new MFIE tag added.
+ */
+static void rtllib_MFIE_Brate(struct rtllib_device *ieee, u8 **tag_p)
+{
+ u8 *tag = *tag_p;
+
+ if (ieee->modulation & RTLLIB_CCK_MODULATION) {
+ *tag++ = MFIE_TYPE_RATES;
+ *tag++ = 4;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_1MB;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_2MB;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_5MB;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_11MB;
+ }
+
+ /* We may add an option for custom rates that specific HW
+ * might support
+ */
+ *tag_p = tag;
+}
+
+static void rtllib_MFIE_Grate(struct rtllib_device *ieee, u8 **tag_p)
+{
+ u8 *tag = *tag_p;
+
+ if (ieee->modulation & RTLLIB_OFDM_MODULATION) {
+ *tag++ = MFIE_TYPE_RATES_EX;
+ *tag++ = 8;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_6MB;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_9MB;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_12MB;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_18MB;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_24MB;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_36MB;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_48MB;
+ *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_54MB;
+ }
+ /* We may add an option for custom rates that specific HW might
+ * support
+ */
+ *tag_p = tag;
+}
+
+static void rtllib_WMM_Info(struct rtllib_device *ieee, u8 **tag_p)
+{
+ u8 *tag = *tag_p;
+
+ *tag++ = MFIE_TYPE_GENERIC;
+ *tag++ = 7;
+ *tag++ = 0x00;
+ *tag++ = 0x50;
+ *tag++ = 0xf2;
+ *tag++ = 0x02;
+ *tag++ = 0x00;
+ *tag++ = 0x01;
+ *tag++ = MAX_SP_Len;
+ *tag_p = tag;
+}
+
+void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p)
+{
+ u8 *tag = *tag_p;
+
+ *tag++ = MFIE_TYPE_GENERIC;
+ *tag++ = 7;
+ *tag++ = 0x00;
+ *tag++ = 0xe0;
+ *tag++ = 0x4c;
+ *tag++ = 0x01;
+ *tag++ = 0x02;
+ *tag++ = 0x11;
+ *tag++ = 0x00;
+
+ *tag_p = tag;
+ netdev_alert(ieee->dev, "This is enable turbo mode IE process\n");
+}
+
+static void enqueue_mgmt(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+ int nh;
+
+ nh = (ieee->mgmt_queue_head + 1) % MGMT_QUEUE_NUM;
+
+/* if the queue is full but we have newer frames then
+ * just overwrites the oldest.
+ *
+ * if (nh == ieee->mgmt_queue_tail)
+ * return -1;
+ */
+ ieee->mgmt_queue_head = nh;
+ ieee->mgmt_queue_ring[nh] = skb;
+
+}
+
+static struct sk_buff *dequeue_mgmt(struct rtllib_device *ieee)
+{
+ struct sk_buff *ret;
+
+ if (ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
+ return NULL;
+
+ ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
+
+ ieee->mgmt_queue_tail =
+ (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
+
+ return ret;
+}
+
+static void init_mgmt_queue(struct rtllib_device *ieee)
+{
+ ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
+}
+
+
+u8
+MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee)
+{
+ u16 i;
+ u8 QueryRate = 0;
+ u8 BasicRate;
+
+
+ for (i = 0; i < ieee->current_network.rates_len; i++) {
+ BasicRate = ieee->current_network.rates[i]&0x7F;
+ if (!rtllib_is_cck_rate(BasicRate)) {
+ if (QueryRate == 0) {
+ QueryRate = BasicRate;
+ } else {
+ if (BasicRate < QueryRate)
+ QueryRate = BasicRate;
+ }
+ }
+ }
+
+ if (QueryRate == 0) {
+ QueryRate = 12;
+ netdev_info(ieee->dev, "No BasicRate found!!\n");
+ }
+ return QueryRate;
+}
+
+static u8 MgntQuery_MgntFrameTxRate(struct rtllib_device *ieee)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+ u8 rate;
+
+ if (pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
+ rate = 0x0c;
+ else
+ rate = ieee->basic_rate & 0x7f;
+
+ if (rate == 0) {
+ if (ieee->mode == IEEE_A ||
+ ieee->mode == IEEE_N_5G ||
+ (ieee->mode == IEEE_N_24G && !pHTInfo->bCurSuppCCK))
+ rate = 0x0c;
+ else
+ rate = 0x02;
+ }
+
+ return rate;
+}
+
+inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee)
+{
+ unsigned long flags;
+ short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
+ struct rtllib_hdr_3addr *header =
+ (struct rtllib_hdr_3addr *) skb->data;
+
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + 8);
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ /* called with 2nd param 0, no mgmt lock required */
+ rtllib_sta_wakeup(ieee, 0);
+
+ if (le16_to_cpu(header->frame_ctl) == RTLLIB_STYPE_BEACON)
+ tcb_desc->queue_index = BEACON_QUEUE;
+ else
+ tcb_desc->queue_index = MGNT_QUEUE;
+
+ if (ieee->disable_mgnt_queue)
+ tcb_desc->queue_index = HIGH_QUEUE;
+
+ tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
+ tcb_desc->RATRIndex = 7;
+ tcb_desc->bTxDisableRateFallBack = 1;
+ tcb_desc->bTxUseDriverAssingedRate = 1;
+ if (single) {
+ if (ieee->queue_stop) {
+ enqueue_mgmt(ieee, skb);
+ } else {
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
+
+ if (ieee->seq_ctrl[0] == 0xFFF)
+ ieee->seq_ctrl[0] = 0;
+ else
+ ieee->seq_ctrl[0]++;
+
+ /* avoid watchdog triggers */
+ ieee->softmac_data_hard_start_xmit(skb, ieee->dev,
+ ieee->basic_rate);
+ }
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+ } else {
+ spin_unlock_irqrestore(&ieee->lock, flags);
+ spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
+
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+
+ if (ieee->seq_ctrl[0] == 0xFFF)
+ ieee->seq_ctrl[0] = 0;
+ else
+ ieee->seq_ctrl[0]++;
+
+ /* check whether the managed packet queued greater than 5 */
+ if (!ieee->check_nic_enough_desc(ieee->dev, tcb_desc->queue_index) ||
+ (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0) ||
+ (ieee->queue_stop)) {
+ /* insert the skb packet to the management queue
+ *
+ * as for the completion function, it does not need
+ * to check it any more.
+ */
+ netdev_info(ieee->dev,
+ "%s():insert to waitqueue, queue_index:%d!\n",
+ __func__, tcb_desc->queue_index);
+ skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index],
+ skb);
+ } else {
+ ieee->softmac_hard_start_xmit(skb, ieee->dev);
+ }
+ spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
+ }
+}
+
+inline void softmac_ps_mgmt_xmit(struct sk_buff *skb,
+ struct rtllib_device *ieee)
+{
+ short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
+ struct rtllib_hdr_3addr *header =
+ (struct rtllib_hdr_3addr *) skb->data;
+ u16 fc, type, stype;
+ struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + 8);
+
+ fc = le16_to_cpu(header->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+
+
+ if (stype != RTLLIB_STYPE_PSPOLL)
+ tcb_desc->queue_index = MGNT_QUEUE;
+ else
+ tcb_desc->queue_index = HIGH_QUEUE;
+
+ if (ieee->disable_mgnt_queue)
+ tcb_desc->queue_index = HIGH_QUEUE;
+
+
+ tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
+ tcb_desc->RATRIndex = 7;
+ tcb_desc->bTxDisableRateFallBack = 1;
+ tcb_desc->bTxUseDriverAssingedRate = 1;
+ if (single) {
+ if (type != RTLLIB_FTYPE_CTL) {
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+
+ if (ieee->seq_ctrl[0] == 0xFFF)
+ ieee->seq_ctrl[0] = 0;
+ else
+ ieee->seq_ctrl[0]++;
+
+ }
+ /* avoid watchdog triggers */
+ ieee->softmac_data_hard_start_xmit(skb, ieee->dev,
+ ieee->basic_rate);
+
+ } else {
+ if (type != RTLLIB_FTYPE_CTL) {
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+
+ if (ieee->seq_ctrl[0] == 0xFFF)
+ ieee->seq_ctrl[0] = 0;
+ else
+ ieee->seq_ctrl[0]++;
+ }
+ ieee->softmac_hard_start_xmit(skb, ieee->dev);
+
+ }
+}
+
+static inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee)
+{
+ unsigned int len, rate_len;
+ u8 *tag;
+ struct sk_buff *skb;
+ struct rtllib_probe_request *req;
+
+ len = ieee->current_network.ssid_len;
+
+ rate_len = rtllib_MFIE_rate_len(ieee);
+
+ skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) +
+ 2 + len + rate_len + ieee->tx_headroom);
+
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ req = (struct rtllib_probe_request *) skb_put(skb,
+ sizeof(struct rtllib_probe_request));
+ req->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_REQ);
+ req->header.duration_id = 0;
+
+ memset(req->header.addr1, 0xff, ETH_ALEN);
+ memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+ memset(req->header.addr3, 0xff, ETH_ALEN);
+
+ tag = (u8 *) skb_put(skb, len + 2 + rate_len);
+
+ *tag++ = MFIE_TYPE_SSID;
+ *tag++ = len;
+ memcpy(tag, ieee->current_network.ssid, len);
+ tag += len;
+
+ rtllib_MFIE_Brate(ieee, &tag);
+ rtllib_MFIE_Grate(ieee, &tag);
+
+ return skb;
+}
+
+struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee);
+
+static void rtllib_send_beacon(struct rtllib_device *ieee)
+{
+ struct sk_buff *skb;
+
+ if (!ieee->ieee_up)
+ return;
+ skb = rtllib_get_beacon_(ieee);
+
+ if (skb) {
+ softmac_mgmt_xmit(skb, ieee);
+ ieee->softmac_stats.tx_beacons++;
+ }
+
+ if (ieee->beacon_txing && ieee->ieee_up)
+ mod_timer(&ieee->beacon_timer, jiffies +
+ (msecs_to_jiffies(ieee->current_network.beacon_interval - 5)));
+}
+
+
+static void rtllib_send_beacon_cb(unsigned long _ieee)
+{
+ struct rtllib_device *ieee =
+ (struct rtllib_device *) _ieee;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ieee->beacon_lock, flags);
+ rtllib_send_beacon(ieee);
+ spin_unlock_irqrestore(&ieee->beacon_lock, flags);
+}
+
+/* Enables network monitor mode, all rx packets will be received. */
+void rtllib_EnableNetMonitorMode(struct net_device *dev,
+ bool bInitState)
+{
+ struct rtllib_device *ieee = netdev_priv_rsl(dev);
+
+ netdev_info(dev, "========>Enter Monitor Mode\n");
+
+ ieee->AllowAllDestAddrHandler(dev, true, !bInitState);
+}
+
+
+/* Disables network monitor mode. Only packets destinated to
+ * us will be received.
+ */
+void rtllib_DisableNetMonitorMode(struct net_device *dev,
+ bool bInitState)
+{
+ struct rtllib_device *ieee = netdev_priv_rsl(dev);
+
+ netdev_info(dev, "========>Exit Monitor Mode\n");
+
+ ieee->AllowAllDestAddrHandler(dev, false, !bInitState);
+}
+
+
+/* Enables the specialized promiscuous mode required by Intel.
+ * In this mode, Intel intends to hear traffics from/to other STAs in the
+ * same BSS. Therefore we don't have to disable checking BSSID and we only need
+ * to allow all dest. BUT: if we enable checking BSSID then we can't recv
+ * packets from other STA.
+ */
+void rtllib_EnableIntelPromiscuousMode(struct net_device *dev,
+ bool bInitState)
+{
+ bool bFilterOutNonAssociatedBSSID = false;
+
+ struct rtllib_device *ieee = netdev_priv_rsl(dev);
+
+ netdev_info(dev, "========>Enter Intel Promiscuous Mode\n");
+
+ ieee->AllowAllDestAddrHandler(dev, true, !bInitState);
+ ieee->SetHwRegHandler(dev, HW_VAR_CECHK_BSSID,
+ (u8 *)&bFilterOutNonAssociatedBSSID);
+
+ ieee->bNetPromiscuousMode = true;
+}
+EXPORT_SYMBOL(rtllib_EnableIntelPromiscuousMode);
+
+
+/* Disables the specialized promiscuous mode required by Intel.
+ * See MgntEnableIntelPromiscuousMode for detail.
+ */
+void rtllib_DisableIntelPromiscuousMode(struct net_device *dev,
+ bool bInitState)
+{
+ bool bFilterOutNonAssociatedBSSID = true;
+
+ struct rtllib_device *ieee = netdev_priv_rsl(dev);
+
+ netdev_info(dev, "========>Exit Intel Promiscuous Mode\n");
+
+ ieee->AllowAllDestAddrHandler(dev, false, !bInitState);
+ ieee->SetHwRegHandler(dev, HW_VAR_CECHK_BSSID,
+ (u8 *)&bFilterOutNonAssociatedBSSID);
+
+ ieee->bNetPromiscuousMode = false;
+}
+EXPORT_SYMBOL(rtllib_DisableIntelPromiscuousMode);
+
+static void rtllib_send_probe(struct rtllib_device *ieee, u8 is_mesh)
+{
+ struct sk_buff *skb;
+
+ skb = rtllib_probe_req(ieee);
+ if (skb) {
+ softmac_mgmt_xmit(skb, ieee);
+ ieee->softmac_stats.tx_probe_rq++;
+ }
+}
+
+
+void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh)
+{
+ if (ieee->active_scan && (ieee->softmac_features &
+ IEEE_SOFTMAC_PROBERQ)) {
+ rtllib_send_probe(ieee, 0);
+ rtllib_send_probe(ieee, 0);
+ }
+}
+
+static void rtllib_softmac_hint11d_wq(void *data)
+{
+}
+
+void rtllib_update_active_chan_map(struct rtllib_device *ieee)
+{
+ memcpy(ieee->active_channel_map, GET_DOT11D_INFO(ieee)->channel_map,
+ MAX_CHANNEL_NUMBER+1);
+}
+
+/* this performs syncro scan blocking the caller until all channels
+ * in the allowed channel map has been checked.
+ */
+void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
+{
+ union iwreq_data wrqu;
+ short ch = 0;
+
+ rtllib_update_active_chan_map(ieee);
+
+ ieee->be_scan_inprogress = true;
+
+ down(&ieee->scan_sem);
+
+ while (1) {
+ do {
+ ch++;
+ if (ch > MAX_CHANNEL_NUMBER)
+ goto out; /* scan completed */
+ } while (!ieee->active_channel_map[ch]);
+
+ /* this function can be called in two situations
+ * 1- We have switched to ad-hoc mode and we are
+ * performing a complete syncro scan before conclude
+ * there are no interesting cell and to create a
+ * new one. In this case the link state is
+ * RTLLIB_NOLINK until we found an interesting cell.
+ * If so the ieee8021_new_net, called by the RX path
+ * will set the state to RTLLIB_LINKED, so we stop
+ * scanning
+ * 2- We are linked and the root uses run iwlist scan.
+ * So we switch to RTLLIB_LINKED_SCANNING to remember
+ * that we are still logically linked (not interested in
+ * new network events, despite for updating the net list,
+ * but we are temporarly 'unlinked' as the driver shall
+ * not filter RX frames and the channel is changing.
+ * So the only situation in which are interested is to check
+ * if the state become LINKED because of the #1 situation
+ */
+
+ if (ieee->state == RTLLIB_LINKED)
+ goto out;
+ if (ieee->sync_scan_hurryup) {
+ netdev_info(ieee->dev,
+ "============>sync_scan_hurryup out\n");
+ goto out;
+ }
+
+ ieee->set_chan(ieee->dev, ch);
+ if (ieee->active_channel_map[ch] == 1)
+ rtllib_send_probe_requests(ieee, 0);
+
+ /* this prevent excessive time wait when we
+ * need to wait for a syncro scan to end..
+ */
+ msleep_interruptible_rsl(RTLLIB_SOFTMAC_SCAN_TIME);
+ }
+out:
+ ieee->actscanning = false;
+ ieee->sync_scan_hurryup = 0;
+
+ if (ieee->state >= RTLLIB_LINKED) {
+ if (IS_DOT11D_ENABLE(ieee))
+ DOT11D_ScanComplete(ieee);
+ }
+ up(&ieee->scan_sem);
+
+ ieee->be_scan_inprogress = false;
+
+ memset(&wrqu, 0, sizeof(wrqu));
+ wireless_send_event(ieee->dev, SIOCGIWSCAN, &wrqu, NULL);
+}
+
+static void rtllib_softmac_scan_wq(void *data)
+{
+ struct rtllib_device *ieee = container_of_dwork_rsl(data,
+ struct rtllib_device, softmac_scan_wq);
+ u8 last_channel = ieee->current_network.channel;
+
+ rtllib_update_active_chan_map(ieee);
+
+ if (!ieee->ieee_up)
+ return;
+ if (rtllib_act_scanning(ieee, true))
+ return;
+
+ down(&ieee->scan_sem);
+
+ if (ieee->eRFPowerState == eRfOff) {
+ netdev_info(ieee->dev,
+ "======>%s():rf state is eRfOff, return\n",
+ __func__);
+ goto out1;
+ }
+
+ do {
+ ieee->current_network.channel =
+ (ieee->current_network.channel + 1) %
+ MAX_CHANNEL_NUMBER;
+ if (ieee->scan_watch_dog++ > MAX_CHANNEL_NUMBER) {
+ if (!ieee->active_channel_map[ieee->current_network.channel])
+ ieee->current_network.channel = 6;
+ goto out; /* no good chans */
+ }
+ } while (!ieee->active_channel_map[ieee->current_network.channel]);
+
+ if (ieee->scanning_continue == 0)
+ goto out;
+
+ ieee->set_chan(ieee->dev, ieee->current_network.channel);
+
+ if (ieee->active_channel_map[ieee->current_network.channel] == 1)
+ rtllib_send_probe_requests(ieee, 0);
+
+ queue_delayed_work_rsl(ieee->wq, &ieee->softmac_scan_wq,
+ msecs_to_jiffies(RTLLIB_SOFTMAC_SCAN_TIME));
+
+ up(&ieee->scan_sem);
+ return;
+
+out:
+ if (IS_DOT11D_ENABLE(ieee))
+ DOT11D_ScanComplete(ieee);
+ ieee->current_network.channel = last_channel;
+
+out1:
+ ieee->actscanning = false;
+ ieee->scan_watch_dog = 0;
+ ieee->scanning_continue = 0;
+ up(&ieee->scan_sem);
+}
+
+
+
+static void rtllib_beacons_start(struct rtllib_device *ieee)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ieee->beacon_lock, flags);
+
+ ieee->beacon_txing = 1;
+ rtllib_send_beacon(ieee);
+
+ spin_unlock_irqrestore(&ieee->beacon_lock, flags);
+}
+
+static void rtllib_beacons_stop(struct rtllib_device *ieee)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ieee->beacon_lock, flags);
+
+ ieee->beacon_txing = 0;
+ del_timer_sync(&ieee->beacon_timer);
+
+ spin_unlock_irqrestore(&ieee->beacon_lock, flags);
+
+}
+
+
+void rtllib_stop_send_beacons(struct rtllib_device *ieee)
+{
+ if (ieee->stop_send_beacons)
+ ieee->stop_send_beacons(ieee->dev);
+ if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
+ rtllib_beacons_stop(ieee);
+}
+EXPORT_SYMBOL(rtllib_stop_send_beacons);
+
+
+void rtllib_start_send_beacons(struct rtllib_device *ieee)
+{
+ if (ieee->start_send_beacons)
+ ieee->start_send_beacons(ieee->dev);
+ if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
+ rtllib_beacons_start(ieee);
+}
+EXPORT_SYMBOL(rtllib_start_send_beacons);
+
+
+static void rtllib_softmac_stop_scan(struct rtllib_device *ieee)
+{
+ down(&ieee->scan_sem);
+ ieee->scan_watch_dog = 0;
+ if (ieee->scanning_continue == 1) {
+ ieee->scanning_continue = 0;
+ ieee->actscanning = false;
+
+ cancel_delayed_work(&ieee->softmac_scan_wq);
+ }
+
+ up(&ieee->scan_sem);
+}
+
+void rtllib_stop_scan(struct rtllib_device *ieee)
+{
+ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
+ rtllib_softmac_stop_scan(ieee);
+ } else {
+ if (ieee->rtllib_stop_hw_scan)
+ ieee->rtllib_stop_hw_scan(ieee->dev);
+ }
+}
+EXPORT_SYMBOL(rtllib_stop_scan);
+
+void rtllib_stop_scan_syncro(struct rtllib_device *ieee)
+{
+ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
+ ieee->sync_scan_hurryup = 1;
+ } else {
+ if (ieee->rtllib_stop_hw_scan)
+ ieee->rtllib_stop_hw_scan(ieee->dev);
+ }
+}
+EXPORT_SYMBOL(rtllib_stop_scan_syncro);
+
+bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan)
+{
+ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
+ if (sync_scan)
+ return ieee->be_scan_inprogress;
+ else
+ return ieee->actscanning || ieee->be_scan_inprogress;
+ } else {
+ return test_bit(STATUS_SCANNING, &ieee->status);
+ }
+}
+EXPORT_SYMBOL(rtllib_act_scanning);
+
+/* called with ieee->lock held */
+static void rtllib_start_scan(struct rtllib_device *ieee)
+{
+ RT_TRACE(COMP_DBG, "===>%s()\n", __func__);
+ if (ieee->rtllib_ips_leave_wq != NULL)
+ ieee->rtllib_ips_leave_wq(ieee->dev);
+
+ if (IS_DOT11D_ENABLE(ieee)) {
+ if (IS_COUNTRY_IE_VALID(ieee))
+ RESET_CIE_WATCHDOG(ieee);
+ }
+ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
+ if (ieee->scanning_continue == 0) {
+ ieee->actscanning = true;
+ ieee->scanning_continue = 1;
+ queue_delayed_work_rsl(ieee->wq,
+ &ieee->softmac_scan_wq, 0);
+ }
+ } else {
+ if (ieee->rtllib_start_hw_scan)
+ ieee->rtllib_start_hw_scan(ieee->dev);
+ }
+}
+
+/* called with wx_sem held */
+void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
+{
+ if (IS_DOT11D_ENABLE(ieee)) {
+ if (IS_COUNTRY_IE_VALID(ieee))
+ RESET_CIE_WATCHDOG(ieee);
+ }
+ ieee->sync_scan_hurryup = 0;
+ if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) {
+ rtllib_softmac_scan_syncro(ieee, is_mesh);
+ } else {
+ if (ieee->rtllib_start_hw_scan)
+ ieee->rtllib_start_hw_scan(ieee->dev);
+ }
+}
+EXPORT_SYMBOL(rtllib_start_scan_syncro);
+
+inline struct sk_buff *rtllib_authentication_req(struct rtllib_network *beacon,
+ struct rtllib_device *ieee, int challengelen, u8 *daddr)
+{
+ struct sk_buff *skb;
+ struct rtllib_authentication *auth;
+ int len = 0;
+
+ len = sizeof(struct rtllib_authentication) + challengelen +
+ ieee->tx_headroom + 4;
+ skb = dev_alloc_skb(len);
+
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ auth = (struct rtllib_authentication *)
+ skb_put(skb, sizeof(struct rtllib_authentication));
+
+ auth->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_AUTH);
+ if (challengelen)
+ auth->header.frame_ctl |= cpu_to_le16(RTLLIB_FCTL_WEP);
+
+ auth->header.duration_id = cpu_to_le16(0x013a);
+ memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
+ memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+ memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
+ if (ieee->auth_mode == 0)
+ auth->algorithm = WLAN_AUTH_OPEN;
+ else if (ieee->auth_mode == 1)
+ auth->algorithm = cpu_to_le16(WLAN_AUTH_SHARED_KEY);
+ else if (ieee->auth_mode == 2)
+ auth->algorithm = WLAN_AUTH_OPEN;
+ auth->transaction = cpu_to_le16(ieee->associate_seq);
+ ieee->associate_seq++;
+
+ auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
+
+ return skb;
+}
+
+static struct sk_buff *rtllib_probe_resp(struct rtllib_device *ieee, u8 *dest)
+{
+ u8 *tag;
+ int beacon_size;
+ struct rtllib_probe_response *beacon_buf;
+ struct sk_buff *skb = NULL;
+ int encrypt;
+ int atim_len, erp_len;
+ struct lib80211_crypt_data *crypt;
+
+ char *ssid = ieee->current_network.ssid;
+ int ssid_len = ieee->current_network.ssid_len;
+ int rate_len = ieee->current_network.rates_len+2;
+ int rate_ex_len = ieee->current_network.rates_ex_len;
+ int wpa_ie_len = ieee->wpa_ie_len;
+ u8 erpinfo_content = 0;
+
+ u8 *tmp_ht_cap_buf = NULL;
+ u8 tmp_ht_cap_len = 0;
+ u8 *tmp_ht_info_buf = NULL;
+ u8 tmp_ht_info_len = 0;
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+ u8 *tmp_generic_ie_buf = NULL;
+ u8 tmp_generic_ie_len = 0;
+
+ if (rate_ex_len > 0)
+ rate_ex_len += 2;
+
+ if (ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
+ atim_len = 4;
+ else
+ atim_len = 0;
+
+ if ((ieee->current_network.mode == IEEE_G) ||
+ (ieee->current_network.mode == IEEE_N_24G &&
+ ieee->pHTInfo->bCurSuppCCK)) {
+ erp_len = 3;
+ erpinfo_content = 0;
+ if (ieee->current_network.buseprotection)
+ erpinfo_content |= ERP_UseProtection;
+ } else
+ erp_len = 0;
+
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
+ encrypt = ieee->host_encrypt && crypt && crypt->ops &&
+ ((0 == strcmp(crypt->ops->name, "R-WEP") || wpa_ie_len));
+ if (ieee->pHTInfo->bCurrentHTSupport) {
+ tmp_ht_cap_buf = (u8 *) &(ieee->pHTInfo->SelfHTCap);
+ tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
+ tmp_ht_info_buf = (u8 *) &(ieee->pHTInfo->SelfHTInfo);
+ tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
+ HTConstructCapabilityElement(ieee, tmp_ht_cap_buf,
+ &tmp_ht_cap_len, encrypt, false);
+ HTConstructInfoElement(ieee, tmp_ht_info_buf, &tmp_ht_info_len,
+ encrypt);
+
+ if (pHTInfo->bRegRT2RTAggregation) {
+ tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
+ tmp_generic_ie_len =
+ sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
+ HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf,
+ &tmp_generic_ie_len);
+ }
+ }
+
+ beacon_size = sizeof(struct rtllib_probe_response)+2+
+ ssid_len + 3 + rate_len + rate_ex_len + atim_len + erp_len
+ + wpa_ie_len + ieee->tx_headroom;
+ skb = dev_alloc_skb(beacon_size);
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ beacon_buf = (struct rtllib_probe_response *) skb_put(skb,
+ (beacon_size - ieee->tx_headroom));
+ memcpy(beacon_buf->header.addr1, dest, ETH_ALEN);
+ memcpy(beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+ memcpy(beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
+
+ beacon_buf->header.duration_id = 0;
+ beacon_buf->beacon_interval =
+ cpu_to_le16(ieee->current_network.beacon_interval);
+ beacon_buf->capability =
+ cpu_to_le16(ieee->current_network.capability &
+ WLAN_CAPABILITY_IBSS);
+ beacon_buf->capability |=
+ cpu_to_le16(ieee->current_network.capability &
+ WLAN_CAPABILITY_SHORT_PREAMBLE);
+
+ if (ieee->short_slot && (ieee->current_network.capability &
+ WLAN_CAPABILITY_SHORT_SLOT_TIME))
+ beacon_buf->capability |=
+ cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
+
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
+ if (encrypt)
+ beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
+
+
+ beacon_buf->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_RESP);
+ beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
+ beacon_buf->info_element[0].len = ssid_len;
+
+ tag = (u8 *) beacon_buf->info_element[0].data;
+
+ memcpy(tag, ssid, ssid_len);
+
+ tag += ssid_len;
+
+ *(tag++) = MFIE_TYPE_RATES;
+ *(tag++) = rate_len-2;
+ memcpy(tag, ieee->current_network.rates, rate_len-2);
+ tag += rate_len-2;
+
+ *(tag++) = MFIE_TYPE_DS_SET;
+ *(tag++) = 1;
+ *(tag++) = ieee->current_network.channel;
+
+ if (atim_len) {
+ u16 val16;
+ *(tag++) = MFIE_TYPE_IBSS_SET;
+ *(tag++) = 2;
+ val16 = ieee->current_network.atim_window;
+ memcpy((u8 *)tag, (u8 *)&val16, 2);
+ tag += 2;
+ }
+
+ if (erp_len) {
+ *(tag++) = MFIE_TYPE_ERP;
+ *(tag++) = 1;
+ *(tag++) = erpinfo_content;
+ }
+ if (rate_ex_len) {
+ *(tag++) = MFIE_TYPE_RATES_EX;
+ *(tag++) = rate_ex_len-2;
+ memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2);
+ tag += rate_ex_len-2;
+ }
+
+ if (wpa_ie_len) {
+ if (ieee->iw_mode == IW_MODE_ADHOC)
+ memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
+ memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
+ tag += ieee->wpa_ie_len;
+ }
+ return skb;
+}
+
+static struct sk_buff *rtllib_assoc_resp(struct rtllib_device *ieee, u8 *dest)
+{
+ struct sk_buff *skb;
+ u8 *tag;
+
+ struct lib80211_crypt_data *crypt;
+ struct rtllib_assoc_response_frame *assoc;
+ short encrypt;
+
+ unsigned int rate_len = rtllib_MFIE_rate_len(ieee);
+ int len = sizeof(struct rtllib_assoc_response_frame) + rate_len +
+ ieee->tx_headroom;
+
+ skb = dev_alloc_skb(len);
+
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ assoc = (struct rtllib_assoc_response_frame *)
+ skb_put(skb, sizeof(struct rtllib_assoc_response_frame));
+
+ assoc->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_ASSOC_RESP);
+ memcpy(assoc->header.addr1, dest, ETH_ALEN);
+ memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
+ memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+ assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
+ WLAN_CAPABILITY_ESS : WLAN_CAPABILITY_IBSS);
+
+
+ if (ieee->short_slot)
+ assoc->capability |=
+ cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
+
+ if (ieee->host_encrypt)
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
+ else
+ crypt = NULL;
+
+ encrypt = (crypt && crypt->ops);
+
+ if (encrypt)
+ assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
+
+ assoc->status = 0;
+ assoc->aid = cpu_to_le16(ieee->assoc_id);
+ if (ieee->assoc_id == 0x2007)
+ ieee->assoc_id = 0;
+ else
+ ieee->assoc_id++;
+
+ tag = (u8 *) skb_put(skb, rate_len);
+ rtllib_MFIE_Brate(ieee, &tag);
+ rtllib_MFIE_Grate(ieee, &tag);
+
+ return skb;
+}
+
+static struct sk_buff *rtllib_auth_resp(struct rtllib_device *ieee, int status,
+ u8 *dest)
+{
+ struct sk_buff *skb = NULL;
+ struct rtllib_authentication *auth;
+ int len = ieee->tx_headroom + sizeof(struct rtllib_authentication) + 1;
+
+ skb = dev_alloc_skb(len);
+ if (!skb)
+ return NULL;
+
+ skb->len = sizeof(struct rtllib_authentication);
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ auth = (struct rtllib_authentication *)
+ skb_put(skb, sizeof(struct rtllib_authentication));
+
+ auth->status = cpu_to_le16(status);
+ auth->transaction = cpu_to_le16(2);
+ auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
+
+ memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
+ memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+ memcpy(auth->header.addr1, dest, ETH_ALEN);
+ auth->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_AUTH);
+ return skb;
+
+
+}
+
+static struct sk_buff *rtllib_null_func(struct rtllib_device *ieee, short pwr)
+{
+ struct sk_buff *skb;
+ struct rtllib_hdr_3addr *hdr;
+
+ skb = dev_alloc_skb(sizeof(struct rtllib_hdr_3addr)+ieee->tx_headroom);
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ hdr = (struct rtllib_hdr_3addr *)skb_put(skb,
+ sizeof(struct rtllib_hdr_3addr));
+
+ memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
+ memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
+ memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
+
+ hdr->frame_ctl = cpu_to_le16(RTLLIB_FTYPE_DATA |
+ RTLLIB_STYPE_NULLFUNC | RTLLIB_FCTL_TODS |
+ (pwr ? RTLLIB_FCTL_PM : 0));
+
+ return skb;
+
+
+}
+
+static struct sk_buff *rtllib_pspoll_func(struct rtllib_device *ieee)
+{
+ struct sk_buff *skb;
+ struct rtllib_pspoll_hdr *hdr;
+
+ skb = dev_alloc_skb(sizeof(struct rtllib_pspoll_hdr)+ieee->tx_headroom);
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ hdr = (struct rtllib_pspoll_hdr *)skb_put(skb,
+ sizeof(struct rtllib_pspoll_hdr));
+
+ memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN);
+ memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN);
+
+ hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000);
+ hdr->frame_ctl = cpu_to_le16(RTLLIB_FTYPE_CTL | RTLLIB_STYPE_PSPOLL |
+ RTLLIB_FCTL_PM);
+
+ return skb;
+
+}
+
+static void rtllib_resp_to_assoc_rq(struct rtllib_device *ieee, u8 *dest)
+{
+ struct sk_buff *buf = rtllib_assoc_resp(ieee, dest);
+
+ if (buf)
+ softmac_mgmt_xmit(buf, ieee);
+}
+
+
+static void rtllib_resp_to_auth(struct rtllib_device *ieee, int s, u8 *dest)
+{
+ struct sk_buff *buf = rtllib_auth_resp(ieee, s, dest);
+
+ if (buf)
+ softmac_mgmt_xmit(buf, ieee);
+}
+
+
+static void rtllib_resp_to_probe(struct rtllib_device *ieee, u8 *dest)
+{
+ struct sk_buff *buf = rtllib_probe_resp(ieee, dest);
+
+ if (buf)
+ softmac_mgmt_xmit(buf, ieee);
+}
+
+
+inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid)
+{
+ int i = 0;
+
+ do {
+ if ((ieee->PMKIDList[i].bUsed) &&
+ (memcmp(ieee->PMKIDList[i].Bssid, bssid, ETH_ALEN) == 0))
+ break;
+ i++;
+ } while (i < NUM_PMKID_CACHE);
+
+ if (i == NUM_PMKID_CACHE)
+ i = -1;
+ return i;
+}
+
+inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon,
+ struct rtllib_device *ieee)
+{
+ struct sk_buff *skb;
+ struct rtllib_assoc_request_frame *hdr;
+ u8 *tag, *ies;
+ int i;
+ u8 *ht_cap_buf = NULL;
+ u8 ht_cap_len = 0;
+ u8 *realtek_ie_buf = NULL;
+ u8 realtek_ie_len = 0;
+ int wpa_ie_len = ieee->wpa_ie_len;
+ int wps_ie_len = ieee->wps_ie_len;
+ unsigned int ckip_ie_len = 0;
+ unsigned int ccxrm_ie_len = 0;
+ unsigned int cxvernum_ie_len = 0;
+ struct lib80211_crypt_data *crypt;
+ int encrypt;
+ int PMKCacheIdx;
+
+ unsigned int rate_len = (beacon->rates_len ?
+ (beacon->rates_len + 2) : 0) +
+ (beacon->rates_ex_len ? (beacon->rates_ex_len) +
+ 2 : 0);
+
+ unsigned int wmm_info_len = beacon->qos_data.supported ? 9 : 0;
+ unsigned int turbo_info_len = beacon->Turbo_Enable ? 9 : 0;
+
+ int len = 0;
+
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
+ if (crypt != NULL)
+ encrypt = ieee->host_encrypt && crypt && crypt->ops &&
+ ((0 == strcmp(crypt->ops->name, "R-WEP") ||
+ wpa_ie_len));
+ else
+ encrypt = 0;
+
+ if ((ieee->rtllib_ap_sec_type &&
+ (ieee->rtllib_ap_sec_type(ieee) & SEC_ALG_TKIP)) ||
+ ieee->bForcedBgMode) {
+ ieee->pHTInfo->bEnableHT = 0;
+ ieee->mode = WIRELESS_MODE_G;
+ }
+
+ if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
+ ht_cap_buf = (u8 *)&(ieee->pHTInfo->SelfHTCap);
+ ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
+ HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len,
+ encrypt, true);
+ if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
+ realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
+ realtek_ie_len =
+ sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
+ HTConstructRT2RTAggElement(ieee, realtek_ie_buf,
+ &realtek_ie_len);
+ }
+ }
+
+ if (beacon->bCkipSupported)
+ ckip_ie_len = 30+2;
+ if (beacon->bCcxRmEnable)
+ ccxrm_ie_len = 6+2;
+ if (beacon->BssCcxVerNumber >= 2)
+ cxvernum_ie_len = 5+2;
+
+ PMKCacheIdx = SecIsInPMKIDList(ieee, ieee->current_network.bssid);
+ if (PMKCacheIdx >= 0) {
+ wpa_ie_len += 18;
+ netdev_info(ieee->dev, "[PMK cache]: WPA2 IE length: %x\n",
+ wpa_ie_len);
+ }
+ len = sizeof(struct rtllib_assoc_request_frame) + 2
+ + beacon->ssid_len
+ + rate_len
+ + wpa_ie_len
+ + wps_ie_len
+ + wmm_info_len
+ + turbo_info_len
+ + ht_cap_len
+ + realtek_ie_len
+ + ckip_ie_len
+ + ccxrm_ie_len
+ + cxvernum_ie_len
+ + ieee->tx_headroom;
+
+ skb = dev_alloc_skb(len);
+
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ hdr = (struct rtllib_assoc_request_frame *)
+ skb_put(skb, sizeof(struct rtllib_assoc_request_frame) + 2);
+
+
+ hdr->header.frame_ctl = RTLLIB_STYPE_ASSOC_REQ;
+ hdr->header.duration_id = cpu_to_le16(37);
+ memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
+ memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+ memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
+
+ memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);
+
+ hdr->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+ if (beacon->capability & WLAN_CAPABILITY_PRIVACY)
+ hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
+
+ if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+ hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
+
+ if (ieee->short_slot &&
+ (beacon->capability&WLAN_CAPABILITY_SHORT_SLOT_TIME))
+ hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
+
+
+ hdr->listen_interval = cpu_to_le16(beacon->listen_interval);
+
+ hdr->info_element[0].id = MFIE_TYPE_SSID;
+
+ hdr->info_element[0].len = beacon->ssid_len;
+ tag = skb_put(skb, beacon->ssid_len);
+ memcpy(tag, beacon->ssid, beacon->ssid_len);
+
+ tag = skb_put(skb, rate_len);
+
+ if (beacon->rates_len) {
+ *tag++ = MFIE_TYPE_RATES;
+ *tag++ = beacon->rates_len;
+ for (i = 0; i < beacon->rates_len; i++)
+ *tag++ = beacon->rates[i];
+ }
+
+ if (beacon->rates_ex_len) {
+ *tag++ = MFIE_TYPE_RATES_EX;
+ *tag++ = beacon->rates_ex_len;
+ for (i = 0; i < beacon->rates_ex_len; i++)
+ *tag++ = beacon->rates_ex[i];
+ }
+
+ if (beacon->bCkipSupported) {
+ static const u8 AironetIeOui[] = {0x00, 0x01, 0x66};
+ u8 CcxAironetBuf[30];
+ struct octet_string osCcxAironetIE;
+
+ memset(CcxAironetBuf, 0, 30);
+ osCcxAironetIE.Octet = CcxAironetBuf;
+ osCcxAironetIE.Length = sizeof(CcxAironetBuf);
+ memcpy(osCcxAironetIE.Octet, AironetIeOui,
+ sizeof(AironetIeOui));
+
+ osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |=
+ (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC);
+ tag = skb_put(skb, ckip_ie_len);
+ *tag++ = MFIE_TYPE_AIRONET;
+ *tag++ = osCcxAironetIE.Length;
+ memcpy(tag, osCcxAironetIE.Octet, osCcxAironetIE.Length);
+ tag += osCcxAironetIE.Length;
+ }
+
+ if (beacon->bCcxRmEnable) {
+ static const u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01,
+ 0x00};
+ struct octet_string osCcxRmCap;
+
+ osCcxRmCap.Octet = (u8 *) CcxRmCapBuf;
+ osCcxRmCap.Length = sizeof(CcxRmCapBuf);
+ tag = skb_put(skb, ccxrm_ie_len);
+ *tag++ = MFIE_TYPE_GENERIC;
+ *tag++ = osCcxRmCap.Length;
+ memcpy(tag, osCcxRmCap.Octet, osCcxRmCap.Length);
+ tag += osCcxRmCap.Length;
+ }
+
+ if (beacon->BssCcxVerNumber >= 2) {
+ u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
+ struct octet_string osCcxVerNum;
+
+ CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
+ osCcxVerNum.Octet = CcxVerNumBuf;
+ osCcxVerNum.Length = sizeof(CcxVerNumBuf);
+ tag = skb_put(skb, cxvernum_ie_len);
+ *tag++ = MFIE_TYPE_GENERIC;
+ *tag++ = osCcxVerNum.Length;
+ memcpy(tag, osCcxVerNum.Octet, osCcxVerNum.Length);
+ tag += osCcxVerNum.Length;
+ }
+ if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
+ if (ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC) {
+ tag = skb_put(skb, ht_cap_len);
+ *tag++ = MFIE_TYPE_HT_CAP;
+ *tag++ = ht_cap_len - 2;
+ memcpy(tag, ht_cap_buf, ht_cap_len - 2);
+ tag += ht_cap_len - 2;
+ }
+ }
+
+ if (wpa_ie_len) {
+ tag = skb_put(skb, ieee->wpa_ie_len);
+ memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
+
+ if (PMKCacheIdx >= 0) {
+ tag = skb_put(skb, 18);
+ *tag = 1;
+ *(tag + 1) = 0;
+ memcpy((tag + 2), &ieee->PMKIDList[PMKCacheIdx].PMKID,
+ 16);
+ }
+ }
+ if (wmm_info_len) {
+ tag = skb_put(skb, wmm_info_len);
+ rtllib_WMM_Info(ieee, &tag);
+ }
+
+ if (wps_ie_len && ieee->wps_ie) {
+ tag = skb_put(skb, wps_ie_len);
+ memcpy(tag, ieee->wps_ie, wps_ie_len);
+ }
+
+ tag = skb_put(skb, turbo_info_len);
+ if (turbo_info_len)
+ rtllib_TURBO_Info(ieee, &tag);
+
+ if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
+ if (ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC) {
+ tag = skb_put(skb, ht_cap_len);
+ *tag++ = MFIE_TYPE_GENERIC;
+ *tag++ = ht_cap_len - 2;
+ memcpy(tag, ht_cap_buf, ht_cap_len - 2);
+ tag += ht_cap_len - 2;
+ }
+
+ if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
+ tag = skb_put(skb, realtek_ie_len);
+ *tag++ = MFIE_TYPE_GENERIC;
+ *tag++ = realtek_ie_len - 2;
+ memcpy(tag, realtek_ie_buf, realtek_ie_len - 2);
+ }
+ }
+
+ kfree(ieee->assocreq_ies);
+ ieee->assocreq_ies = NULL;
+ ies = &(hdr->info_element[0].id);
+ ieee->assocreq_ies_len = (skb->data + skb->len) - ies;
+ ieee->assocreq_ies = kmalloc(ieee->assocreq_ies_len, GFP_ATOMIC);
+ if (ieee->assocreq_ies)
+ memcpy(ieee->assocreq_ies, ies, ieee->assocreq_ies_len);
+ else {
+ netdev_info(ieee->dev,
+ "%s()Warning: can't alloc memory for assocreq_ies\n",
+ __func__);
+ ieee->assocreq_ies_len = 0;
+ }
+ return skb;
+}
+
+void rtllib_associate_abort(struct rtllib_device *ieee)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ ieee->associate_seq++;
+
+ /* don't scan, and avoid to have the RX path possibily
+ * try again to associate. Even do not react to AUTH or
+ * ASSOC response. Just wait for the retry wq to be scheduled.
+ * Here we will check if there are good nets to associate
+ * with, so we retry or just get back to NO_LINK and scanning
+ */
+ if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING) {
+ RTLLIB_DEBUG_MGMT("Authentication failed\n");
+ ieee->softmac_stats.no_auth_rs++;
+ } else {
+ RTLLIB_DEBUG_MGMT("Association failed\n");
+ ieee->softmac_stats.no_ass_rs++;
+ }
+
+ ieee->state = RTLLIB_ASSOCIATING_RETRY;
+
+ queue_delayed_work_rsl(ieee->wq, &ieee->associate_retry_wq,
+ RTLLIB_SOFTMAC_ASSOC_RETRY_TIME);
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+static void rtllib_associate_abort_cb(unsigned long dev)
+{
+ rtllib_associate_abort((struct rtllib_device *) dev);
+}
+
+static void rtllib_associate_step1(struct rtllib_device *ieee, u8 *daddr)
+{
+ struct rtllib_network *beacon = &ieee->current_network;
+ struct sk_buff *skb;
+
+ RTLLIB_DEBUG_MGMT("Stopping scan\n");
+
+ ieee->softmac_stats.tx_auth_rq++;
+
+ skb = rtllib_authentication_req(beacon, ieee, 0, daddr);
+
+ if (!skb)
+ rtllib_associate_abort(ieee);
+ else {
+ ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATING;
+ RTLLIB_DEBUG_MGMT("Sending authentication request\n");
+ softmac_mgmt_xmit(skb, ieee);
+ if (!timer_pending(&ieee->associate_timer)) {
+ ieee->associate_timer.expires = jiffies + (HZ / 2);
+ add_timer(&ieee->associate_timer);
+ }
+ }
+}
+
+static void rtllib_auth_challenge(struct rtllib_device *ieee, u8 *challenge, int chlen)
+{
+ u8 *c;
+ struct sk_buff *skb;
+ struct rtllib_network *beacon = &ieee->current_network;
+
+ ieee->associate_seq++;
+ ieee->softmac_stats.tx_auth_rq++;
+
+ skb = rtllib_authentication_req(beacon, ieee, chlen + 2, beacon->bssid);
+
+ if (!skb)
+ rtllib_associate_abort(ieee);
+ else {
+ c = skb_put(skb, chlen+2);
+ *(c++) = MFIE_TYPE_CHALLENGE;
+ *(c++) = chlen;
+ memcpy(c, challenge, chlen);
+
+ RTLLIB_DEBUG_MGMT("Sending authentication challenge response\n");
+
+ rtllib_encrypt_fragment(ieee, skb,
+ sizeof(struct rtllib_hdr_3addr));
+
+ softmac_mgmt_xmit(skb, ieee);
+ mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
+ }
+ kfree(challenge);
+}
+
+static void rtllib_associate_step2(struct rtllib_device *ieee)
+{
+ struct sk_buff *skb;
+ struct rtllib_network *beacon = &ieee->current_network;
+
+ del_timer_sync(&ieee->associate_timer);
+
+ RTLLIB_DEBUG_MGMT("Sending association request\n");
+
+ ieee->softmac_stats.tx_ass_rq++;
+ skb = rtllib_association_req(beacon, ieee);
+ if (!skb)
+ rtllib_associate_abort(ieee);
+ else {
+ softmac_mgmt_xmit(skb, ieee);
+ mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
+ }
+}
+
+#define CANCELLED 2
+static void rtllib_associate_complete_wq(void *data)
+{
+ struct rtllib_device *ieee = (struct rtllib_device *)
+ container_of_work_rsl(data,
+ struct rtllib_device,
+ associate_complete_wq);
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ (&(ieee->PowerSaveControl));
+ netdev_info(ieee->dev, "Associated successfully\n");
+ if (!ieee->is_silent_reset) {
+ netdev_info(ieee->dev, "normal associate\n");
+ notify_wx_assoc_event(ieee);
+ }
+
+ netif_carrier_on(ieee->dev);
+ ieee->is_roaming = false;
+ if (rtllib_is_54g(&ieee->current_network) &&
+ (ieee->modulation & RTLLIB_OFDM_MODULATION)) {
+ ieee->rate = 108;
+ netdev_info(ieee->dev, "Using G rates:%d\n", ieee->rate);
+ } else {
+ ieee->rate = 22;
+ ieee->SetWirelessMode(ieee->dev, IEEE_B);
+ netdev_info(ieee->dev, "Using B rates:%d\n", ieee->rate);
+ }
+ if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
+ netdev_info(ieee->dev, "Successfully associated, ht enabled\n");
+ HTOnAssocRsp(ieee);
+ } else {
+ netdev_info(ieee->dev,
+ "Successfully associated, ht not enabled(%d, %d)\n",
+ ieee->pHTInfo->bCurrentHTSupport,
+ ieee->pHTInfo->bEnableHT);
+ memset(ieee->dot11HTOperationalRateSet, 0, 16);
+ }
+ ieee->LinkDetectInfo.SlotNum = 2 * (1 +
+ ieee->current_network.beacon_interval /
+ 500);
+ if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 ||
+ ieee->LinkDetectInfo.NumRecvDataInPeriod == 0) {
+ ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
+ ieee->LinkDetectInfo.NumRecvDataInPeriod = 1;
+ }
+ pPSC->LpsIdleCount = 0;
+ ieee->link_change(ieee->dev);
+
+ if (ieee->is_silent_reset) {
+ netdev_info(ieee->dev, "silent reset associate\n");
+ ieee->is_silent_reset = false;
+ }
+
+ if (ieee->data_hard_resume)
+ ieee->data_hard_resume(ieee->dev);
+
+}
+
+static void rtllib_sta_send_associnfo(struct rtllib_device *ieee)
+{
+}
+
+static void rtllib_associate_complete(struct rtllib_device *ieee)
+{
+ del_timer_sync(&ieee->associate_timer);
+
+ ieee->state = RTLLIB_LINKED;
+ rtllib_sta_send_associnfo(ieee);
+
+ queue_work_rsl(ieee->wq, &ieee->associate_complete_wq);
+}
+
+static void rtllib_associate_procedure_wq(void *data)
+{
+ struct rtllib_device *ieee = container_of_dwork_rsl(data,
+ struct rtllib_device,
+ associate_procedure_wq);
+ rtllib_stop_scan_syncro(ieee);
+ if (ieee->rtllib_ips_leave != NULL)
+ ieee->rtllib_ips_leave(ieee->dev);
+ down(&ieee->wx_sem);
+
+ if (ieee->data_hard_stop)
+ ieee->data_hard_stop(ieee->dev);
+
+ rtllib_stop_scan(ieee);
+ RT_TRACE(COMP_DBG, "===>%s(), chan:%d\n", __func__,
+ ieee->current_network.channel);
+ HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+ if (ieee->eRFPowerState == eRfOff) {
+ RT_TRACE(COMP_DBG,
+ "=============>%s():Rf state is eRfOff, schedule ipsleave wq again,return\n",
+ __func__);
+ if (ieee->rtllib_ips_leave_wq != NULL)
+ ieee->rtllib_ips_leave_wq(ieee->dev);
+ up(&ieee->wx_sem);
+ return;
+ }
+ ieee->associate_seq = 1;
+
+ rtllib_associate_step1(ieee, ieee->current_network.bssid);
+
+ up(&ieee->wx_sem);
+}
+
+inline void rtllib_softmac_new_net(struct rtllib_device *ieee,
+ struct rtllib_network *net)
+{
+ u8 tmp_ssid[IW_ESSID_MAX_SIZE + 1];
+ int tmp_ssid_len = 0;
+
+ short apset, ssidset, ssidbroad, apmatch, ssidmatch;
+
+ /* we are interested in new new only if we are not associated
+ * and we are not associating / authenticating
+ */
+ if (ieee->state != RTLLIB_NOLINK)
+ return;
+
+ if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability &
+ WLAN_CAPABILITY_ESS))
+ return;
+
+ if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability &
+ WLAN_CAPABILITY_IBSS))
+ return;
+
+ if ((ieee->iw_mode == IW_MODE_ADHOC) &&
+ (net->channel > ieee->ibss_maxjoin_chal))
+ return;
+ if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
+ /* if the user specified the AP MAC, we need also the essid
+ * This could be obtained by beacons or, if the network does not
+ * broadcast it, it can be put manually.
+ */
+ apset = ieee->wap_set;
+ ssidset = ieee->ssid_set;
+ ssidbroad = !(net->ssid_len == 0 || net->ssid[0] == '\0');
+ apmatch = (memcmp(ieee->current_network.bssid, net->bssid,
+ ETH_ALEN) == 0);
+ if (!ssidbroad) {
+ ssidmatch = (ieee->current_network.ssid_len ==
+ net->hidden_ssid_len) &&
+ (!strncmp(ieee->current_network.ssid,
+ net->hidden_ssid, net->hidden_ssid_len));
+ if (net->hidden_ssid_len > 0) {
+ strncpy(net->ssid, net->hidden_ssid,
+ net->hidden_ssid_len);
+ net->ssid_len = net->hidden_ssid_len;
+ ssidbroad = 1;
+ }
+ } else
+ ssidmatch =
+ (ieee->current_network.ssid_len == net->ssid_len) &&
+ (!strncmp(ieee->current_network.ssid, net->ssid,
+ net->ssid_len));
+
+ /* if the user set the AP check if match.
+ * if the network does not broadcast essid we check the
+ * user supplied ANY essid
+ * if the network does broadcast and the user does not set
+ * essid it is OK
+ * if the network does broadcast and the user did set essid
+ * check if essid match
+ * if the ap is not set, check that the user set the bssid
+ * and the network does broadcast and that those two bssid match
+ */
+ if ((apset && apmatch &&
+ ((ssidset && ssidbroad && ssidmatch) ||
+ (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) ||
+ (!apset && ssidset && ssidbroad && ssidmatch) ||
+ (ieee->is_roaming && ssidset && ssidbroad && ssidmatch)) {
+ /* if the essid is hidden replace it with the
+ * essid provided by the user.
+ */
+ if (!ssidbroad) {
+ strncpy(tmp_ssid, ieee->current_network.ssid,
+ IW_ESSID_MAX_SIZE);
+ tmp_ssid_len = ieee->current_network.ssid_len;
+ }
+ memcpy(&ieee->current_network, net,
+ sizeof(struct rtllib_network));
+ if (!ssidbroad) {
+ strncpy(ieee->current_network.ssid, tmp_ssid,
+ IW_ESSID_MAX_SIZE);
+ ieee->current_network.ssid_len = tmp_ssid_len;
+ }
+ netdev_info(ieee->dev,
+ "Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d, mode:%x cur_net.flags:0x%x\n",
+ ieee->current_network.ssid,
+ ieee->current_network.channel,
+ ieee->current_network.qos_data.supported,
+ ieee->pHTInfo->bEnableHT,
+ ieee->current_network.bssht.bdSupportHT,
+ ieee->current_network.mode,
+ ieee->current_network.flags);
+
+ if ((rtllib_act_scanning(ieee, false)) &&
+ !(ieee->softmac_features & IEEE_SOFTMAC_SCAN))
+ rtllib_stop_scan_syncro(ieee);
+
+ ieee->hwscan_ch_bk = ieee->current_network.channel;
+ HTResetIOTSetting(ieee->pHTInfo);
+ ieee->wmm_acm = 0;
+ if (ieee->iw_mode == IW_MODE_INFRA) {
+ /* Join the network for the first time */
+ ieee->AsocRetryCount = 0;
+ if ((ieee->current_network.qos_data.supported == 1) &&
+ ieee->current_network.bssht.bdSupportHT)
+ HTResetSelfAndSavePeerSetting(ieee,
+ &(ieee->current_network));
+ else
+ ieee->pHTInfo->bCurrentHTSupport =
+ false;
+
+ ieee->state = RTLLIB_ASSOCIATING;
+ if (ieee->LedControlHandler != NULL)
+ ieee->LedControlHandler(ieee->dev,
+ LED_CTL_START_TO_LINK);
+ queue_delayed_work_rsl(ieee->wq,
+ &ieee->associate_procedure_wq, 0);
+ } else {
+ if (rtllib_is_54g(&ieee->current_network) &&
+ (ieee->modulation & RTLLIB_OFDM_MODULATION)) {
+ ieee->rate = 108;
+ ieee->SetWirelessMode(ieee->dev, IEEE_G);
+ netdev_info(ieee->dev, "Using G rates\n");
+ } else {
+ ieee->rate = 22;
+ ieee->SetWirelessMode(ieee->dev, IEEE_B);
+ netdev_info(ieee->dev, "Using B rates\n");
+ }
+ memset(ieee->dot11HTOperationalRateSet, 0, 16);
+ ieee->state = RTLLIB_LINKED;
+ }
+ }
+ }
+}
+
+void rtllib_softmac_check_all_nets(struct rtllib_device *ieee)
+{
+ unsigned long flags;
+ struct rtllib_network *target;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ list_for_each_entry(target, &ieee->network_list, list) {
+
+ /* if the state become different that NOLINK means
+ * we had found what we are searching for
+ */
+
+ if (ieee->state != RTLLIB_NOLINK)
+ break;
+
+ if (ieee->scan_age == 0 || time_after(target->last_scanned +
+ ieee->scan_age, jiffies))
+ rtllib_softmac_new_net(ieee, target);
+ }
+ spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
+{
+ struct rtllib_authentication *a;
+ u8 *t;
+
+ if (skb->len < (sizeof(struct rtllib_authentication) -
+ sizeof(struct rtllib_info_element))) {
+ RTLLIB_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
+ return 0xcafe;
+ }
+ *challenge = NULL;
+ a = (struct rtllib_authentication *) skb->data;
+ if (skb->len > (sizeof(struct rtllib_authentication) + 3)) {
+ t = skb->data + sizeof(struct rtllib_authentication);
+
+ if (*(t++) == MFIE_TYPE_CHALLENGE) {
+ *chlen = *(t++);
+ *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
+ if (!*challenge)
+ return -ENOMEM;
+ }
+ }
+ return cpu_to_le16(a->status);
+}
+
+static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
+{
+ struct rtllib_authentication *a;
+
+ if (skb->len < (sizeof(struct rtllib_authentication) -
+ sizeof(struct rtllib_info_element))) {
+ RTLLIB_DEBUG_MGMT("invalid len in auth request: %d\n",
+ skb->len);
+ return -1;
+ }
+ a = (struct rtllib_authentication *) skb->data;
+
+ memcpy(dest, a->header.addr2, ETH_ALEN);
+
+ if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
+ return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
+
+ return WLAN_STATUS_SUCCESS;
+}
+
+static short probe_rq_parse(struct rtllib_device *ieee, struct sk_buff *skb,
+ u8 *src)
+{
+ u8 *tag;
+ u8 *skbend;
+ u8 *ssid = NULL;
+ u8 ssidlen = 0;
+ struct rtllib_hdr_3addr *header =
+ (struct rtllib_hdr_3addr *) skb->data;
+ bool bssid_match;
+
+ if (skb->len < sizeof(struct rtllib_hdr_3addr))
+ return -1; /* corrupted */
+
+ bssid_match =
+ (memcmp(header->addr3, ieee->current_network.bssid, ETH_ALEN) != 0) &&
+ (!is_broadcast_ether_addr(header->addr3));
+ if (bssid_match)
+ return -1;
+
+ memcpy(src, header->addr2, ETH_ALEN);
+
+ skbend = (u8 *)skb->data + skb->len;
+
+ tag = skb->data + sizeof(struct rtllib_hdr_3addr);
+
+ while (tag + 1 < skbend) {
+ if (*tag == 0) {
+ ssid = tag + 2;
+ ssidlen = *(tag + 1);
+ break;
+ }
+ tag++; /* point to the len field */
+ tag = tag + *(tag); /* point to the last data byte of the tag */
+ tag++; /* point to the next tag */
+ }
+
+ if (ssidlen == 0)
+ return 1;
+
+ if (!ssid)
+ return 1; /* ssid not found in tagged param */
+
+ return !strncmp(ssid, ieee->current_network.ssid, ssidlen);
+}
+
+static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
+{
+ struct rtllib_assoc_request_frame *a;
+
+ if (skb->len < (sizeof(struct rtllib_assoc_request_frame) -
+ sizeof(struct rtllib_info_element))) {
+
+ RTLLIB_DEBUG_MGMT("invalid len in auth request:%d\n", skb->len);
+ return -1;
+ }
+
+ a = (struct rtllib_assoc_request_frame *) skb->data;
+
+ memcpy(dest, a->header.addr2, ETH_ALEN);
+
+ return 0;
+}
+
+static inline u16 assoc_parse(struct rtllib_device *ieee, struct sk_buff *skb,
+ int *aid)
+{
+ struct rtllib_assoc_response_frame *response_head;
+ u16 status_code;
+
+ if (skb->len < sizeof(struct rtllib_assoc_response_frame)) {
+ RTLLIB_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
+ return 0xcafe;
+ }
+
+ response_head = (struct rtllib_assoc_response_frame *) skb->data;
+ *aid = le16_to_cpu(response_head->aid) & 0x3fff;
+
+ status_code = le16_to_cpu(response_head->status);
+ if ((status_code == WLAN_STATUS_ASSOC_DENIED_RATES ||
+ status_code == WLAN_STATUS_CAPS_UNSUPPORTED) &&
+ ((ieee->mode == IEEE_G) &&
+ (ieee->current_network.mode == IEEE_N_24G) &&
+ (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
+ ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
+ } else {
+ ieee->AsocRetryCount = 0;
+ }
+
+ return le16_to_cpu(response_head->status);
+}
+
+void rtllib_rx_probe_rq(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+ u8 dest[ETH_ALEN];
+
+ ieee->softmac_stats.rx_probe_rq++;
+ if (probe_rq_parse(ieee, skb, dest) > 0) {
+ ieee->softmac_stats.tx_probe_rs++;
+ rtllib_resp_to_probe(ieee, dest);
+ }
+}
+
+static inline void rtllib_rx_auth_rq(struct rtllib_device *ieee,
+ struct sk_buff *skb)
+{
+ u8 dest[ETH_ALEN];
+ int status;
+
+ ieee->softmac_stats.rx_auth_rq++;
+
+ status = auth_rq_parse(skb, dest);
+ if (status != -1)
+ rtllib_resp_to_auth(ieee, status, dest);
+}
+
+static inline void rtllib_rx_assoc_rq(struct rtllib_device *ieee,
+ struct sk_buff *skb)
+{
+
+ u8 dest[ETH_ALEN];
+
+ ieee->softmac_stats.rx_ass_rq++;
+ if (assoc_rq_parse(skb, dest) != -1)
+ rtllib_resp_to_assoc_rq(ieee, dest);
+
+ netdev_info(ieee->dev, "New client associated: %pM\n", dest);
+}
+
+void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr)
+{
+
+ struct sk_buff *buf = rtllib_null_func(ieee, pwr);
+
+ if (buf)
+ softmac_ps_mgmt_xmit(buf, ieee);
+}
+EXPORT_SYMBOL(rtllib_sta_ps_send_null_frame);
+
+void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee)
+{
+ struct sk_buff *buf = rtllib_pspoll_func(ieee);
+
+ if (buf)
+ softmac_ps_mgmt_xmit(buf, ieee);
+}
+
+static short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u64 *time)
+{
+ int timeout = ieee->ps_timeout;
+ u8 dtim;
+ struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
+ (&(ieee->PowerSaveControl));
+
+ if (ieee->LPSDelayCnt) {
+ ieee->LPSDelayCnt--;
+ return 0;
+ }
+
+ dtim = ieee->current_network.dtim_data;
+ if (!(dtim & RTLLIB_DTIM_VALID))
+ return 0;
+ timeout = ieee->current_network.beacon_interval;
+ ieee->current_network.dtim_data = RTLLIB_DTIM_INVALID;
+ /* there's no need to nofity AP that I find you buffered
+ * with broadcast packet
+ */
+ if (dtim & (RTLLIB_DTIM_UCAST & ieee->ps))
+ return 2;
+
+ if (!time_after(jiffies,
+ ieee->dev->trans_start + msecs_to_jiffies(timeout)))
+ return 0;
+ if (!time_after(jiffies,
+ ieee->last_rx_ps_time + msecs_to_jiffies(timeout)))
+ return 0;
+ if ((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) &&
+ (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
+ return 0;
+
+ if (time) {
+ if (ieee->bAwakePktSent) {
+ pPSC->LPSAwakeIntvl = 1;
+ } else {
+ u8 MaxPeriod = 1;
+
+ if (pPSC->LPSAwakeIntvl == 0)
+ pPSC->LPSAwakeIntvl = 1;
+ if (pPSC->RegMaxLPSAwakeIntvl == 0)
+ MaxPeriod = 1;
+ else if (pPSC->RegMaxLPSAwakeIntvl == 0xFF)
+ MaxPeriod = ieee->current_network.dtim_period;
+ else
+ MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
+ pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >=
+ MaxPeriod) ? MaxPeriod :
+ (pPSC->LPSAwakeIntvl + 1);
+ }
+ {
+ u8 LPSAwakeIntvl_tmp = 0;
+ u8 period = ieee->current_network.dtim_period;
+ u8 count = ieee->current_network.tim.tim_count;
+
+ if (count == 0) {
+ if (pPSC->LPSAwakeIntvl > period)
+ LPSAwakeIntvl_tmp = period +
+ (pPSC->LPSAwakeIntvl -
+ period) -
+ ((pPSC->LPSAwakeIntvl-period) %
+ period);
+ else
+ LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
+
+ } else {
+ if (pPSC->LPSAwakeIntvl >
+ ieee->current_network.tim.tim_count)
+ LPSAwakeIntvl_tmp = count +
+ (pPSC->LPSAwakeIntvl - count) -
+ ((pPSC->LPSAwakeIntvl-count)%period);
+ else
+ LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
+ }
+
+ *time = ieee->current_network.last_dtim_sta_time
+ + msecs_to_jiffies(ieee->current_network.beacon_interval *
+ LPSAwakeIntvl_tmp);
+ }
+ }
+
+ return 1;
+
+
+}
+
+static inline void rtllib_sta_ps(struct rtllib_device *ieee)
+{
+ u64 time;
+ short sleep;
+ unsigned long flags, flags2;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ if ((ieee->ps == RTLLIB_PS_DISABLED ||
+ ieee->iw_mode != IW_MODE_INFRA ||
+ ieee->state != RTLLIB_LINKED)) {
+ RT_TRACE(COMP_DBG,
+ "=====>%s(): no need to ps,wake up!! ieee->ps is %d, ieee->iw_mode is %d, ieee->state is %d\n",
+ __func__, ieee->ps, ieee->iw_mode, ieee->state);
+ spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+ rtllib_sta_wakeup(ieee, 1);
+
+ spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+ }
+ sleep = rtllib_sta_ps_sleep(ieee, &time);
+ /* 2 wake, 1 sleep, 0 do nothing */
+ if (sleep == 0)
+ goto out;
+ if (sleep == 1) {
+ if (ieee->sta_sleep == LPS_IS_SLEEP) {
+ ieee->enter_sleep_state(ieee->dev, time);
+ } else if (ieee->sta_sleep == LPS_IS_WAKE) {
+ spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+
+ if (ieee->ps_is_queue_empty(ieee->dev)) {
+ ieee->sta_sleep = LPS_WAIT_NULL_DATA_SEND;
+ ieee->ack_tx_to_ieee = 1;
+ rtllib_sta_ps_send_null_frame(ieee, 1);
+ ieee->ps_time = time;
+ }
+ spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+
+ }
+
+ ieee->bAwakePktSent = false;
+
+ } else if (sleep == 2) {
+ spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+
+ rtllib_sta_wakeup(ieee, 1);
+
+ spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+ }
+
+out:
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+}
+
+void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl)
+{
+ if (ieee->sta_sleep == LPS_IS_WAKE) {
+ if (nl) {
+ if (ieee->pHTInfo->IOTAction &
+ HT_IOT_ACT_NULL_DATA_POWER_SAVING) {
+ ieee->ack_tx_to_ieee = 1;
+ rtllib_sta_ps_send_null_frame(ieee, 0);
+ } else {
+ ieee->ack_tx_to_ieee = 1;
+ rtllib_sta_ps_send_pspoll_frame(ieee);
+ }
+ }
+ return;
+
+ }
+
+ if (ieee->sta_sleep == LPS_IS_SLEEP)
+ ieee->sta_wake_up(ieee->dev);
+ if (nl) {
+ if (ieee->pHTInfo->IOTAction &
+ HT_IOT_ACT_NULL_DATA_POWER_SAVING) {
+ ieee->ack_tx_to_ieee = 1;
+ rtllib_sta_ps_send_null_frame(ieee, 0);
+ } else {
+ ieee->ack_tx_to_ieee = 1;
+ ieee->polling = true;
+ rtllib_sta_ps_send_pspoll_frame(ieee);
+ }
+
+ } else {
+ ieee->sta_sleep = LPS_IS_WAKE;
+ ieee->polling = false;
+ }
+}
+
+void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success)
+{
+ unsigned long flags, flags2;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ if (ieee->sta_sleep == LPS_WAIT_NULL_DATA_SEND) {
+ /* Null frame with PS bit set */
+ if (success) {
+ ieee->sta_sleep = LPS_IS_SLEEP;
+ ieee->enter_sleep_state(ieee->dev, ieee->ps_time);
+ }
+ /* if the card report not success we can't be sure the AP
+ * has not RXed so we can't assume the AP believe us awake
+ */
+ } else {/* 21112005 - tx again null without PS bit if lost */
+
+ if ((ieee->sta_sleep == LPS_IS_WAKE) && !success) {
+ spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+ if (ieee->pHTInfo->IOTAction &
+ HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+ rtllib_sta_ps_send_null_frame(ieee, 0);
+ else
+ rtllib_sta_ps_send_pspoll_frame(ieee);
+ spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+ }
+ }
+ spin_unlock_irqrestore(&ieee->lock, flags);
+}
+EXPORT_SYMBOL(rtllib_ps_tx_ack);
+
+static void rtllib_process_action(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+ struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data;
+ u8 *act = rtllib_get_payload((struct rtllib_hdr *)header);
+ u8 category = 0;
+
+ if (act == NULL) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "error to get payload of action frame\n");
+ return;
+ }
+
+ category = *act;
+ act++;
+ switch (category) {
+ case ACT_CAT_BA:
+ switch (*act) {
+ case ACT_ADDBAREQ:
+ rtllib_rx_ADDBAReq(ieee, skb);
+ break;
+ case ACT_ADDBARSP:
+ rtllib_rx_ADDBARsp(ieee, skb);
+ break;
+ case ACT_DELBA:
+ rtllib_rx_DELBA(ieee, skb);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+inline int rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats)
+{
+ u16 errcode;
+ int aid;
+ u8 *ies;
+ struct rtllib_assoc_response_frame *assoc_resp;
+ struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data;
+
+ RTLLIB_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
+ WLAN_FC_GET_STYPE(header->frame_ctl));
+
+ if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
+ ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATED &&
+ (ieee->iw_mode == IW_MODE_INFRA)) {
+ errcode = assoc_parse(ieee, skb, &aid);
+ if (0 == errcode) {
+ struct rtllib_network *network =
+ kzalloc(sizeof(struct rtllib_network),
+ GFP_ATOMIC);
+
+ if (!network)
+ return 1;
+ ieee->state = RTLLIB_LINKED;
+ ieee->assoc_id = aid;
+ ieee->softmac_stats.rx_ass_ok++;
+ /* station support qos */
+ /* Let the register setting default with Legacy station */
+ assoc_resp = (struct rtllib_assoc_response_frame *)skb->data;
+ if (ieee->current_network.qos_data.supported == 1) {
+ if (rtllib_parse_info_param(ieee, assoc_resp->info_element,
+ rx_stats->len - sizeof(*assoc_resp),
+ network, rx_stats)) {
+ kfree(network);
+ return 1;
+ }
+ memcpy(ieee->pHTInfo->PeerHTCapBuf,
+ network->bssht.bdHTCapBuf,
+ network->bssht.bdHTCapLen);
+ memcpy(ieee->pHTInfo->PeerHTInfoBuf,
+ network->bssht.bdHTInfoBuf,
+ network->bssht.bdHTInfoLen);
+ if (ieee->handle_assoc_response != NULL)
+ ieee->handle_assoc_response(ieee->dev,
+ (struct rtllib_assoc_response_frame *)header,
+ network);
+ }
+ kfree(network);
+
+ kfree(ieee->assocresp_ies);
+ ieee->assocresp_ies = NULL;
+ ies = &(assoc_resp->info_element[0].id);
+ ieee->assocresp_ies_len = (skb->data + skb->len) - ies;
+ ieee->assocresp_ies = kmalloc(ieee->assocresp_ies_len,
+ GFP_ATOMIC);
+ if (ieee->assocresp_ies)
+ memcpy(ieee->assocresp_ies, ies,
+ ieee->assocresp_ies_len);
+ else {
+ netdev_info(ieee->dev,
+ "%s()Warning: can't alloc memory for assocresp_ies\n",
+ __func__);
+ ieee->assocresp_ies_len = 0;
+ }
+ rtllib_associate_complete(ieee);
+ } else {
+ /* aid could not been allocated */
+ ieee->softmac_stats.rx_ass_err++;
+ netdev_info(ieee->dev,
+ "Association response status code 0x%x\n",
+ errcode);
+ RTLLIB_DEBUG_MGMT(
+ "Association response status code 0x%x\n",
+ errcode);
+ if (ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT)
+ queue_delayed_work_rsl(ieee->wq,
+ &ieee->associate_procedure_wq, 0);
+ else
+ rtllib_associate_abort(ieee);
+ }
+ }
+ return 0;
+}
+
+static void rtllib_rx_auth_resp(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+ u16 errcode;
+ u8 *challenge;
+ int chlen = 0;
+ bool bSupportNmode = true, bHalfSupportNmode = false;
+
+ errcode = auth_parse(skb, &challenge, &chlen);
+
+ if (errcode) {
+ ieee->softmac_stats.rx_auth_rs_err++;
+ RTLLIB_DEBUG_MGMT("Authentication respose status code 0x%x",
+ errcode);
+
+ netdev_info(ieee->dev,
+ "Authentication respose status code 0x%x", errcode);
+ rtllib_associate_abort(ieee);
+ return;
+ }
+
+ if (ieee->open_wep || !challenge) {
+ ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATED;
+ ieee->softmac_stats.rx_auth_rs_ok++;
+ if (!(ieee->pHTInfo->IOTAction & HT_IOT_ACT_PURE_N_MODE)) {
+ if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
+ if (IsHTHalfNmodeAPs(ieee)) {
+ bSupportNmode = true;
+ bHalfSupportNmode = true;
+ } else {
+ bSupportNmode = false;
+ bHalfSupportNmode = false;
+ }
+ }
+ }
+ /* Dummy wirless mode setting to avoid encryption issue */
+ if (bSupportNmode) {
+ ieee->SetWirelessMode(ieee->dev,
+ ieee->current_network.mode);
+ } else {
+ /*TODO*/
+ ieee->SetWirelessMode(ieee->dev, IEEE_G);
+ }
+
+ if ((ieee->current_network.mode == IEEE_N_24G) &&
+ bHalfSupportNmode) {
+ netdev_info(ieee->dev, "======>enter half N mode\n");
+ ieee->bHalfWirelessN24GMode = true;
+ } else {
+ ieee->bHalfWirelessN24GMode = false;
+ }
+ rtllib_associate_step2(ieee);
+ } else {
+ rtllib_auth_challenge(ieee, challenge, chlen);
+ }
+}
+
+inline int rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats)
+{
+
+ if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
+ if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING &&
+ (ieee->iw_mode == IW_MODE_INFRA)) {
+ RTLLIB_DEBUG_MGMT("Received authentication response");
+ rtllib_rx_auth_resp(ieee, skb);
+ } else if (ieee->iw_mode == IW_MODE_MASTER) {
+ rtllib_rx_auth_rq(ieee, skb);
+ }
+ }
+ return 0;
+}
+
+inline int rtllib_rx_deauth(struct rtllib_device *ieee, struct sk_buff *skb)
+{
+ struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data;
+
+ if (memcmp(header->addr3, ieee->current_network.bssid, ETH_ALEN) != 0)
+ return 0;
+
+ /* FIXME for now repeat all the association procedure
+ * both for disassociation and deauthentication
+ */
+ if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
+ ieee->state == RTLLIB_LINKED &&
+ (ieee->iw_mode == IW_MODE_INFRA)) {
+ netdev_info(ieee->dev,
+ "==========>received disassoc/deauth(%x) frame, reason code:%x\n",
+ WLAN_FC_GET_STYPE(header->frame_ctl),
+ ((struct rtllib_disassoc *)skb->data)->reason);
+ ieee->state = RTLLIB_ASSOCIATING;
+ ieee->softmac_stats.reassoc++;
+ ieee->is_roaming = true;
+ ieee->LinkDetectInfo.bBusyTraffic = false;
+ rtllib_disassociate(ieee);
+ RemovePeerTS(ieee, header->addr2);
+ if (ieee->LedControlHandler != NULL)
+ ieee->LedControlHandler(ieee->dev,
+ LED_CTL_START_TO_LINK);
+
+ if (!(ieee->rtllib_ap_sec_type(ieee) &
+ (SEC_ALG_CCMP|SEC_ALG_TKIP)))
+ queue_delayed_work_rsl(ieee->wq,
+ &ieee->associate_procedure_wq, 5);
+ }
+ return 0;
+}
+
+inline int rtllib_rx_frame_softmac(struct rtllib_device *ieee,
+ struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats, u16 type,
+ u16 stype)
+{
+ struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data;
+
+ if (!ieee->proto_started)
+ return 0;
+
+ switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
+ case RTLLIB_STYPE_ASSOC_RESP:
+ case RTLLIB_STYPE_REASSOC_RESP:
+ if (rtllib_rx_assoc_resp(ieee, skb, rx_stats) == 1)
+ return 1;
+ break;
+ case RTLLIB_STYPE_ASSOC_REQ:
+ case RTLLIB_STYPE_REASSOC_REQ:
+ if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
+ ieee->iw_mode == IW_MODE_MASTER)
+ rtllib_rx_assoc_rq(ieee, skb);
+ break;
+ case RTLLIB_STYPE_AUTH:
+ rtllib_rx_auth(ieee, skb, rx_stats);
+ break;
+ case RTLLIB_STYPE_DISASSOC:
+ case RTLLIB_STYPE_DEAUTH:
+ rtllib_rx_deauth(ieee, skb);
+ break;
+ case RTLLIB_STYPE_MANAGE_ACT:
+ rtllib_process_action(ieee, skb);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+/* following are for a simpler TX queue management.
+ * Instead of using netif_[stop/wake]_queue the driver
+ * will use these two functions (plus a reset one), that
+ * will internally use the kernel netif_* and takes
+ * care of the ieee802.11 fragmentation.
+ * So the driver receives a fragment per time and might
+ * call the stop function when it wants to not
+ * have enough room to TX an entire packet.
+ * This might be useful if each fragment needs it's own
+ * descriptor, thus just keep a total free memory > than
+ * the max fragmentation threshold is not enough.. If the
+ * ieee802.11 stack passed a TXB struct then you need
+ * to keep N free descriptors where
+ * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
+ * In this way you need just one and the 802.11 stack
+ * will take care of buffering fragments and pass them to
+ * to the driver later, when it wakes the queue.
+ */
+void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee)
+{
+
+ unsigned int queue_index = txb->queue_index;
+ unsigned long flags;
+ int i;
+ struct cb_desc *tcb_desc = NULL;
+ unsigned long queue_len = 0;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ /* called with 2nd parm 0, no tx mgmt lock required */
+ rtllib_sta_wakeup(ieee, 0);
+
+ /* update the tx status */
+ tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb +
+ MAX_DEV_ADDR_SIZE);
+ if (tcb_desc->bMulticast)
+ ieee->stats.multicast++;
+
+ /* if xmit available, just xmit it immediately, else just insert it to
+ * the wait queue
+ */
+ for (i = 0; i < txb->nr_frags; i++) {
+ queue_len = skb_queue_len(&ieee->skb_waitQ[queue_index]);
+ if ((queue_len != 0) ||
+ (!ieee->check_nic_enough_desc(ieee->dev, queue_index)) ||
+ (ieee->queue_stop)) {
+ /* insert the skb packet to the wait queue
+ * as for the completion function, it does not need
+ * to check it any more.
+ */
+ if (queue_len < 200)
+ skb_queue_tail(&ieee->skb_waitQ[queue_index],
+ txb->fragments[i]);
+ else
+ kfree_skb(txb->fragments[i]);
+ } else {
+ ieee->softmac_data_hard_start_xmit(
+ txb->fragments[i],
+ ieee->dev, ieee->rate);
+ }
+ }
+
+ rtllib_txb_free(txb);
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+}
+
+/* called with ieee->lock acquired */
+static void rtllib_resume_tx(struct rtllib_device *ieee)
+{
+ int i;
+
+ for (i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags;
+ i++) {
+
+ if (ieee->queue_stop) {
+ ieee->tx_pending.frag = i;
+ return;
+ }
+
+ ieee->softmac_data_hard_start_xmit(
+ ieee->tx_pending.txb->fragments[i],
+ ieee->dev, ieee->rate);
+ ieee->stats.tx_packets++;
+ }
+
+ rtllib_txb_free(ieee->tx_pending.txb);
+ ieee->tx_pending.txb = NULL;
+}
+
+
+void rtllib_reset_queue(struct rtllib_device *ieee)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+ init_mgmt_queue(ieee);
+ if (ieee->tx_pending.txb) {
+ rtllib_txb_free(ieee->tx_pending.txb);
+ ieee->tx_pending.txb = NULL;
+ }
+ ieee->queue_stop = 0;
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+}
+EXPORT_SYMBOL(rtllib_reset_queue);
+
+void rtllib_wake_queue(struct rtllib_device *ieee)
+{
+
+ unsigned long flags;
+ struct sk_buff *skb;
+ struct rtllib_hdr_3addr *header;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+ if (!ieee->queue_stop)
+ goto exit;
+
+ ieee->queue_stop = 0;
+
+ if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
+ while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))) {
+
+ header = (struct rtllib_hdr_3addr *) skb->data;
+
+ header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+
+ if (ieee->seq_ctrl[0] == 0xFFF)
+ ieee->seq_ctrl[0] = 0;
+ else
+ ieee->seq_ctrl[0]++;
+
+ ieee->softmac_data_hard_start_xmit(skb, ieee->dev,
+ ieee->basic_rate);
+ }
+ }
+ if (!ieee->queue_stop && ieee->tx_pending.txb)
+ rtllib_resume_tx(ieee);
+
+ if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
+ ieee->softmac_stats.swtxawake++;
+ netif_wake_queue(ieee->dev);
+ }
+
+exit:
+ spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+
+void rtllib_stop_queue(struct rtllib_device *ieee)
+{
+
+ if (!netif_queue_stopped(ieee->dev)) {
+ netif_stop_queue(ieee->dev);
+ ieee->softmac_stats.swtxstop++;
+ }
+ ieee->queue_stop = 1;
+
+}
+
+void rtllib_stop_all_queues(struct rtllib_device *ieee)
+{
+ unsigned int i;
+
+ for (i = 0; i < ieee->dev->num_tx_queues; i++)
+ netdev_get_tx_queue(ieee->dev, i)->trans_start = jiffies;
+
+ netif_tx_stop_all_queues(ieee->dev);
+}
+
+void rtllib_wake_all_queues(struct rtllib_device *ieee)
+{
+ netif_tx_wake_all_queues(ieee->dev);
+}
+
+inline void rtllib_randomize_cell(struct rtllib_device *ieee)
+{
+
+ random_ether_addr(ieee->current_network.bssid);
+}
+
+/* called in user context only */
+void rtllib_start_master_bss(struct rtllib_device *ieee)
+{
+ ieee->assoc_id = 1;
+
+ if (ieee->current_network.ssid_len == 0) {
+ strncpy(ieee->current_network.ssid,
+ RTLLIB_DEFAULT_TX_ESSID,
+ IW_ESSID_MAX_SIZE);
+
+ ieee->current_network.ssid_len =
+ strlen(RTLLIB_DEFAULT_TX_ESSID);
+ ieee->ssid_set = 1;
+ }
+
+ memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
+
+ ieee->set_chan(ieee->dev, ieee->current_network.channel);
+ ieee->state = RTLLIB_LINKED;
+ ieee->link_change(ieee->dev);
+ notify_wx_assoc_event(ieee);
+
+ if (ieee->data_hard_resume)
+ ieee->data_hard_resume(ieee->dev);
+
+ netif_carrier_on(ieee->dev);
+}
+
+static void rtllib_start_monitor_mode(struct rtllib_device *ieee)
+{
+ /* reset hardware status */
+ if (ieee->raw_tx) {
+ if (ieee->data_hard_resume)
+ ieee->data_hard_resume(ieee->dev);
+
+ netif_carrier_on(ieee->dev);
+ }
+}
+
+static void rtllib_start_ibss_wq(void *data)
+{
+ struct rtllib_device *ieee = container_of_dwork_rsl(data,
+ struct rtllib_device, start_ibss_wq);
+ /* iwconfig mode ad-hoc will schedule this and return
+ * on the other hand this will block further iwconfig SET
+ * operations because of the wx_sem hold.
+ * Anyway some most set operations set a flag to speed-up
+ * (abort) this wq (when syncro scanning) before sleeping
+ * on the semaphore
+ */
+ if (!ieee->proto_started) {
+ netdev_info(ieee->dev, "==========oh driver down return\n");
+ return;
+ }
+ down(&ieee->wx_sem);
+
+ if (ieee->current_network.ssid_len == 0) {
+ strcpy(ieee->current_network.ssid, RTLLIB_DEFAULT_TX_ESSID);
+ ieee->current_network.ssid_len = strlen(RTLLIB_DEFAULT_TX_ESSID);
+ ieee->ssid_set = 1;
+ }
+
+ ieee->state = RTLLIB_NOLINK;
+ ieee->mode = IEEE_G;
+ /* check if we have this cell in our network list */
+ rtllib_softmac_check_all_nets(ieee);
+
+
+ /* if not then the state is not linked. Maybe the user switched to
+ * ad-hoc mode just after being in monitor mode, or just after
+ * being very few time in managed mode (so the card have had no
+ * time to scan all the chans..) or we have just run up the iface
+ * after setting ad-hoc mode. So we have to give another try..
+ * Here, in ibss mode, should be safe to do this without extra care
+ * (in bss mode we had to make sure no-one tried to associate when
+ * we had just checked the ieee->state and we was going to start the
+ * scan) because in ibss mode the rtllib_new_net function, when
+ * finds a good net, just set the ieee->state to RTLLIB_LINKED,
+ * so, at worst, we waste a bit of time to initiate an unneeded syncro
+ * scan, that will stop at the first round because it sees the state
+ * associated.
+ */
+ if (ieee->state == RTLLIB_NOLINK)
+ rtllib_start_scan_syncro(ieee, 0);
+
+ /* the network definitively is not here.. create a new cell */
+ if (ieee->state == RTLLIB_NOLINK) {
+ netdev_info(ieee->dev, "creating new IBSS cell\n");
+ ieee->current_network.channel = ieee->IbssStartChnl;
+ if (!ieee->wap_set)
+ rtllib_randomize_cell(ieee);
+
+ if (ieee->modulation & RTLLIB_CCK_MODULATION) {
+
+ ieee->current_network.rates_len = 4;
+
+ ieee->current_network.rates[0] =
+ RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_1MB;
+ ieee->current_network.rates[1] =
+ RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_2MB;
+ ieee->current_network.rates[2] =
+ RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_5MB;
+ ieee->current_network.rates[3] =
+ RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_11MB;
+
+ } else
+ ieee->current_network.rates_len = 0;
+
+ if (ieee->modulation & RTLLIB_OFDM_MODULATION) {
+ ieee->current_network.rates_ex_len = 8;
+
+ ieee->current_network.rates_ex[0] =
+ RTLLIB_OFDM_RATE_6MB;
+ ieee->current_network.rates_ex[1] =
+ RTLLIB_OFDM_RATE_9MB;
+ ieee->current_network.rates_ex[2] =
+ RTLLIB_OFDM_RATE_12MB;
+ ieee->current_network.rates_ex[3] =
+ RTLLIB_OFDM_RATE_18MB;
+ ieee->current_network.rates_ex[4] =
+ RTLLIB_OFDM_RATE_24MB;
+ ieee->current_network.rates_ex[5] =
+ RTLLIB_OFDM_RATE_36MB;
+ ieee->current_network.rates_ex[6] =
+ RTLLIB_OFDM_RATE_48MB;
+ ieee->current_network.rates_ex[7] =
+ RTLLIB_OFDM_RATE_54MB;
+
+ ieee->rate = 108;
+ } else {
+ ieee->current_network.rates_ex_len = 0;
+ ieee->rate = 22;
+ }
+
+ ieee->current_network.qos_data.supported = 0;
+ ieee->SetWirelessMode(ieee->dev, IEEE_G);
+ ieee->current_network.mode = ieee->mode;
+ ieee->current_network.atim_window = 0;
+ ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
+ }
+
+ netdev_info(ieee->dev, "%s(): ieee->mode = %d\n", __func__, ieee->mode);
+ if ((ieee->mode == IEEE_N_24G) || (ieee->mode == IEEE_N_5G))
+ HTUseDefaultSetting(ieee);
+ else
+ ieee->pHTInfo->bCurrentHTSupport = false;
+
+ ieee->SetHwRegHandler(ieee->dev, HW_VAR_MEDIA_STATUS,
+ (u8 *)(&ieee->state));
+
+ ieee->state = RTLLIB_LINKED;
+ ieee->link_change(ieee->dev);
+
+ HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+ if (ieee->LedControlHandler != NULL)
+ ieee->LedControlHandler(ieee->dev, LED_CTL_LINK);
+
+ rtllib_start_send_beacons(ieee);
+
+ notify_wx_assoc_event(ieee);
+
+ if (ieee->data_hard_resume)
+ ieee->data_hard_resume(ieee->dev);
+
+ netif_carrier_on(ieee->dev);
+
+ up(&ieee->wx_sem);
+}
+
+inline void rtllib_start_ibss(struct rtllib_device *ieee)
+{
+ queue_delayed_work_rsl(ieee->wq, &ieee->start_ibss_wq,
+ msecs_to_jiffies(150));
+}
+
+/* this is called only in user context, with wx_sem held */
+void rtllib_start_bss(struct rtllib_device *ieee)
+{
+ unsigned long flags;
+
+ if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) {
+ if (!ieee->bGlobalDomain)
+ return;
+ }
+ /* check if we have already found the net we
+ * are interested in (if any).
+ * if not (we are disassociated and we are not
+ * in associating / authenticating phase) start the background scanning.
+ */
+ rtllib_softmac_check_all_nets(ieee);
+
+ /* ensure no-one start an associating process (thus setting
+ * the ieee->state to rtllib_ASSOCIATING) while we
+ * have just checked it and we are going to enable scan.
+ * The rtllib_new_net function is always called with
+ * lock held (from both rtllib_softmac_check_all_nets and
+ * the rx path), so we cannot be in the middle of such function
+ */
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ if (ieee->state == RTLLIB_NOLINK)
+ rtllib_start_scan(ieee);
+ spin_unlock_irqrestore(&ieee->lock, flags);
+}
+
+static void rtllib_link_change_wq(void *data)
+{
+ struct rtllib_device *ieee = container_of_dwork_rsl(data,
+ struct rtllib_device, link_change_wq);
+ ieee->link_change(ieee->dev);
+}
+/* called only in userspace context */
+void rtllib_disassociate(struct rtllib_device *ieee)
+{
+ netif_carrier_off(ieee->dev);
+ if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
+ rtllib_reset_queue(ieee);
+
+ if (ieee->data_hard_stop)
+ ieee->data_hard_stop(ieee->dev);
+ if (IS_DOT11D_ENABLE(ieee))
+ Dot11d_Reset(ieee);
+ ieee->state = RTLLIB_NOLINK;
+ ieee->is_set_key = false;
+ ieee->wap_set = 0;
+
+ queue_delayed_work_rsl(ieee->wq, &ieee->link_change_wq, 0);
+
+ notify_wx_assoc_event(ieee);
+}
+
+static void rtllib_associate_retry_wq(void *data)
+{
+ struct rtllib_device *ieee = container_of_dwork_rsl(data,
+ struct rtllib_device, associate_retry_wq);
+ unsigned long flags;
+
+ down(&ieee->wx_sem);
+ if (!ieee->proto_started)
+ goto exit;
+
+ if (ieee->state != RTLLIB_ASSOCIATING_RETRY)
+ goto exit;
+
+ /* until we do not set the state to RTLLIB_NOLINK
+ * there are no possibility to have someone else trying
+ * to start an association procedure (we get here with
+ * ieee->state = RTLLIB_ASSOCIATING).
+ * When we set the state to RTLLIB_NOLINK it is possible
+ * that the RX path run an attempt to associate, but
+ * both rtllib_softmac_check_all_nets and the
+ * RX path works with ieee->lock held so there are no
+ * problems. If we are still disassociated then start a scan.
+ * the lock here is necessary to ensure no one try to start
+ * an association procedure when we have just checked the
+ * state and we are going to start the scan.
+ */
+ ieee->beinretry = true;
+ ieee->state = RTLLIB_NOLINK;
+
+ rtllib_softmac_check_all_nets(ieee);
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ if (ieee->state == RTLLIB_NOLINK)
+ rtllib_start_scan(ieee);
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+ ieee->beinretry = false;
+exit:
+ up(&ieee->wx_sem);
+}
+
+struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee)
+{
+ u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ struct sk_buff *skb;
+ struct rtllib_probe_response *b;
+
+ skb = rtllib_probe_resp(ieee, broadcast_addr);
+
+ if (!skb)
+ return NULL;
+
+ b = (struct rtllib_probe_response *) skb->data;
+ b->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_BEACON);
+
+ return skb;
+
+}
+
+struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee)
+{
+ struct sk_buff *skb;
+ struct rtllib_probe_response *b;
+
+ skb = rtllib_get_beacon_(ieee);
+ if (!skb)
+ return NULL;
+
+ b = (struct rtllib_probe_response *) skb->data;
+ b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
+
+ if (ieee->seq_ctrl[0] == 0xFFF)
+ ieee->seq_ctrl[0] = 0;
+ else
+ ieee->seq_ctrl[0]++;
+
+ return skb;
+}
+EXPORT_SYMBOL(rtllib_get_beacon);
+
+void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag,
+ u8 shutdown)
+{
+ rtllib_stop_scan_syncro(ieee);
+ down(&ieee->wx_sem);
+ rtllib_stop_protocol(ieee, shutdown);
+ up(&ieee->wx_sem);
+}
+EXPORT_SYMBOL(rtllib_softmac_stop_protocol);
+
+
+void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown)
+{
+ if (!ieee->proto_started)
+ return;
+
+ if (shutdown) {
+ ieee->proto_started = 0;
+ ieee->proto_stoppping = 1;
+ if (ieee->rtllib_ips_leave != NULL)
+ ieee->rtllib_ips_leave(ieee->dev);
+ }
+
+ rtllib_stop_send_beacons(ieee);
+ del_timer_sync(&ieee->associate_timer);
+ cancel_delayed_work(&ieee->associate_retry_wq);
+ cancel_delayed_work(&ieee->start_ibss_wq);
+ cancel_delayed_work(&ieee->link_change_wq);
+ rtllib_stop_scan(ieee);
+
+ if (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED)
+ ieee->state = RTLLIB_NOLINK;
+
+ if (ieee->state == RTLLIB_LINKED) {
+ if (ieee->iw_mode == IW_MODE_INFRA)
+ SendDisassociation(ieee, 1, deauth_lv_ss);
+ rtllib_disassociate(ieee);
+ }
+
+ if (shutdown) {
+ RemoveAllTS(ieee);
+ ieee->proto_stoppping = 0;
+ }
+ kfree(ieee->assocreq_ies);
+ ieee->assocreq_ies = NULL;
+ ieee->assocreq_ies_len = 0;
+ kfree(ieee->assocresp_ies);
+ ieee->assocresp_ies = NULL;
+ ieee->assocresp_ies_len = 0;
+}
+
+void rtllib_softmac_start_protocol(struct rtllib_device *ieee, u8 mesh_flag)
+{
+ down(&ieee->wx_sem);
+ rtllib_start_protocol(ieee);
+ up(&ieee->wx_sem);
+}
+EXPORT_SYMBOL(rtllib_softmac_start_protocol);
+
+void rtllib_start_protocol(struct rtllib_device *ieee)
+{
+ short ch = 0;
+ int i = 0;
+
+ rtllib_update_active_chan_map(ieee);
+
+ if (ieee->proto_started)
+ return;
+
+ ieee->proto_started = 1;
+
+ if (ieee->current_network.channel == 0) {
+ do {
+ ch++;
+ if (ch > MAX_CHANNEL_NUMBER)
+ return; /* no channel found */
+ } while (!ieee->active_channel_map[ch]);
+ ieee->current_network.channel = ch;
+ }
+
+ if (ieee->current_network.beacon_interval == 0)
+ ieee->current_network.beacon_interval = 100;
+
+ for (i = 0; i < 17; i++) {
+ ieee->last_rxseq_num[i] = -1;
+ ieee->last_rxfrag_num[i] = -1;
+ ieee->last_packet_time[i] = 0;
+ }
+
+ if (ieee->UpdateBeaconInterruptHandler)
+ ieee->UpdateBeaconInterruptHandler(ieee->dev, false);
+
+ ieee->wmm_acm = 0;
+ /* if the user set the MAC of the ad-hoc cell and then
+ * switch to managed mode, shall we make sure that association
+ * attempts does not fail just because the user provide the essid
+ * and the nic is still checking for the AP MAC ??
+ */
+ if (ieee->iw_mode == IW_MODE_INFRA) {
+ rtllib_start_bss(ieee);
+ } else if (ieee->iw_mode == IW_MODE_ADHOC) {
+ if (ieee->UpdateBeaconInterruptHandler)
+ ieee->UpdateBeaconInterruptHandler(ieee->dev, true);
+
+ rtllib_start_ibss(ieee);
+
+ } else if (ieee->iw_mode == IW_MODE_MASTER) {
+ rtllib_start_master_bss(ieee);
+ } else if (ieee->iw_mode == IW_MODE_MONITOR) {
+ rtllib_start_monitor_mode(ieee);
+ }
+}
+
+void rtllib_softmac_init(struct rtllib_device *ieee)
+{
+ int i;
+
+ memset(&ieee->current_network, 0, sizeof(struct rtllib_network));
+
+ ieee->state = RTLLIB_NOLINK;
+ for (i = 0; i < 5; i++)
+ ieee->seq_ctrl[i] = 0;
+ ieee->pDot11dInfo = kzalloc(sizeof(struct rt_dot11d_info), GFP_ATOMIC);
+ if (!ieee->pDot11dInfo)
+ RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc memory for DOT11D\n");
+ ieee->LinkDetectInfo.SlotIndex = 0;
+ ieee->LinkDetectInfo.SlotNum = 2;
+ ieee->LinkDetectInfo.NumRecvBcnInPeriod = 0;
+ ieee->LinkDetectInfo.NumRecvDataInPeriod = 0;
+ ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
+ ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
+ ieee->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
+ ieee->bIsAggregateFrame = false;
+ ieee->assoc_id = 0;
+ ieee->queue_stop = 0;
+ ieee->scanning_continue = 0;
+ ieee->softmac_features = 0;
+ ieee->wap_set = 0;
+ ieee->ssid_set = 0;
+ ieee->proto_started = 0;
+ ieee->proto_stoppping = 0;
+ ieee->basic_rate = RTLLIB_DEFAULT_BASIC_RATE;
+ ieee->rate = 22;
+ ieee->ps = RTLLIB_PS_DISABLED;
+ ieee->sta_sleep = LPS_IS_WAKE;
+
+ ieee->Regdot11HTOperationalRateSet[0] = 0xff;
+ ieee->Regdot11HTOperationalRateSet[1] = 0xff;
+ ieee->Regdot11HTOperationalRateSet[4] = 0x01;
+
+ ieee->Regdot11TxHTOperationalRateSet[0] = 0xff;
+ ieee->Regdot11TxHTOperationalRateSet[1] = 0xff;
+ ieee->Regdot11TxHTOperationalRateSet[4] = 0x01;
+
+ ieee->FirstIe_InScan = false;
+ ieee->actscanning = false;
+ ieee->beinretry = false;
+ ieee->is_set_key = false;
+ init_mgmt_queue(ieee);
+
+ ieee->sta_edca_param[0] = 0x0000A403;
+ ieee->sta_edca_param[1] = 0x0000A427;
+ ieee->sta_edca_param[2] = 0x005E4342;
+ ieee->sta_edca_param[3] = 0x002F3262;
+ ieee->aggregation = true;
+ ieee->enable_rx_imm_BA = true;
+ ieee->tx_pending.txb = NULL;
+
+ _setup_timer(&ieee->associate_timer,
+ rtllib_associate_abort_cb,
+ (unsigned long) ieee);
+
+ _setup_timer(&ieee->beacon_timer,
+ rtllib_send_beacon_cb,
+ (unsigned long) ieee);
+
+
+ ieee->wq = create_workqueue(DRV_NAME);
+
+ INIT_DELAYED_WORK_RSL(&ieee->link_change_wq,
+ (void *)rtllib_link_change_wq, ieee);
+ INIT_DELAYED_WORK_RSL(&ieee->start_ibss_wq,
+ (void *)rtllib_start_ibss_wq, ieee);
+ INIT_WORK_RSL(&ieee->associate_complete_wq,
+ (void *)rtllib_associate_complete_wq, ieee);
+ INIT_DELAYED_WORK_RSL(&ieee->associate_procedure_wq,
+ (void *)rtllib_associate_procedure_wq, ieee);
+ INIT_DELAYED_WORK_RSL(&ieee->softmac_scan_wq,
+ (void *)rtllib_softmac_scan_wq, ieee);
+ INIT_DELAYED_WORK_RSL(&ieee->softmac_hint11d_wq,
+ (void *)rtllib_softmac_hint11d_wq, ieee);
+ INIT_DELAYED_WORK_RSL(&ieee->associate_retry_wq,
+ (void *)rtllib_associate_retry_wq, ieee);
+ INIT_WORK_RSL(&ieee->wx_sync_scan_wq, (void *)rtllib_wx_sync_scan_wq,
+ ieee);
+
+ sema_init(&ieee->wx_sem, 1);
+ sema_init(&ieee->scan_sem, 1);
+ sema_init(&ieee->ips_sem, 1);
+
+ spin_lock_init(&ieee->mgmt_tx_lock);
+ spin_lock_init(&ieee->beacon_lock);
+
+ tasklet_init(&ieee->ps_task,
+ (void(*)(unsigned long)) rtllib_sta_ps,
+ (unsigned long)ieee);
+
+}
+
+void rtllib_softmac_free(struct rtllib_device *ieee)
+{
+ down(&ieee->wx_sem);
+ kfree(ieee->pDot11dInfo);
+ ieee->pDot11dInfo = NULL;
+ del_timer_sync(&ieee->associate_timer);
+
+ cancel_delayed_work(&ieee->associate_retry_wq);
+ destroy_workqueue(ieee->wq);
+ up(&ieee->wx_sem);
+ tasklet_kill(&ieee->ps_task);
+}
+
+/********************************************************
+ * Start of WPA code. *
+ * this is stolen from the ipw2200 driver *
+ ********************************************************/
+
+
+static int rtllib_wpa_enable(struct rtllib_device *ieee, int value)
+{
+ /* This is called when wpa_supplicant loads and closes the driver
+ * interface.
+ */
+ netdev_info(ieee->dev, "%s WPA\n", value ? "enabling" : "disabling");
+ ieee->wpa_enabled = value;
+ memset(ieee->ap_mac_addr, 0, 6);
+ return 0;
+}
+
+
+static void rtllib_wpa_assoc_frame(struct rtllib_device *ieee, char *wpa_ie,
+ int wpa_ie_len)
+{
+ /* make sure WPA is enabled */
+ rtllib_wpa_enable(ieee, 1);
+
+ rtllib_disassociate(ieee);
+}
+
+
+static int rtllib_wpa_mlme(struct rtllib_device *ieee, int command, int reason)
+{
+
+ int ret = 0;
+
+ switch (command) {
+ case IEEE_MLME_STA_DEAUTH:
+ break;
+
+ case IEEE_MLME_STA_DISASSOC:
+ rtllib_disassociate(ieee);
+ break;
+
+ default:
+ netdev_info(ieee->dev, "Unknown MLME request: %d\n", command);
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+
+static int rtllib_wpa_set_wpa_ie(struct rtllib_device *ieee,
+ struct ieee_param *param, int plen)
+{
+ u8 *buf;
+
+ if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
+ (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
+ return -EINVAL;
+
+ if (param->u.wpa_ie.len) {
+ buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
+ GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ kfree(ieee->wpa_ie);
+ ieee->wpa_ie = buf;
+ ieee->wpa_ie_len = param->u.wpa_ie.len;
+ } else {
+ kfree(ieee->wpa_ie);
+ ieee->wpa_ie = NULL;
+ ieee->wpa_ie_len = 0;
+ }
+
+ rtllib_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
+ return 0;
+}
+
+#define AUTH_ALG_OPEN_SYSTEM 0x1
+#define AUTH_ALG_SHARED_KEY 0x2
+#define AUTH_ALG_LEAP 0x4
+static int rtllib_wpa_set_auth_algs(struct rtllib_device *ieee, int value)
+{
+
+ struct rtllib_security sec = {
+ .flags = SEC_AUTH_MODE,
+ };
+
+ if (value & AUTH_ALG_SHARED_KEY) {
+ sec.auth_mode = WLAN_AUTH_SHARED_KEY;
+ ieee->open_wep = 0;
+ ieee->auth_mode = 1;
+ } else if (value & AUTH_ALG_OPEN_SYSTEM) {
+ sec.auth_mode = WLAN_AUTH_OPEN;
+ ieee->open_wep = 1;
+ ieee->auth_mode = 0;
+ } else if (value & AUTH_ALG_LEAP) {
+ sec.auth_mode = WLAN_AUTH_LEAP >> 6;
+ ieee->open_wep = 1;
+ ieee->auth_mode = 2;
+ }
+
+
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+
+ return 0;
+}
+
+static int rtllib_wpa_set_param(struct rtllib_device *ieee, u8 name, u32 value)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ switch (name) {
+ case IEEE_PARAM_WPA_ENABLED:
+ ret = rtllib_wpa_enable(ieee, value);
+ break;
+
+ case IEEE_PARAM_TKIP_COUNTERMEASURES:
+ ieee->tkip_countermeasures = value;
+ break;
+
+ case IEEE_PARAM_DROP_UNENCRYPTED:
+ {
+ /* HACK:
+ *
+ * wpa_supplicant calls set_wpa_enabled when the driver
+ * is loaded and unloaded, regardless of if WPA is being
+ * used. No other calls are made which can be used to
+ * determine if encryption will be used or not prior to
+ * association being expected. If encryption is not being
+ * used, drop_unencrypted is set to false, else true -- we
+ * can use this to determine if the CAP_PRIVACY_ON bit should
+ * be set.
+ */
+ struct rtllib_security sec = {
+ .flags = SEC_ENABLED,
+ .enabled = value,
+ };
+ ieee->drop_unencrypted = value;
+ /* We only change SEC_LEVEL for open mode. Others
+ * are set by ipw_wpa_set_encryption.
+ */
+ if (!value) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_0;
+ } else {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_1;
+ }
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+ break;
+ }
+
+ case IEEE_PARAM_PRIVACY_INVOKED:
+ ieee->privacy_invoked = value;
+ break;
+
+ case IEEE_PARAM_AUTH_ALGS:
+ ret = rtllib_wpa_set_auth_algs(ieee, value);
+ break;
+
+ case IEEE_PARAM_IEEE_802_1X:
+ ieee->ieee802_1x = value;
+ break;
+ case IEEE_PARAM_WPAX_SELECT:
+ spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
+ spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
+ break;
+
+ default:
+ netdev_info(ieee->dev, "Unknown WPA param: %d\n", name);
+ ret = -EOPNOTSUPP;
+ }
+
+ return ret;
+}
+
+/* implementation borrowed from hostap driver */
+static int rtllib_wpa_set_encryption(struct rtllib_device *ieee,
+ struct ieee_param *param, int param_len,
+ u8 is_mesh)
+{
+ int ret = 0;
+ struct lib80211_crypto_ops *ops;
+ struct lib80211_crypt_data **crypt;
+
+ struct rtllib_security sec = {
+ .flags = 0,
+ };
+
+ param->u.crypt.err = 0;
+ param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
+
+ if (param_len !=
+ (int) ((char *) param->u.crypt.key - (char *) param) +
+ param->u.crypt.key_len) {
+ netdev_info(ieee->dev, "Len mismatch %d, %d\n", param_len,
+ param->u.crypt.key_len);
+ return -EINVAL;
+ }
+ if (is_broadcast_ether_addr(param->sta_addr)) {
+ if (param->u.crypt.idx >= NUM_WEP_KEYS)
+ return -EINVAL;
+ crypt = &ieee->crypt_info.crypt[param->u.crypt.idx];
+ } else {
+ return -EINVAL;
+ }
+
+ if (strcmp(param->u.crypt.alg, "none") == 0) {
+ if (crypt) {
+ sec.enabled = 0;
+ sec.level = SEC_LEVEL_0;
+ sec.flags |= SEC_ENABLED | SEC_LEVEL;
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+ }
+ goto done;
+ }
+ sec.enabled = 1;
+ sec.flags |= SEC_ENABLED;
+
+ /* IPW HW cannot build TKIP MIC, host decryption still needed. */
+ if (!(ieee->host_encrypt || ieee->host_decrypt) &&
+ strcmp(param->u.crypt.alg, "R-TKIP"))
+ goto skip_host_crypt;
+
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
+ if (ops == NULL && strcmp(param->u.crypt.alg, "R-WEP") == 0) {
+ request_module("rtllib_crypt_wep");
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "R-TKIP") == 0) {
+ request_module("rtllib_crypt_tkip");
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
+ } else if (ops == NULL && strcmp(param->u.crypt.alg, "R-CCMP") == 0) {
+ request_module("rtllib_crypt_ccmp");
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
+ }
+ if (ops == NULL) {
+ netdev_info(ieee->dev, "unknown crypto alg '%s'\n",
+ param->u.crypt.alg);
+ param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
+ ret = -EINVAL;
+ goto done;
+ }
+ if (*crypt == NULL || (*crypt)->ops != ops) {
+ struct lib80211_crypt_data *new_crypt;
+
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+
+ new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
+ if (new_crypt == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ new_crypt->ops = ops;
+ if (new_crypt->ops)
+ new_crypt->priv =
+ new_crypt->ops->init(param->u.crypt.idx);
+
+ if (new_crypt->priv == NULL) {
+ kfree(new_crypt);
+ param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ *crypt = new_crypt;
+ }
+
+ if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
+ (*crypt)->ops->set_key(param->u.crypt.key,
+ param->u.crypt.key_len, param->u.crypt.seq,
+ (*crypt)->priv) < 0) {
+ netdev_info(ieee->dev, "key setting failed\n");
+ param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
+ ret = -EINVAL;
+ goto done;
+ }
+
+ skip_host_crypt:
+ if (param->u.crypt.set_tx) {
+ ieee->crypt_info.tx_keyidx = param->u.crypt.idx;
+ sec.active_key = param->u.crypt.idx;
+ sec.flags |= SEC_ACTIVE_KEY;
+ } else
+ sec.flags &= ~SEC_ACTIVE_KEY;
+
+ if (param->u.crypt.alg != NULL) {
+ memcpy(sec.keys[param->u.crypt.idx],
+ param->u.crypt.key,
+ param->u.crypt.key_len);
+ sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
+ sec.flags |= (1 << param->u.crypt.idx);
+
+ if (strcmp(param->u.crypt.alg, "R-WEP") == 0) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_1;
+ } else if (strcmp(param->u.crypt.alg, "R-TKIP") == 0) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_2;
+ } else if (strcmp(param->u.crypt.alg, "R-CCMP") == 0) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_3;
+ }
+ }
+ done:
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+
+ /* Do not reset port if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. If your hardware requires a reset after WEP
+ * configuration (for example... Prism2), implement the reset_port in
+ * the callbacks structures used to initialize the 802.11 stack.
+ */
+ if (ieee->reset_on_keychange &&
+ ieee->iw_mode != IW_MODE_INFRA &&
+ ieee->reset_port &&
+ ieee->reset_port(ieee->dev)) {
+ netdev_info(ieee->dev, "reset_port failed\n");
+ param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+inline struct sk_buff *rtllib_disauth_skb(struct rtllib_network *beacon,
+ struct rtllib_device *ieee, u16 asRsn)
+{
+ struct sk_buff *skb;
+ struct rtllib_disauth *disauth;
+ int len = sizeof(struct rtllib_disauth) + ieee->tx_headroom;
+
+ skb = dev_alloc_skb(len);
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ disauth = (struct rtllib_disauth *) skb_put(skb,
+ sizeof(struct rtllib_disauth));
+ disauth->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_DEAUTH);
+ disauth->header.duration_id = 0;
+
+ memcpy(disauth->header.addr1, beacon->bssid, ETH_ALEN);
+ memcpy(disauth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+ memcpy(disauth->header.addr3, beacon->bssid, ETH_ALEN);
+
+ disauth->reason = cpu_to_le16(asRsn);
+ return skb;
+}
+
+inline struct sk_buff *rtllib_disassociate_skb(struct rtllib_network *beacon,
+ struct rtllib_device *ieee, u16 asRsn)
+{
+ struct sk_buff *skb;
+ struct rtllib_disassoc *disass;
+ int len = sizeof(struct rtllib_disassoc) + ieee->tx_headroom;
+
+ skb = dev_alloc_skb(len);
+
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, ieee->tx_headroom);
+
+ disass = (struct rtllib_disassoc *) skb_put(skb,
+ sizeof(struct rtllib_disassoc));
+ disass->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_DISASSOC);
+ disass->header.duration_id = 0;
+
+ memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
+ memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
+ memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
+
+ disass->reason = cpu_to_le16(asRsn);
+ return skb;
+}
+
+void SendDisassociation(struct rtllib_device *ieee, bool deauth, u16 asRsn)
+{
+ struct rtllib_network *beacon = &ieee->current_network;
+ struct sk_buff *skb;
+
+ if (deauth)
+ skb = rtllib_disauth_skb(beacon, ieee, asRsn);
+ else
+ skb = rtllib_disassociate_skb(beacon, ieee, asRsn);
+
+ if (skb)
+ softmac_mgmt_xmit(skb, ieee);
+}
+
+u8 rtllib_ap_sec_type(struct rtllib_device *ieee)
+{
+ static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04};
+ static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
+ int wpa_ie_len = ieee->wpa_ie_len;
+ struct lib80211_crypt_data *crypt;
+ int encrypt;
+
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
+ encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY)
+ || (ieee->host_encrypt && crypt && crypt->ops &&
+ (0 == strcmp(crypt->ops->name, "R-WEP")));
+
+ /* simply judge */
+ if (encrypt && (wpa_ie_len == 0)) {
+ return SEC_ALG_WEP;
+ } else if ((wpa_ie_len != 0)) {
+ if (((ieee->wpa_ie[0] == 0xdd) &&
+ (!memcmp(&(ieee->wpa_ie[14]), ccmp_ie, 4))) ||
+ ((ieee->wpa_ie[0] == 0x30) &&
+ (!memcmp(&ieee->wpa_ie[10], ccmp_rsn_ie, 4))))
+ return SEC_ALG_CCMP;
+ else
+ return SEC_ALG_TKIP;
+ } else {
+ return SEC_ALG_NONE;
+ }
+}
+
+int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p,
+ u8 is_mesh)
+{
+ struct ieee_param *param;
+ int ret = 0;
+
+ down(&ieee->wx_sem);
+
+ if (p->length < sizeof(struct ieee_param) || !p->pointer) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ param = memdup_user(p->pointer, p->length);
+ if (IS_ERR(param)) {
+ ret = PTR_ERR(param);
+ goto out;
+ }
+
+ switch (param->cmd) {
+ case IEEE_CMD_SET_WPA_PARAM:
+ ret = rtllib_wpa_set_param(ieee, param->u.wpa_param.name,
+ param->u.wpa_param.value);
+ break;
+
+ case IEEE_CMD_SET_WPA_IE:
+ ret = rtllib_wpa_set_wpa_ie(ieee, param, p->length);
+ break;
+
+ case IEEE_CMD_SET_ENCRYPTION:
+ ret = rtllib_wpa_set_encryption(ieee, param, p->length, 0);
+ break;
+
+ case IEEE_CMD_MLME:
+ ret = rtllib_wpa_mlme(ieee, param->u.mlme.command,
+ param->u.mlme.reason_code);
+ break;
+
+ default:
+ netdev_info(ieee->dev, "Unknown WPA supplicant request: %d\n",
+ param->cmd);
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ if (ret == 0 && copy_to_user(p->pointer, param, p->length))
+ ret = -EFAULT;
+
+ kfree(param);
+out:
+ up(&ieee->wx_sem);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtllib_wpa_supplicant_ioctl);
+
+static void rtllib_MgntDisconnectIBSS(struct rtllib_device *rtllib)
+{
+ u8 OpMode;
+ u8 i;
+ bool bFilterOutNonAssociatedBSSID = false;
+
+ rtllib->state = RTLLIB_NOLINK;
+
+ for (i = 0; i < 6; i++)
+ rtllib->current_network.bssid[i] = 0x55;
+
+ rtllib->OpMode = RT_OP_MODE_NO_LINK;
+ rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_BSSID,
+ rtllib->current_network.bssid);
+ OpMode = RT_OP_MODE_NO_LINK;
+ rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_MEDIA_STATUS, &OpMode);
+ rtllib_stop_send_beacons(rtllib);
+
+ bFilterOutNonAssociatedBSSID = false;
+ rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_CECHK_BSSID,
+ (u8 *)(&bFilterOutNonAssociatedBSSID));
+ notify_wx_assoc_event(rtllib);
+
+}
+
+static void rtllib_MlmeDisassociateRequest(struct rtllib_device *rtllib, u8 *asSta,
+ u8 asRsn)
+{
+ u8 i;
+ u8 OpMode;
+
+ RemovePeerTS(rtllib, asSta);
+
+ if (memcmp(rtllib->current_network.bssid, asSta, 6) == 0) {
+ rtllib->state = RTLLIB_NOLINK;
+
+ for (i = 0; i < 6; i++)
+ rtllib->current_network.bssid[i] = 0x22;
+ OpMode = RT_OP_MODE_NO_LINK;
+ rtllib->OpMode = RT_OP_MODE_NO_LINK;
+ rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_MEDIA_STATUS,
+ (u8 *)(&OpMode));
+ rtllib_disassociate(rtllib);
+
+ rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_BSSID,
+ rtllib->current_network.bssid);
+
+ }
+
+}
+
+static void
+rtllib_MgntDisconnectAP(
+ struct rtllib_device *rtllib,
+ u8 asRsn
+)
+{
+ bool bFilterOutNonAssociatedBSSID = false;
+
+ bFilterOutNonAssociatedBSSID = false;
+ rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_CECHK_BSSID,
+ (u8 *)(&bFilterOutNonAssociatedBSSID));
+ rtllib_MlmeDisassociateRequest(rtllib, rtllib->current_network.bssid,
+ asRsn);
+
+ rtllib->state = RTLLIB_NOLINK;
+}
+
+bool rtllib_MgntDisconnect(struct rtllib_device *rtllib, u8 asRsn)
+{
+ if (rtllib->ps != RTLLIB_PS_DISABLED)
+ rtllib->sta_wake_up(rtllib->dev);
+
+ if (rtllib->state == RTLLIB_LINKED) {
+ if (rtllib->iw_mode == IW_MODE_ADHOC)
+ rtllib_MgntDisconnectIBSS(rtllib);
+ if (rtllib->iw_mode == IW_MODE_INFRA)
+ rtllib_MgntDisconnectAP(rtllib, asRsn);
+
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(rtllib_MgntDisconnect);
+
+void notify_wx_assoc_event(struct rtllib_device *ieee)
+{
+ union iwreq_data wrqu;
+
+ if (ieee->cannot_notify)
+ return;
+
+ wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+ if (ieee->state == RTLLIB_LINKED)
+ memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid,
+ ETH_ALEN);
+ else {
+
+ netdev_info(ieee->dev, "%s(): Tell user space disconnected\n",
+ __func__);
+ eth_zero_addr(wrqu.ap_addr.sa_data);
+ }
+ wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
+}
+EXPORT_SYMBOL(notify_wx_assoc_event);
diff --git a/drivers/staging/rtl8192e/rtllib_softmac_wx.c b/drivers/staging/rtl8192e/rtllib_softmac_wx.c
new file mode 100644
index 000000000..9715a793f
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_softmac_wx.c
@@ -0,0 +1,661 @@
+/* IEEE 802.11 SoftMAC layer
+ * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
+ *
+ * Mostly extracted from the rtl8180-sa2400 driver for the
+ * in-kernel generic ieee802.11 stack.
+ *
+ * Some pieces of code might be stolen from ipw2100 driver
+ * copyright of who own it's copyright ;-)
+ *
+ * PS wx handler mostly stolen from hostap, copyright who
+ * own it's copyright ;-)
+ *
+ * released under the GPL
+ */
+
+
+#include <linux/etherdevice.h>
+
+#include "rtllib.h"
+#include "dot11d.h"
+/* FIXME: add A freqs */
+
+const long rtllib_wlan_frequencies[] = {
+ 2412, 2417, 2422, 2427,
+ 2432, 2437, 2442, 2447,
+ 2452, 2457, 2462, 2467,
+ 2472, 2484
+};
+EXPORT_SYMBOL(rtllib_wlan_frequencies);
+
+
+int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ int ret;
+ struct iw_freq *fwrq = &wrqu->freq;
+
+ down(&ieee->wx_sem);
+
+ if (ieee->iw_mode == IW_MODE_INFRA) {
+ ret = 0;
+ goto out;
+ }
+
+ /* if setting by freq convert to channel */
+ if (fwrq->e == 1) {
+ if ((fwrq->m >= (int) 2.412e8 &&
+ fwrq->m <= (int) 2.487e8)) {
+ int f = fwrq->m / 100000;
+ int c = 0;
+
+ while ((c < 14) && (f != rtllib_wlan_frequencies[c]))
+ c++;
+
+ /* hack to fall through */
+ fwrq->e = 0;
+ fwrq->m = c + 1;
+ }
+ }
+
+ if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) {
+ ret = -EOPNOTSUPP;
+ goto out;
+
+ } else { /* Set the channel */
+
+ if (ieee->active_channel_map[fwrq->m] != 1) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ieee->current_network.channel = fwrq->m;
+ ieee->set_chan(ieee->dev, ieee->current_network.channel);
+
+ if (ieee->iw_mode == IW_MODE_ADHOC ||
+ ieee->iw_mode == IW_MODE_MASTER)
+ if (ieee->state == RTLLIB_LINKED) {
+ rtllib_stop_send_beacons(ieee);
+ rtllib_start_send_beacons(ieee);
+ }
+ }
+
+ ret = 0;
+out:
+ up(&ieee->wx_sem);
+ return ret;
+}
+EXPORT_SYMBOL(rtllib_wx_set_freq);
+
+
+int rtllib_wx_get_freq(struct rtllib_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ struct iw_freq *fwrq = &wrqu->freq;
+
+ if (ieee->current_network.channel == 0)
+ return -1;
+ fwrq->m = rtllib_wlan_frequencies[ieee->current_network.channel-1] *
+ 100000;
+ fwrq->e = 1;
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_get_freq);
+
+int rtllib_wx_get_wap(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ unsigned long flags;
+
+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
+
+ if (ieee->iw_mode == IW_MODE_MONITOR)
+ return -1;
+
+ /* We want avoid to give to the user inconsistent infos*/
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ if (ieee->state != RTLLIB_LINKED &&
+ ieee->state != RTLLIB_LINKED_SCANNING &&
+ ieee->wap_set == 0)
+
+ eth_zero_addr(wrqu->ap_addr.sa_data);
+ else
+ memcpy(wrqu->ap_addr.sa_data,
+ ieee->current_network.bssid, ETH_ALEN);
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_get_wap);
+
+
+int rtllib_wx_set_wap(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *awrq,
+ char *extra)
+{
+
+ int ret = 0;
+ unsigned long flags;
+
+ short ifup = ieee->proto_started;
+ struct sockaddr *temp = (struct sockaddr *)awrq;
+
+ rtllib_stop_scan_syncro(ieee);
+
+ down(&ieee->wx_sem);
+ /* use ifconfig hw ether */
+ if (ieee->iw_mode == IW_MODE_MASTER) {
+ ret = -1;
+ goto out;
+ }
+
+ if (temp->sa_family != ARPHRD_ETHER) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (is_zero_ether_addr(temp->sa_data)) {
+ spin_lock_irqsave(&ieee->lock, flags);
+ memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
+ ieee->wap_set = 0;
+ spin_unlock_irqrestore(&ieee->lock, flags);
+ ret = -1;
+ goto out;
+ }
+
+
+ if (ifup)
+ rtllib_stop_protocol(ieee, true);
+
+ /* just to avoid to give inconsistent infos in the
+ * get wx method. not really needed otherwise
+ */
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ ieee->cannot_notify = false;
+ memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
+ ieee->wap_set = !is_zero_ether_addr(temp->sa_data);
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+ if (ifup)
+ rtllib_start_protocol(ieee);
+out:
+ up(&ieee->wx_sem);
+ return ret;
+}
+EXPORT_SYMBOL(rtllib_wx_set_wap);
+
+int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ int len, ret = 0;
+ unsigned long flags;
+
+ if (ieee->iw_mode == IW_MODE_MONITOR)
+ return -1;
+
+ /* We want avoid to give to the user inconsistent infos*/
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ if (ieee->current_network.ssid[0] == '\0' ||
+ ieee->current_network.ssid_len == 0) {
+ ret = -1;
+ goto out;
+ }
+
+ if (ieee->state != RTLLIB_LINKED &&
+ ieee->state != RTLLIB_LINKED_SCANNING &&
+ ieee->ssid_set == 0) {
+ ret = -1;
+ goto out;
+ }
+ len = ieee->current_network.ssid_len;
+ wrqu->essid.length = len;
+ strncpy(b, ieee->current_network.ssid, len);
+ wrqu->essid.flags = 1;
+
+out:
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+ return ret;
+
+}
+EXPORT_SYMBOL(rtllib_wx_get_essid);
+
+int rtllib_wx_set_rate(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ u32 target_rate = wrqu->bitrate.value;
+
+ ieee->rate = target_rate/100000;
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_set_rate);
+
+int rtllib_wx_get_rate(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ u32 tmp_rate = 0;
+
+ tmp_rate = TxCountToDataRate(ieee,
+ ieee->softmac_stats.CurrentShowTxate);
+ wrqu->bitrate.value = tmp_rate * 500000;
+
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_get_rate);
+
+
+int rtllib_wx_set_rts(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ if (wrqu->rts.disabled || !wrqu->rts.fixed)
+ ieee->rts = DEFAULT_RTS_THRESHOLD;
+ else {
+ if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
+ wrqu->rts.value > MAX_RTS_THRESHOLD)
+ return -EINVAL;
+ ieee->rts = wrqu->rts.value;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_set_rts);
+
+int rtllib_wx_get_rts(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ wrqu->rts.value = ieee->rts;
+ wrqu->rts.fixed = 0; /* no auto select */
+ wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_get_rts);
+
+int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ int set_mode_status = 0;
+
+ rtllib_stop_scan_syncro(ieee);
+ down(&ieee->wx_sem);
+ switch (wrqu->mode) {
+ case IW_MODE_MONITOR:
+ case IW_MODE_ADHOC:
+ case IW_MODE_INFRA:
+ break;
+ case IW_MODE_AUTO:
+ wrqu->mode = IW_MODE_INFRA;
+ break;
+ default:
+ set_mode_status = -EINVAL;
+ goto out;
+ }
+
+ if (wrqu->mode == ieee->iw_mode)
+ goto out;
+
+ if (wrqu->mode == IW_MODE_MONITOR) {
+ ieee->dev->type = ARPHRD_IEEE80211;
+ rtllib_EnableNetMonitorMode(ieee->dev, false);
+ } else {
+ ieee->dev->type = ARPHRD_ETHER;
+ if (ieee->iw_mode == IW_MODE_MONITOR)
+ rtllib_DisableNetMonitorMode(ieee->dev, false);
+ }
+
+ if (!ieee->proto_started) {
+ ieee->iw_mode = wrqu->mode;
+ } else {
+ rtllib_stop_protocol(ieee, true);
+ ieee->iw_mode = wrqu->mode;
+ rtllib_start_protocol(ieee);
+ }
+
+out:
+ up(&ieee->wx_sem);
+ return set_mode_status;
+}
+EXPORT_SYMBOL(rtllib_wx_set_mode);
+
+void rtllib_wx_sync_scan_wq(void *data)
+{
+ struct rtllib_device *ieee = container_of_work_rsl(data,
+ struct rtllib_device, wx_sync_scan_wq);
+ short chan;
+ enum ht_extchnl_offset chan_offset = 0;
+ enum ht_channel_width bandwidth = 0;
+ int b40M = 0;
+
+ if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)) {
+ rtllib_start_scan_syncro(ieee, 0);
+ goto out;
+ }
+
+ chan = ieee->current_network.channel;
+
+ if (ieee->LeisurePSLeave)
+ ieee->LeisurePSLeave(ieee->dev);
+ /* notify AP to be in PS mode */
+ rtllib_sta_ps_send_null_frame(ieee, 1);
+ rtllib_sta_ps_send_null_frame(ieee, 1);
+
+ rtllib_stop_all_queues(ieee);
+
+ if (ieee->data_hard_stop)
+ ieee->data_hard_stop(ieee->dev);
+ rtllib_stop_send_beacons(ieee);
+ ieee->state = RTLLIB_LINKED_SCANNING;
+ ieee->link_change(ieee->dev);
+ /* wait for ps packet to be kicked out successfully */
+ msleep(50);
+
+ if (ieee->ScanOperationBackupHandler)
+ ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_BACKUP);
+
+ if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT &&
+ ieee->pHTInfo->bCurBW40MHz) {
+ b40M = 1;
+ chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
+ bandwidth = (enum ht_channel_width)ieee->pHTInfo->bCurBW40MHz;
+ RT_TRACE(COMP_DBG, "Scan in 40M, force to 20M first:%d, %d\n",
+ chan_offset, bandwidth);
+ ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20,
+ HT_EXTCHNL_OFFSET_NO_EXT);
+ }
+
+ rtllib_start_scan_syncro(ieee, 0);
+
+ if (b40M) {
+ RT_TRACE(COMP_DBG, "Scan in 20M, back to 40M\n");
+ if (chan_offset == HT_EXTCHNL_OFFSET_UPPER)
+ ieee->set_chan(ieee->dev, chan + 2);
+ else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER)
+ ieee->set_chan(ieee->dev, chan - 2);
+ else
+ ieee->set_chan(ieee->dev, chan);
+ ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset);
+ } else {
+ ieee->set_chan(ieee->dev, chan);
+ }
+
+ if (ieee->ScanOperationBackupHandler)
+ ieee->ScanOperationBackupHandler(ieee->dev, SCAN_OPT_RESTORE);
+
+ ieee->state = RTLLIB_LINKED;
+ ieee->link_change(ieee->dev);
+
+ /* Notify AP that I wake up again */
+ rtllib_sta_ps_send_null_frame(ieee, 0);
+
+ if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 ||
+ ieee->LinkDetectInfo.NumRecvDataInPeriod == 0) {
+ ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
+ ieee->LinkDetectInfo.NumRecvDataInPeriod = 1;
+ }
+
+ if (ieee->data_hard_resume)
+ ieee->data_hard_resume(ieee->dev);
+
+ if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
+ rtllib_start_send_beacons(ieee);
+
+ rtllib_wake_all_queues(ieee);
+
+out:
+ up(&ieee->wx_sem);
+
+}
+
+int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ int ret = 0;
+
+ down(&ieee->wx_sem);
+
+ if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) {
+ ret = -1;
+ goto out;
+ }
+
+ if (ieee->state == RTLLIB_LINKED) {
+ queue_work_rsl(ieee->wq, &ieee->wx_sync_scan_wq);
+ /* intentionally forget to up sem */
+ return 0;
+ }
+
+out:
+ up(&ieee->wx_sem);
+ return ret;
+}
+EXPORT_SYMBOL(rtllib_wx_set_scan);
+
+int rtllib_wx_set_essid(struct rtllib_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ int ret = 0, len, i;
+ short proto_started;
+ unsigned long flags;
+
+ rtllib_stop_scan_syncro(ieee);
+ down(&ieee->wx_sem);
+
+ proto_started = ieee->proto_started;
+
+ len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length :
+ IW_ESSID_MAX_SIZE;
+
+ if (len > IW_ESSID_MAX_SIZE) {
+ ret = -E2BIG;
+ goto out;
+ }
+
+ if (ieee->iw_mode == IW_MODE_MONITOR) {
+ ret = -1;
+ goto out;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (extra[i] < 0) {
+ ret = -1;
+ goto out;
+ }
+ }
+
+ if (proto_started)
+ rtllib_stop_protocol(ieee, true);
+
+
+ /* this is just to be sure that the GET wx callback
+ * has consistent infos. not needed otherwise
+ */
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ if (wrqu->essid.flags && wrqu->essid.length) {
+ strncpy(ieee->current_network.ssid, extra, len);
+ ieee->current_network.ssid_len = len;
+ ieee->cannot_notify = false;
+ ieee->ssid_set = 1;
+ } else {
+ ieee->ssid_set = 0;
+ ieee->current_network.ssid[0] = '\0';
+ ieee->current_network.ssid_len = 0;
+ }
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+ if (proto_started)
+ rtllib_start_protocol(ieee);
+out:
+ up(&ieee->wx_sem);
+ return ret;
+}
+EXPORT_SYMBOL(rtllib_wx_set_essid);
+
+int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b)
+{
+ wrqu->mode = ieee->iw_mode;
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_get_mode);
+
+int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+
+ int *parms = (int *)extra;
+ int enable = (parms[0] > 0);
+ short prev = ieee->raw_tx;
+
+ down(&ieee->wx_sem);
+
+ if (enable)
+ ieee->raw_tx = 1;
+ else
+ ieee->raw_tx = 0;
+
+ netdev_info(ieee->dev, "raw TX is %s\n",
+ ieee->raw_tx ? "enabled" : "disabled");
+
+ if (ieee->iw_mode == IW_MODE_MONITOR) {
+ if (prev == 0 && ieee->raw_tx) {
+ if (ieee->data_hard_resume)
+ ieee->data_hard_resume(ieee->dev);
+
+ netif_carrier_on(ieee->dev);
+ }
+
+ if (prev && ieee->raw_tx == 1)
+ netif_carrier_off(ieee->dev);
+ }
+
+ up(&ieee->wx_sem);
+
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_set_rawtx);
+
+int rtllib_wx_get_name(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ strcpy(wrqu->name, "802.11");
+
+ if (ieee->modulation & RTLLIB_CCK_MODULATION)
+ strcat(wrqu->name, "b");
+ if (ieee->modulation & RTLLIB_OFDM_MODULATION)
+ strcat(wrqu->name, "g");
+ if (ieee->mode & (IEEE_N_24G | IEEE_N_5G))
+ strcat(wrqu->name, "n");
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_get_name);
+
+
+/* this is mostly stolen from hostap */
+int rtllib_wx_set_power(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+
+ if ((!ieee->sta_wake_up) ||
+ (!ieee->enter_sleep_state) ||
+ (!ieee->ps_is_queue_empty)) {
+ RTLLIB_DEBUG(RTLLIB_DL_ERR,
+ "%s(): PS mode is tried to be use but driver missed a callback\n\n",
+ __func__);
+ return -1;
+ }
+
+ down(&ieee->wx_sem);
+
+ if (wrqu->power.disabled) {
+ RT_TRACE(COMP_DBG, "===>%s(): power disable\n", __func__);
+ ieee->ps = RTLLIB_PS_DISABLED;
+ goto exit;
+ }
+ if (wrqu->power.flags & IW_POWER_TIMEOUT) {
+ ieee->ps_timeout = wrqu->power.value / 1000;
+ RT_TRACE(COMP_DBG, "===>%s():ps_timeout is %d\n", __func__,
+ ieee->ps_timeout);
+ }
+
+ if (wrqu->power.flags & IW_POWER_PERIOD)
+ ieee->ps_period = wrqu->power.value / 1000;
+
+ switch (wrqu->power.flags & IW_POWER_MODE) {
+ case IW_POWER_UNICAST_R:
+ ieee->ps = RTLLIB_PS_UNICAST;
+ break;
+ case IW_POWER_MULTICAST_R:
+ ieee->ps = RTLLIB_PS_MBCAST;
+ break;
+ case IW_POWER_ALL_R:
+ ieee->ps = RTLLIB_PS_UNICAST | RTLLIB_PS_MBCAST;
+ break;
+
+ case IW_POWER_ON:
+ break;
+
+ default:
+ ret = -EINVAL;
+ goto exit;
+
+ }
+exit:
+ up(&ieee->wx_sem);
+ return ret;
+
+}
+EXPORT_SYMBOL(rtllib_wx_set_power);
+
+/* this is stolen from hostap */
+int rtllib_wx_get_power(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ down(&ieee->wx_sem);
+
+ if (ieee->ps == RTLLIB_PS_DISABLED) {
+ wrqu->power.disabled = 1;
+ goto exit;
+ }
+
+ wrqu->power.disabled = 0;
+
+ if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
+ wrqu->power.flags = IW_POWER_TIMEOUT;
+ wrqu->power.value = ieee->ps_timeout * 1000;
+ } else {
+ wrqu->power.flags = IW_POWER_PERIOD;
+ wrqu->power.value = ieee->ps_period * 1000;
+ }
+
+ if ((ieee->ps & (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) ==
+ (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST))
+ wrqu->power.flags |= IW_POWER_ALL_R;
+ else if (ieee->ps & RTLLIB_PS_MBCAST)
+ wrqu->power.flags |= IW_POWER_MULTICAST_R;
+ else
+ wrqu->power.flags |= IW_POWER_UNICAST_R;
+
+exit:
+ up(&ieee->wx_sem);
+ return 0;
+
+}
+EXPORT_SYMBOL(rtllib_wx_get_power);
diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c
new file mode 100644
index 000000000..3b159638b
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_tx.c
@@ -0,0 +1,988 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************
+
+ Few modifications for Realtek's Wi-Fi drivers by
+ Andrea Merello <andrea.merello@gmail.com>
+
+ A special thanks goes to Realtek for their support !
+
+******************************************************************************/
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <linux/uaccess.h>
+#include <linux/if_vlan.h>
+
+#include "rtllib.h"
+
+/* 802.11 Data Frame
+ *
+ *
+ * 802.11 frame_control for data frames - 2 bytes
+ * ,-----------------------------------------------------------------------------------------.
+ * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
+ * |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
+ * val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x |
+ * |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
+ * desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep |
+ * | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
+ * '-----------------------------------------------------------------------------------------'
+ * /\
+ * |
+ * 802.11 Data Frame |
+ * ,--------- 'ctrl' expands to >-----------'
+ * |
+ * ,--'---,-------------------------------------------------------------.
+ * Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
+ * |------|------|---------|---------|---------|------|---------|------|
+ * Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
+ * | | tion | (BSSID) | | | ence | data | |
+ * `--------------------------------------------------| |------'
+ * Total: 28 non-data bytes `----.----'
+ * |
+ * .- 'Frame data' expands to <---------------------------'
+ * |
+ * V
+ * ,---------------------------------------------------.
+ * Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
+ * |------|------|---------|----------|------|---------|
+ * Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
+ * | DSAP | SSAP | | | | Packet |
+ * | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
+ * `-----------------------------------------| |
+ * Total: 8 non-data bytes `----.----'
+ * |
+ * .- 'IP Packet' expands, if WEP enabled, to <--'
+ * |
+ * V
+ * ,-----------------------.
+ * Bytes | 4 | 0-2296 | 4 |
+ * |-----|-----------|-----|
+ * Desc. | IV | Encrypted | ICV |
+ * | | IP Packet | |
+ * `-----------------------'
+ * Total: 8 non-data bytes
+ *
+ *
+ * 802.3 Ethernet Data Frame
+ *
+ * ,-----------------------------------------.
+ * Bytes | 6 | 6 | 2 | Variable | 4 |
+ * |-------|-------|------|-----------|------|
+ * Desc. | Dest. | Source| Type | IP Packet | fcs |
+ * | MAC | MAC | | | |
+ * `-----------------------------------------'
+ * Total: 18 non-data bytes
+ *
+ * In the event that fragmentation is required, the incoming payload is split into
+ * N parts of size ieee->fts. The first fragment contains the SNAP header and the
+ * remaining packets are just data.
+ *
+ * If encryption is enabled, each fragment payload size is reduced by enough space
+ * to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
+ * So if you have 1500 bytes of payload with ieee->fts set to 500 without
+ * encryption it will take 3 frames. With WEP it will take 4 frames as the
+ * payload of each frame is reduced to 492 bytes.
+ *
+ * SKB visualization
+ *
+ * ,- skb->data
+ * |
+ * | ETHERNET HEADER ,-<-- PAYLOAD
+ * | | 14 bytes from skb->data
+ * | 2 bytes for Type --> ,T. | (sizeof ethhdr)
+ * | | | |
+ * |,-Dest.--. ,--Src.---. | | |
+ * | 6 bytes| | 6 bytes | | | |
+ * v | | | | | |
+ * 0 | v 1 | v | v 2
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * ^ | ^ | ^ |
+ * | | | | | |
+ * | | | | `T' <---- 2 bytes for Type
+ * | | | |
+ * | | '---SNAP--' <-------- 6 bytes for SNAP
+ * | |
+ * `-IV--' <-------------------- 4 bytes for IV (WEP)
+ *
+ * SNAP HEADER
+ *
+ */
+
+static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
+static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
+
+inline int rtllib_put_snap(u8 *data, u16 h_proto)
+{
+ struct rtllib_snap_hdr *snap;
+ u8 *oui;
+
+ snap = (struct rtllib_snap_hdr *)data;
+ snap->dsap = 0xaa;
+ snap->ssap = 0xaa;
+ snap->ctrl = 0x03;
+
+ if (h_proto == 0x8137 || h_proto == 0x80f3)
+ oui = P802_1H_OUI;
+ else
+ oui = RFC1042_OUI;
+ snap->oui[0] = oui[0];
+ snap->oui[1] = oui[1];
+ snap->oui[2] = oui[2];
+
+ *(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
+
+ return SNAP_SIZE + sizeof(u16);
+}
+
+int rtllib_encrypt_fragment(struct rtllib_device *ieee, struct sk_buff *frag,
+ int hdr_len)
+{
+ struct lib80211_crypt_data *crypt = NULL;
+ int res;
+
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
+
+ if (!(crypt && crypt->ops)) {
+ netdev_info(ieee->dev, "=========>%s(), crypt is null\n",
+ __func__);
+ return -1;
+ }
+ /* To encrypt, frame format is:
+ * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes)
+ */
+
+ /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
+ * call both MSDU and MPDU encryption functions from here.
+ */
+ atomic_inc(&crypt->refcnt);
+ res = 0;
+ if (crypt->ops->encrypt_msdu)
+ res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
+ if (res == 0 && crypt->ops->encrypt_mpdu)
+ res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
+
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ netdev_info(ieee->dev, "%s: Encryption failed: len=%d.\n",
+ ieee->dev->name, frag->len);
+ ieee->ieee_stats.tx_discards++;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+void rtllib_txb_free(struct rtllib_txb *txb)
+{
+ if (unlikely(!txb))
+ return;
+ kfree(txb);
+}
+
+static struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size,
+ gfp_t gfp_mask)
+{
+ struct rtllib_txb *txb;
+ int i;
+
+ txb = kmalloc(sizeof(struct rtllib_txb) + (sizeof(u8 *) * nr_frags),
+ gfp_mask);
+ if (!txb)
+ return NULL;
+
+ memset(txb, 0, sizeof(struct rtllib_txb));
+ txb->nr_frags = nr_frags;
+ txb->frag_size = cpu_to_le16(txb_size);
+
+ for (i = 0; i < nr_frags; i++) {
+ txb->fragments[i] = dev_alloc_skb(txb_size);
+ if (unlikely(!txb->fragments[i])) {
+ i--;
+ break;
+ }
+ memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
+ }
+ if (unlikely(i != nr_frags)) {
+ while (i >= 0)
+ dev_kfree_skb_any(txb->fragments[i--]);
+ kfree(txb);
+ return NULL;
+ }
+ return txb;
+}
+
+static int rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu)
+{
+ struct ethhdr *eth;
+ struct iphdr *ip;
+
+ eth = (struct ethhdr *)skb->data;
+ if (eth->h_proto != htons(ETH_P_IP))
+ return 0;
+
+ RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA, skb->data, skb->len);
+ ip = ip_hdr(skb);
+ switch (ip->tos & 0xfc) {
+ case 0x20:
+ return 2;
+ case 0x40:
+ return 1;
+ case 0x60:
+ return 3;
+ case 0x80:
+ return 4;
+ case 0xa0:
+ return 5;
+ case 0xc0:
+ return 6;
+ case 0xe0:
+ return 7;
+ default:
+ return 0;
+ }
+}
+
+static void rtllib_tx_query_agg_cap(struct rtllib_device *ieee,
+ struct sk_buff *skb,
+ struct cb_desc *tcb_desc)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+ struct tx_ts_record *pTxTs = NULL;
+ struct rtllib_hdr_1addr *hdr = (struct rtllib_hdr_1addr *)skb->data;
+
+ if (rtllib_act_scanning(ieee, false))
+ return;
+
+ if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
+ return;
+ if (!IsQoSDataFrame(skb->data))
+ return;
+ if (is_multicast_ether_addr(hdr->addr1))
+ return;
+
+ if (tcb_desc->bdhcp || ieee->CntAfterLink < 2)
+ return;
+
+ if (pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION)
+ return;
+
+ if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
+ return;
+ if (pHTInfo->bCurrentAMPDUEnable) {
+ if (!GetTs(ieee, (struct ts_common_info **)(&pTxTs), hdr->addr1,
+ skb->priority, TX_DIR, true)) {
+ netdev_info(ieee->dev, "%s: can't get TS\n", __func__);
+ return;
+ }
+ if (pTxTs->TxAdmittedBARecord.bValid == false) {
+ if (ieee->wpa_ie_len && (ieee->pairwise_key_type ==
+ KEY_TYPE_NA)) {
+ ;
+ } else if (tcb_desc->bdhcp == 1) {
+ ;
+ } else if (!pTxTs->bDisable_AddBa) {
+ TsStartAddBaProcess(ieee, pTxTs);
+ }
+ goto FORCED_AGG_SETTING;
+ } else if (pTxTs->bUsingBa == false) {
+ if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum,
+ (pTxTs->TxCurSeq+1)%4096))
+ pTxTs->bUsingBa = true;
+ else
+ goto FORCED_AGG_SETTING;
+ }
+ if (ieee->iw_mode == IW_MODE_INFRA) {
+ tcb_desc->bAMPDUEnable = true;
+ tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
+ tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
+ }
+ }
+FORCED_AGG_SETTING:
+ switch (pHTInfo->ForcedAMPDUMode) {
+ case HT_AGG_AUTO:
+ break;
+
+ case HT_AGG_FORCE_ENABLE:
+ tcb_desc->bAMPDUEnable = true;
+ tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
+ tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
+ break;
+
+ case HT_AGG_FORCE_DISABLE:
+ tcb_desc->bAMPDUEnable = false;
+ tcb_desc->ampdu_density = 0;
+ tcb_desc->ampdu_factor = 0;
+ break;
+ }
+}
+
+static void rtllib_qurey_ShortPreambleMode(struct rtllib_device *ieee,
+ struct cb_desc *tcb_desc)
+{
+ tcb_desc->bUseShortPreamble = false;
+ if (tcb_desc->data_rate == 2)
+ return;
+ else if (ieee->current_network.capability &
+ WLAN_CAPABILITY_SHORT_PREAMBLE)
+ tcb_desc->bUseShortPreamble = true;
+}
+
+static void rtllib_query_HTCapShortGI(struct rtllib_device *ieee,
+ struct cb_desc *tcb_desc)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+
+ tcb_desc->bUseShortGI = false;
+
+ if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
+ return;
+
+ if (pHTInfo->bForcedShortGI) {
+ tcb_desc->bUseShortGI = true;
+ return;
+ }
+
+ if ((pHTInfo->bCurBW40MHz == true) && pHTInfo->bCurShortGI40MHz)
+ tcb_desc->bUseShortGI = true;
+ else if ((pHTInfo->bCurBW40MHz == false) && pHTInfo->bCurShortGI20MHz)
+ tcb_desc->bUseShortGI = true;
+}
+
+static void rtllib_query_BandwidthMode(struct rtllib_device *ieee,
+ struct cb_desc *tcb_desc)
+{
+ struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
+
+ tcb_desc->bPacketBW = false;
+
+ if (!pHTInfo->bCurrentHTSupport || !pHTInfo->bEnableHT)
+ return;
+
+ if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
+ return;
+
+ if ((tcb_desc->data_rate & 0x80) == 0)
+ return;
+ if (pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz &&
+ !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
+ tcb_desc->bPacketBW = true;
+}
+
+static void rtllib_query_protectionmode(struct rtllib_device *ieee,
+ struct cb_desc *tcb_desc,
+ struct sk_buff *skb)
+{
+ struct rt_hi_throughput *pHTInfo;
+
+ tcb_desc->bRTSSTBC = false;
+ tcb_desc->bRTSUseShortGI = false;
+ tcb_desc->bCTSEnable = false;
+ tcb_desc->RTSSC = 0;
+ tcb_desc->bRTSBW = false;
+
+ if (tcb_desc->bBroadcast || tcb_desc->bMulticast)
+ return;
+
+ if (is_broadcast_ether_addr(skb->data+16))
+ return;
+
+ if (ieee->mode < IEEE_N_24G) {
+ if (skb->len > ieee->rts) {
+ tcb_desc->bRTSEnable = true;
+ tcb_desc->rts_rate = MGN_24M;
+ } else if (ieee->current_network.buseprotection) {
+ tcb_desc->bRTSEnable = true;
+ tcb_desc->bCTSEnable = true;
+ tcb_desc->rts_rate = MGN_24M;
+ }
+ return;
+ }
+
+ pHTInfo = ieee->pHTInfo;
+
+ while (true) {
+ if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) {
+ tcb_desc->bCTSEnable = true;
+ tcb_desc->rts_rate = MGN_24M;
+ tcb_desc->bRTSEnable = true;
+ break;
+ } else if (pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS |
+ HT_IOT_ACT_PURE_N_MODE)) {
+ tcb_desc->bRTSEnable = true;
+ tcb_desc->rts_rate = MGN_24M;
+ break;
+ }
+ if (ieee->current_network.buseprotection) {
+ tcb_desc->bRTSEnable = true;
+ tcb_desc->bCTSEnable = true;
+ tcb_desc->rts_rate = MGN_24M;
+ break;
+ }
+ if (pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) {
+ u8 HTOpMode = pHTInfo->CurrentOpMode;
+
+ if ((pHTInfo->bCurBW40MHz && (HTOpMode == 2 ||
+ HTOpMode == 3)) ||
+ (!pHTInfo->bCurBW40MHz && HTOpMode == 3)) {
+ tcb_desc->rts_rate = MGN_24M;
+ tcb_desc->bRTSEnable = true;
+ break;
+ }
+ }
+ if (skb->len > ieee->rts) {
+ tcb_desc->rts_rate = MGN_24M;
+ tcb_desc->bRTSEnable = true;
+ break;
+ }
+ if (tcb_desc->bAMPDUEnable) {
+ tcb_desc->rts_rate = MGN_24M;
+ tcb_desc->bRTSEnable = false;
+ break;
+ }
+ goto NO_PROTECTION;
+ }
+ if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+ tcb_desc->bUseShortPreamble = true;
+ if (ieee->iw_mode == IW_MODE_MASTER)
+ goto NO_PROTECTION;
+ return;
+NO_PROTECTION:
+ tcb_desc->bRTSEnable = false;
+ tcb_desc->bCTSEnable = false;
+ tcb_desc->rts_rate = 0;
+ tcb_desc->RTSSC = 0;
+ tcb_desc->bRTSBW = false;
+}
+
+
+static void rtllib_txrate_selectmode(struct rtllib_device *ieee,
+ struct cb_desc *tcb_desc)
+{
+ if (ieee->bTxDisableRateFallBack)
+ tcb_desc->bTxDisableRateFallBack = true;
+
+ if (ieee->bTxUseDriverAssingedRate)
+ tcb_desc->bTxUseDriverAssingedRate = true;
+ if (!tcb_desc->bTxDisableRateFallBack ||
+ !tcb_desc->bTxUseDriverAssingedRate) {
+ if (ieee->iw_mode == IW_MODE_INFRA ||
+ ieee->iw_mode == IW_MODE_ADHOC)
+ tcb_desc->RATRIndex = 0;
+ }
+}
+
+u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
+ u8 *dst)
+{
+ u16 seqnum = 0;
+
+ if (is_multicast_ether_addr(dst))
+ return 0;
+ if (IsQoSDataFrame(skb->data)) {
+ struct tx_ts_record *pTS = NULL;
+
+ if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
+ skb->priority, TX_DIR, true))
+ return 0;
+ seqnum = pTS->TxCurSeq;
+ pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
+ return seqnum;
+ }
+ return 0;
+}
+
+static int wme_downgrade_ac(struct sk_buff *skb)
+{
+ switch (skb->priority) {
+ case 6:
+ case 7:
+ skb->priority = 5; /* VO -> VI */
+ return 0;
+ case 4:
+ case 5:
+ skb->priority = 3; /* VI -> BE */
+ return 0;
+ case 0:
+ case 3:
+ skb->priority = 1; /* BE -> BK */
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+static u8 rtllib_current_rate(struct rtllib_device *ieee)
+{
+ if (ieee->mode & IEEE_MODE_MASK)
+ return ieee->rate;
+
+ if (ieee->HTCurrentOperaRate)
+ return ieee->HTCurrentOperaRate;
+ else
+ return ieee->rate & 0x7F;
+}
+
+int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
+{
+ struct rtllib_device *ieee = (struct rtllib_device *)
+ netdev_priv_rsl(dev);
+ struct rtllib_txb *txb = NULL;
+ struct rtllib_hdr_3addrqos *frag_hdr;
+ int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
+ unsigned long flags;
+ struct net_device_stats *stats = &ieee->stats;
+ int ether_type = 0, encrypt;
+ int bytes, fc, qos_ctl = 0, hdr_len;
+ struct sk_buff *skb_frag;
+ struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */
+ .duration_id = 0,
+ .seq_ctl = 0,
+ .qos_ctl = 0
+ };
+ u8 dest[ETH_ALEN], src[ETH_ALEN];
+ int qos_actived = ieee->current_network.qos_data.active;
+ struct lib80211_crypt_data *crypt = NULL;
+ struct cb_desc *tcb_desc;
+ u8 bIsMulticast = false;
+ u8 IsAmsdu = false;
+ bool bdhcp = false;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ /* If there is no driver handler to take the TXB, don't bother
+ * creating it...
+ */
+ if ((!ieee->hard_start_xmit && !(ieee->softmac_features &
+ IEEE_SOFTMAC_TX_QUEUE)) ||
+ ((!ieee->softmac_data_hard_start_xmit &&
+ (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
+ netdev_warn(ieee->dev, "No xmit handler.\n");
+ goto success;
+ }
+
+
+ if (likely(ieee->raw_tx == 0)) {
+ if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
+ netdev_warn(ieee->dev, "skb too small (%d).\n",
+ skb->len);
+ goto success;
+ }
+ /* Save source and destination addresses */
+ memcpy(dest, skb->data, ETH_ALEN);
+ memcpy(src, skb->data+ETH_ALEN, ETH_ALEN);
+
+ memset(skb->cb, 0, sizeof(skb->cb));
+ ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
+
+ if (ieee->iw_mode == IW_MODE_MONITOR) {
+ txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
+ if (unlikely(!txb)) {
+ netdev_warn(ieee->dev,
+ "Could not allocate TXB\n");
+ goto failed;
+ }
+
+ txb->encrypted = 0;
+ txb->payload_size = cpu_to_le16(skb->len);
+ memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
+ skb->len);
+
+ goto success;
+ }
+
+ if (skb->len > 282) {
+ if (ETH_P_IP == ether_type) {
+ const struct iphdr *ip = (struct iphdr *)
+ ((u8 *)skb->data+14);
+ if (IPPROTO_UDP == ip->protocol) {
+ struct udphdr *udp;
+
+ udp = (struct udphdr *)((u8 *)ip +
+ (ip->ihl << 2));
+ if (((((u8 *)udp)[1] == 68) &&
+ (((u8 *)udp)[3] == 67)) ||
+ ((((u8 *)udp)[1] == 67) &&
+ (((u8 *)udp)[3] == 68))) {
+ bdhcp = true;
+ ieee->LPSDelayCnt = 200;
+ }
+ }
+ } else if (ETH_P_ARP == ether_type) {
+ netdev_info(ieee->dev,
+ "=================>DHCP Protocol start tx ARP pkt!!\n");
+ bdhcp = true;
+ ieee->LPSDelayCnt =
+ ieee->current_network.tim.tim_count;
+ }
+ }
+
+ skb->priority = rtllib_classify(skb, IsAmsdu);
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
+ encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
+ ieee->host_encrypt && crypt && crypt->ops;
+ if (!encrypt && ieee->ieee802_1x &&
+ ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
+ stats->tx_dropped++;
+ goto success;
+ }
+ if (crypt && !encrypt && ether_type == ETH_P_PAE) {
+ struct eapol *eap = (struct eapol *)(skb->data +
+ sizeof(struct ethhdr) - SNAP_SIZE -
+ sizeof(u16));
+ RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
+ eap_get_type(eap->type));
+ }
+
+ /* Advance the SKB to the start of the payload */
+ skb_pull(skb, sizeof(struct ethhdr));
+
+ /* Determine total amount of storage required for TXB packets */
+ bytes = skb->len + SNAP_SIZE + sizeof(u16);
+
+ if (encrypt)
+ fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP;
+ else
+ fc = RTLLIB_FTYPE_DATA;
+
+ if (qos_actived)
+ fc |= RTLLIB_STYPE_QOS_DATA;
+ else
+ fc |= RTLLIB_STYPE_DATA;
+
+ if (ieee->iw_mode == IW_MODE_INFRA) {
+ fc |= RTLLIB_FCTL_TODS;
+ /* To DS: Addr1 = BSSID, Addr2 = SA,
+ * Addr3 = DA
+ */
+ memcpy(&header.addr1, ieee->current_network.bssid,
+ ETH_ALEN);
+ memcpy(&header.addr2, &src, ETH_ALEN);
+ if (IsAmsdu)
+ memcpy(&header.addr3,
+ ieee->current_network.bssid, ETH_ALEN);
+ else
+ memcpy(&header.addr3, &dest, ETH_ALEN);
+ } else if (ieee->iw_mode == IW_MODE_ADHOC) {
+ /* not From/To DS: Addr1 = DA, Addr2 = SA,
+ * Addr3 = BSSID
+ */
+ memcpy(&header.addr1, dest, ETH_ALEN);
+ memcpy(&header.addr2, src, ETH_ALEN);
+ memcpy(&header.addr3, ieee->current_network.bssid,
+ ETH_ALEN);
+ }
+
+ bIsMulticast = is_multicast_ether_addr(header.addr1);
+
+ header.frame_ctl = cpu_to_le16(fc);
+
+ /* Determine fragmentation size based on destination (multicast
+ * and broadcast are not fragmented)
+ */
+ if (bIsMulticast) {
+ frag_size = MAX_FRAG_THRESHOLD;
+ qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
+ } else {
+ frag_size = ieee->fts;
+ qos_ctl = 0;
+ }
+
+ if (qos_actived) {
+ hdr_len = RTLLIB_3ADDR_LEN + 2;
+
+ /* in case we are a client verify acm is not set for this ac */
+ while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) {
+ netdev_info(ieee->dev, "skb->priority = %x\n",
+ skb->priority);
+ if (wme_downgrade_ac(skb))
+ break;
+ netdev_info(ieee->dev, "converted skb->priority = %x\n",
+ skb->priority);
+ }
+ qos_ctl |= skb->priority;
+ header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID);
+ } else {
+ hdr_len = RTLLIB_3ADDR_LEN;
+ }
+ /* Determine amount of payload per fragment. Regardless of if
+ * this stack is providing the full 802.11 header, one will
+ * eventually be affixed to this fragment -- so we must account
+ * for it when determining the amount of payload space.
+ */
+ bytes_per_frag = frag_size - hdr_len;
+ if (ieee->config &
+ (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
+ bytes_per_frag -= RTLLIB_FCS_LEN;
+
+ /* Each fragment may need to have room for encrypting
+ * pre/postfix
+ */
+ if (encrypt) {
+ bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
+ crypt->ops->extra_mpdu_postfix_len +
+ crypt->ops->extra_msdu_prefix_len +
+ crypt->ops->extra_msdu_postfix_len;
+ }
+ /* Number of fragments is the total bytes_per_frag /
+ * payload_per_fragment
+ */
+ nr_frags = bytes / bytes_per_frag;
+ bytes_last_frag = bytes % bytes_per_frag;
+ if (bytes_last_frag)
+ nr_frags++;
+ else
+ bytes_last_frag = bytes_per_frag;
+
+ /* When we allocate the TXB we allocate enough space for the
+ * reserve and full fragment bytes (bytes_per_frag doesn't
+ * include prefix, postfix, header, FCS, etc.)
+ */
+ txb = rtllib_alloc_txb(nr_frags, frag_size +
+ ieee->tx_headroom, GFP_ATOMIC);
+ if (unlikely(!txb)) {
+ netdev_warn(ieee->dev, "Could not allocate TXB\n");
+ goto failed;
+ }
+ txb->encrypted = encrypt;
+ txb->payload_size = cpu_to_le16(bytes);
+
+ if (qos_actived)
+ txb->queue_index = UP2AC(skb->priority);
+ else
+ txb->queue_index = WME_AC_BE;
+
+ for (i = 0; i < nr_frags; i++) {
+ skb_frag = txb->fragments[i];
+ tcb_desc = (struct cb_desc *)(skb_frag->cb +
+ MAX_DEV_ADDR_SIZE);
+ if (qos_actived) {
+ skb_frag->priority = skb->priority;
+ tcb_desc->queue_index = UP2AC(skb->priority);
+ } else {
+ skb_frag->priority = WME_AC_BE;
+ tcb_desc->queue_index = WME_AC_BE;
+ }
+ skb_reserve(skb_frag, ieee->tx_headroom);
+
+ if (encrypt) {
+ if (ieee->hwsec_active)
+ tcb_desc->bHwSec = 1;
+ else
+ tcb_desc->bHwSec = 0;
+ skb_reserve(skb_frag,
+ crypt->ops->extra_mpdu_prefix_len +
+ crypt->ops->extra_msdu_prefix_len);
+ } else {
+ tcb_desc->bHwSec = 0;
+ }
+ frag_hdr = (struct rtllib_hdr_3addrqos *)
+ skb_put(skb_frag, hdr_len);
+ memcpy(frag_hdr, &header, hdr_len);
+
+ /* If this is not the last fragment, then add the
+ * MOREFRAGS bit to the frame control
+ */
+ if (i != nr_frags - 1) {
+ frag_hdr->frame_ctl = cpu_to_le16(
+ fc | RTLLIB_FCTL_MOREFRAGS);
+ bytes = bytes_per_frag;
+
+ } else {
+ /* The last fragment has the remaining length */
+ bytes = bytes_last_frag;
+ }
+ if ((qos_actived) && (!bIsMulticast)) {
+ frag_hdr->seq_ctl =
+ cpu_to_le16(rtllib_query_seqnum(ieee, skb_frag,
+ header.addr1));
+ frag_hdr->seq_ctl =
+ cpu_to_le16(le16_to_cpu(frag_hdr->seq_ctl)<<4 | i);
+ } else {
+ frag_hdr->seq_ctl =
+ cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
+ }
+ /* Put a SNAP header on the first fragment */
+ if (i == 0) {
+ rtllib_put_snap(
+ skb_put(skb_frag, SNAP_SIZE +
+ sizeof(u16)), ether_type);
+ bytes -= SNAP_SIZE + sizeof(u16);
+ }
+
+ memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
+
+ /* Advance the SKB... */
+ skb_pull(skb, bytes);
+
+ /* Encryption routine will move the header forward in
+ * order to insert the IV between the header and the
+ * payload
+ */
+ if (encrypt)
+ rtllib_encrypt_fragment(ieee, skb_frag,
+ hdr_len);
+ if (ieee->config &
+ (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
+ skb_put(skb_frag, 4);
+ }
+
+ if ((qos_actived) && (!bIsMulticast)) {
+ if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
+ ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
+ else
+ ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
+ } else {
+ if (ieee->seq_ctrl[0] == 0xFFF)
+ ieee->seq_ctrl[0] = 0;
+ else
+ ieee->seq_ctrl[0]++;
+ }
+ } else {
+ if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) {
+ netdev_warn(ieee->dev, "skb too small (%d).\n",
+ skb->len);
+ goto success;
+ }
+
+ txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
+ if (!txb) {
+ netdev_warn(ieee->dev, "Could not allocate TXB\n");
+ goto failed;
+ }
+
+ txb->encrypted = 0;
+ txb->payload_size = cpu_to_le16(skb->len);
+ memcpy(skb_put(txb->fragments[0], skb->len), skb->data,
+ skb->len);
+ }
+
+ success:
+ if (txb) {
+ struct cb_desc *tcb_desc = (struct cb_desc *)
+ (txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
+ tcb_desc->bTxEnableFwCalcDur = 1;
+ tcb_desc->priority = skb->priority;
+
+ if (ether_type == ETH_P_PAE) {
+ if (ieee->pHTInfo->IOTAction &
+ HT_IOT_ACT_WA_IOT_Broadcom) {
+ tcb_desc->data_rate =
+ MgntQuery_TxRateExcludeCCKRates(ieee);
+ tcb_desc->bTxDisableRateFallBack = false;
+ } else {
+ tcb_desc->data_rate = ieee->basic_rate;
+ tcb_desc->bTxDisableRateFallBack = 1;
+ }
+
+
+ tcb_desc->RATRIndex = 7;
+ tcb_desc->bTxUseDriverAssingedRate = 1;
+ } else {
+ if (is_multicast_ether_addr(header.addr1))
+ tcb_desc->bMulticast = 1;
+ if (is_broadcast_ether_addr(header.addr1))
+ tcb_desc->bBroadcast = 1;
+ rtllib_txrate_selectmode(ieee, tcb_desc);
+ if (tcb_desc->bMulticast || tcb_desc->bBroadcast)
+ tcb_desc->data_rate = ieee->basic_rate;
+ else
+ tcb_desc->data_rate = rtllib_current_rate(ieee);
+
+ if (bdhcp) {
+ if (ieee->pHTInfo->IOTAction &
+ HT_IOT_ACT_WA_IOT_Broadcom) {
+ tcb_desc->data_rate =
+ MgntQuery_TxRateExcludeCCKRates(ieee);
+ tcb_desc->bTxDisableRateFallBack = false;
+ } else {
+ tcb_desc->data_rate = MGN_1M;
+ tcb_desc->bTxDisableRateFallBack = 1;
+ }
+
+
+ tcb_desc->RATRIndex = 7;
+ tcb_desc->bTxUseDriverAssingedRate = 1;
+ tcb_desc->bdhcp = 1;
+ }
+
+ rtllib_qurey_ShortPreambleMode(ieee, tcb_desc);
+ rtllib_tx_query_agg_cap(ieee, txb->fragments[0],
+ tcb_desc);
+ rtllib_query_HTCapShortGI(ieee, tcb_desc);
+ rtllib_query_BandwidthMode(ieee, tcb_desc);
+ rtllib_query_protectionmode(ieee, tcb_desc,
+ txb->fragments[0]);
+ }
+ }
+ spin_unlock_irqrestore(&ieee->lock, flags);
+ dev_kfree_skb_any(skb);
+ if (txb) {
+ if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += le16_to_cpu(txb->payload_size);
+ rtllib_softmac_xmit(txb, ieee);
+ } else {
+ if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
+ stats->tx_packets++;
+ stats->tx_bytes += le16_to_cpu(txb->payload_size);
+ return 0;
+ }
+ rtllib_txb_free(txb);
+ }
+ }
+
+ return 0;
+
+ failed:
+ spin_unlock_irqrestore(&ieee->lock, flags);
+ netif_stop_queue(dev);
+ stats->tx_errors++;
+ return 1;
+
+}
+int rtllib_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ memset(skb->cb, 0, sizeof(skb->cb));
+ return rtllib_xmit_inter(skb, dev);
+}
+EXPORT_SYMBOL(rtllib_xmit);
diff --git a/drivers/staging/rtl8192e/rtllib_wx.c b/drivers/staging/rtl8192e/rtllib_wx.c
new file mode 100644
index 000000000..6234aae5b
--- /dev/null
+++ b/drivers/staging/rtl8192e/rtllib_wx.c
@@ -0,0 +1,881 @@
+/******************************************************************************
+
+ Copyright(c) 2004 Intel Corporation. All rights reserved.
+
+ Portions of this file are based on the WEP enablement code provided by the
+ Host AP project hostap-drivers v0.1.3
+ Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ <jkmaline@cc.hut.fi>
+ Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+#include <linux/wireless.h>
+#include <linux/kmod.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include "rtllib.h"
+struct modes_unit {
+ char *mode_string;
+ int mode_size;
+};
+static struct modes_unit rtllib_modes[] = {
+ {"a", 1},
+ {"b", 1},
+ {"g", 1},
+ {"?", 1},
+ {"N-24G", 5},
+ {"N-5G", 4},
+};
+
+#define MAX_CUSTOM_LEN 64
+static inline char *rtl819x_translate_scan(struct rtllib_device *ieee,
+ char *start, char *stop,
+ struct rtllib_network *network,
+ struct iw_request_info *info)
+{
+ char custom[MAX_CUSTOM_LEN];
+ char proto_name[IFNAMSIZ];
+ char *pname = proto_name;
+ char *p;
+ struct iw_event iwe;
+ int i, j;
+ u16 max_rate, rate;
+ static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
+
+ /* First entry *MUST* be the AP MAC address */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ ether_addr_copy(iwe.u.ap_addr.sa_data, network->bssid);
+ start = iwe_stream_add_event_rsl(info, start, stop,
+ &iwe, IW_EV_ADDR_LEN);
+ /* Remaining entries will be displayed in the order we provide them */
+
+ /* Add the ESSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ if (network->ssid_len > 0) {
+ iwe.u.data.length = min_t(u8, network->ssid_len, 32);
+ start = iwe_stream_add_point_rsl(info, start, stop, &iwe,
+ network->ssid);
+ } else if (network->hidden_ssid_len == 0) {
+ iwe.u.data.length = sizeof("<hidden>");
+ start = iwe_stream_add_point_rsl(info, start, stop,
+ &iwe, "<hidden>");
+ } else {
+ iwe.u.data.length = min_t(u8, network->hidden_ssid_len, 32);
+ start = iwe_stream_add_point_rsl(info, start, stop, &iwe,
+ network->hidden_ssid);
+ }
+ /* Add the protocol name */
+ iwe.cmd = SIOCGIWNAME;
+ for (i = 0; i < ARRAY_SIZE(rtllib_modes); i++) {
+ if (network->mode&(1<<i)) {
+ sprintf(pname, rtllib_modes[i].mode_string,
+ rtllib_modes[i].mode_size);
+ pname += rtllib_modes[i].mode_size;
+ }
+ }
+ *pname = '\0';
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
+ start = iwe_stream_add_event_rsl(info, start, stop,
+ &iwe, IW_EV_CHAR_LEN);
+ /* Add mode */
+ iwe.cmd = SIOCGIWMODE;
+ if (network->capability &
+ (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
+ if (network->capability & WLAN_CAPABILITY_ESS)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+ start = iwe_stream_add_event_rsl(info, start, stop,
+ &iwe, IW_EV_UINT_LEN);
+ }
+
+ /* Add frequency/channel */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = network->channel;
+ iwe.u.freq.e = 0;
+ iwe.u.freq.i = 0;
+ start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
+ IW_EV_FREQ_LEN);
+
+ /* Add encryption capability */
+ iwe.cmd = SIOCGIWENCODE;
+ if (network->capability & WLAN_CAPABILITY_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ start = iwe_stream_add_point_rsl(info, start, stop,
+ &iwe, network->ssid);
+ /* Add basic and extended rates */
+ max_rate = 0;
+ p = custom;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
+ for (i = 0, j = 0; i < network->rates_len;) {
+ if (j < network->rates_ex_len &&
+ ((network->rates_ex[j] & 0x7F) <
+ (network->rates[i] & 0x7F)))
+ rate = network->rates_ex[j++] & 0x7F;
+ else
+ rate = network->rates[i++] & 0x7F;
+ if (rate > max_rate)
+ max_rate = rate;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+ }
+ for (; j < network->rates_ex_len; j++) {
+ rate = network->rates_ex[j] & 0x7F;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+ if (rate > max_rate)
+ max_rate = rate;
+ }
+
+ if (network->mode >= IEEE_N_24G) {
+ struct ht_capab_ele *ht_cap = NULL;
+ bool is40M = false, isShortGI = false;
+ u8 max_mcs = 0;
+
+ if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
+ ht_cap = (struct ht_capab_ele *)
+ &network->bssht.bdHTCapBuf[4];
+ else
+ ht_cap = (struct ht_capab_ele *)
+ &network->bssht.bdHTCapBuf[0];
+ is40M = (ht_cap->ChlWidth) ? 1 : 0;
+ isShortGI = (ht_cap->ChlWidth) ?
+ ((ht_cap->ShortGI40Mhz) ? 1 : 0) :
+ ((ht_cap->ShortGI20Mhz) ? 1 : 0);
+
+ max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS,
+ MCS_FILTER_ALL);
+ rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs & 0x7f];
+ if (rate > max_rate)
+ max_rate = rate;
+ }
+ iwe.cmd = SIOCGIWRATE;
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+ iwe.u.bitrate.value = max_rate * 500000;
+ start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
+ IW_EV_PARAM_LEN);
+ iwe.cmd = IWEVCUSTOM;
+ iwe.u.data.length = p - custom;
+ if (iwe.u.data.length)
+ start = iwe_stream_add_point_rsl(info, start, stop,
+ &iwe, custom);
+ /* Add quality statistics */
+ /* TODO: Fix these values... */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.qual = network->stats.signal;
+ iwe.u.qual.level = network->stats.rssi;
+ iwe.u.qual.noise = network->stats.noise;
+ iwe.u.qual.updated = network->stats.mask & RTLLIB_STATMASK_WEMASK;
+ if (!(network->stats.mask & RTLLIB_STATMASK_RSSI))
+ iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
+ if (!(network->stats.mask & RTLLIB_STATMASK_NOISE))
+ iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
+ if (!(network->stats.mask & RTLLIB_STATMASK_SIGNAL))
+ iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
+ iwe.u.qual.updated = 7;
+ start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
+ IW_EV_QUAL_LEN);
+
+ iwe.cmd = IWEVCUSTOM;
+ p = custom;
+ iwe.u.data.length = p - custom;
+ if (iwe.u.data.length)
+ start = iwe_stream_add_point_rsl(info, start, stop,
+ &iwe, custom);
+
+ memset(&iwe, 0, sizeof(iwe));
+ if (network->wpa_ie_len) {
+ char buf[MAX_WPA_IE_LEN];
+
+ memcpy(buf, network->wpa_ie, network->wpa_ie_len);
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = network->wpa_ie_len;
+ start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
+ }
+ memset(&iwe, 0, sizeof(iwe));
+ if (network->rsn_ie_len) {
+ char buf[MAX_WPA_IE_LEN];
+
+ memcpy(buf, network->rsn_ie, network->rsn_ie_len);
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = network->rsn_ie_len;
+ start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
+ }
+
+ /* add info for WZC */
+ memset(&iwe, 0, sizeof(iwe));
+ if (network->wzc_ie_len) {
+ char buf[MAX_WZC_IE_LEN];
+
+ memcpy(buf, network->wzc_ie, network->wzc_ie_len);
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = network->wzc_ie_len;
+ start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf);
+ }
+
+ /* Add EXTRA: Age to display seconds since last beacon/probe response
+ * for given network.
+ */
+ iwe.cmd = IWEVCUSTOM;
+ p = custom;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ " Last beacon: %lums ago",
+ (jiffies - network->last_scanned) / (HZ / 100));
+ iwe.u.data.length = p - custom;
+ if (iwe.u.data.length)
+ start = iwe_stream_add_point_rsl(info, start, stop,
+ &iwe, custom);
+
+ return start;
+}
+
+int rtllib_wx_get_scan(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct rtllib_network *network;
+ unsigned long flags;
+
+ char *ev = extra;
+ char *stop = ev + wrqu->data.length;
+ int i = 0;
+ int err = 0;
+
+ RTLLIB_DEBUG_WX("Getting scan\n");
+ down(&ieee->wx_sem);
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ list_for_each_entry(network, &ieee->network_list, list) {
+ i++;
+ if ((stop - ev) < 200) {
+ err = -E2BIG;
+ break;
+ }
+ if (ieee->scan_age == 0 ||
+ time_after(network->last_scanned + ieee->scan_age, jiffies))
+ ev = rtl819x_translate_scan(ieee, ev, stop, network,
+ info);
+ else
+ RTLLIB_DEBUG_SCAN("Not showing network '%s ( %pM)' due to age (%lums).\n",
+ escape_essid(network->ssid,
+ network->ssid_len),
+ network->bssid,
+ (jiffies - network->last_scanned) / (HZ / 100));
+ }
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+ up(&ieee->wx_sem);
+ wrqu->data.length = ev - extra;
+ wrqu->data.flags = 0;
+
+ RTLLIB_DEBUG_WX("exit: %d networks returned.\n", i);
+
+ return err;
+}
+EXPORT_SYMBOL(rtllib_wx_get_scan);
+
+int rtllib_wx_set_encode(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *keybuf)
+{
+ struct iw_point *erq = &(wrqu->encoding);
+ struct net_device *dev = ieee->dev;
+ struct rtllib_security sec = {
+ .flags = 0
+ };
+ int i, key, key_provided, len;
+ struct lib80211_crypt_data **crypt;
+
+ RTLLIB_DEBUG_WX("SET_ENCODE\n");
+
+ key = erq->flags & IW_ENCODE_INDEX;
+ if (key) {
+ if (key > NUM_WEP_KEYS)
+ return -EINVAL;
+ key--;
+ key_provided = 1;
+ } else {
+ key_provided = 0;
+ key = ieee->crypt_info.tx_keyidx;
+ }
+
+ RTLLIB_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
+ "provided" : "default");
+ crypt = &ieee->crypt_info.crypt[key];
+ if (erq->flags & IW_ENCODE_DISABLED) {
+ if (key_provided && *crypt) {
+ RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n",
+ key);
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+ } else
+ RTLLIB_DEBUG_WX("Disabling encryption.\n");
+
+ /* Check all the keys to see if any are still configured,
+ * and if no key index was provided, de-init them all
+ */
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ if (ieee->crypt_info.crypt[i] != NULL) {
+ if (key_provided)
+ break;
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info,
+ &ieee->crypt_info.crypt[i]);
+ }
+ }
+
+ if (i == NUM_WEP_KEYS) {
+ sec.enabled = 0;
+ sec.level = SEC_LEVEL_0;
+ sec.flags |= SEC_ENABLED | SEC_LEVEL;
+ }
+
+ goto done;
+ }
+
+
+
+ sec.enabled = 1;
+ sec.flags |= SEC_ENABLED;
+
+ if (*crypt != NULL && (*crypt)->ops != NULL &&
+ strcmp((*crypt)->ops->name, "R-WEP") != 0) {
+ /* changing to use WEP; deinit previously used algorithm
+ * on this key
+ */
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+ }
+
+ if (*crypt == NULL) {
+ struct lib80211_crypt_data *new_crypt;
+
+ /* take WEP into use */
+ new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
+ GFP_KERNEL);
+ if (new_crypt == NULL)
+ return -ENOMEM;
+ new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
+ if (!new_crypt->ops) {
+ request_module("rtllib_crypt_wep");
+ new_crypt->ops = lib80211_get_crypto_ops("R-WEP");
+ }
+
+ if (new_crypt->ops)
+ new_crypt->priv = new_crypt->ops->init(key);
+
+ if (!new_crypt->ops || !new_crypt->priv) {
+ kfree(new_crypt);
+ new_crypt = NULL;
+
+ netdev_warn(dev,
+ "%s: could not initialize WEP: load module rtllib_crypt_wep\n",
+ dev->name);
+ return -EOPNOTSUPP;
+ }
+ *crypt = new_crypt;
+ }
+
+ /* If a new key was provided, set it up */
+ if (erq->length > 0) {
+ len = erq->length <= 5 ? 5 : 13;
+ memcpy(sec.keys[key], keybuf, erq->length);
+ if (len > erq->length)
+ memset(sec.keys[key] + erq->length, 0,
+ len - erq->length);
+ RTLLIB_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
+ key, escape_essid(sec.keys[key], len),
+ erq->length, len);
+ sec.key_sizes[key] = len;
+ (*crypt)->ops->set_key(sec.keys[key], len, NULL,
+ (*crypt)->priv);
+ sec.flags |= (1 << key);
+ /* This ensures a key will be activated if no key is
+ * explicitly set
+ */
+ if (key == sec.active_key)
+ sec.flags |= SEC_ACTIVE_KEY;
+ ieee->crypt_info.tx_keyidx = key;
+
+ } else {
+ len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
+ NULL, (*crypt)->priv);
+ if (len == 0) {
+ /* Set a default key of all 0 */
+ netdev_info(ieee->dev, "Setting key %d to all zero.\n",
+ key);
+
+ memset(sec.keys[key], 0, 13);
+ (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
+ (*crypt)->priv);
+ sec.key_sizes[key] = 13;
+ sec.flags |= (1 << key);
+ }
+
+ /* No key data - just set the default TX key index */
+ if (key_provided) {
+ RTLLIB_DEBUG_WX("Setting key %d to default Tx key.\n",
+ key);
+ ieee->crypt_info.tx_keyidx = key;
+ sec.active_key = key;
+ sec.flags |= SEC_ACTIVE_KEY;
+ }
+ }
+ done:
+ ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
+ ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
+ WLAN_AUTH_SHARED_KEY;
+ sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
+ sec.flags |= SEC_AUTH_MODE;
+ RTLLIB_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
+ "OPEN" : "SHARED KEY");
+
+ /* For now we just support WEP, so only set that security level...
+ * TODO: When WPA is added this is one place that needs to change
+ */
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
+
+ if (ieee->set_security)
+ ieee->set_security(dev, &sec);
+
+ /* Do not reset port if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. If your hardware requires a reset after WEP
+ * configuration (for example... Prism2), implement the reset_port in
+ * the callbacks structures used to initialize the 802.11 stack.
+ */
+ if (ieee->reset_on_keychange &&
+ ieee->iw_mode != IW_MODE_INFRA &&
+ ieee->reset_port && ieee->reset_port(dev)) {
+ netdev_dbg(dev, "%s: reset_port failed\n", dev->name);
+ return -EINVAL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_set_encode);
+
+int rtllib_wx_get_encode(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *keybuf)
+{
+ struct iw_point *erq = &(wrqu->encoding);
+ int len, key;
+ struct lib80211_crypt_data *crypt;
+
+ RTLLIB_DEBUG_WX("GET_ENCODE\n");
+
+ if (ieee->iw_mode == IW_MODE_MONITOR)
+ return -1;
+
+ key = erq->flags & IW_ENCODE_INDEX;
+ if (key) {
+ if (key > NUM_WEP_KEYS)
+ return -EINVAL;
+ key--;
+ } else {
+ key = ieee->crypt_info.tx_keyidx;
+ }
+ crypt = ieee->crypt_info.crypt[key];
+
+ erq->flags = key + 1;
+
+ if (crypt == NULL || crypt->ops == NULL) {
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ return 0;
+ }
+ len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
+ erq->length = (len >= 0 ? len : 0);
+
+ erq->flags |= IW_ENCODE_ENABLED;
+
+ if (ieee->open_wep)
+ erq->flags |= IW_ENCODE_OPEN;
+ else
+ erq->flags |= IW_ENCODE_RESTRICTED;
+
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_get_encode);
+
+int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int ret = 0;
+ struct net_device *dev = ieee->dev;
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ int i, idx;
+ int group_key = 0;
+ const char *alg, *module;
+ struct lib80211_crypto_ops *ops;
+ struct lib80211_crypt_data **crypt;
+
+ struct rtllib_security sec = {
+ .flags = 0,
+ };
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > NUM_WEP_KEYS)
+ return -EINVAL;
+ idx--;
+ } else{
+ idx = ieee->crypt_info.tx_keyidx;
+ }
+ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ crypt = &ieee->crypt_info.crypt[idx];
+ group_key = 1;
+ } else {
+ /* some Cisco APs use idx>0 for unicast in dynamic WEP */
+ if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
+ return -EINVAL;
+ if (ieee->iw_mode == IW_MODE_INFRA)
+ crypt = &ieee->crypt_info.crypt[idx];
+ else
+ return -EINVAL;
+ }
+
+ sec.flags |= SEC_ENABLED;
+ if ((encoding->flags & IW_ENCODE_DISABLED) ||
+ ext->alg == IW_ENCODE_ALG_NONE) {
+ if (*crypt)
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+
+ for (i = 0; i < NUM_WEP_KEYS; i++) {
+ if (ieee->crypt_info.crypt[i] != NULL)
+ break;
+ }
+ if (i == NUM_WEP_KEYS) {
+ sec.enabled = 0;
+ sec.level = SEC_LEVEL_0;
+ sec.flags |= SEC_LEVEL;
+ }
+ goto done;
+ }
+
+ sec.enabled = 1;
+ switch (ext->alg) {
+ case IW_ENCODE_ALG_WEP:
+ alg = "R-WEP";
+ module = "rtllib_crypt_wep";
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ alg = "R-TKIP";
+ module = "rtllib_crypt_tkip";
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ alg = "R-CCMP";
+ module = "rtllib_crypt_ccmp";
+ break;
+ default:
+ RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n",
+ dev->name, ext->alg);
+ ret = -EINVAL;
+ goto done;
+ }
+ netdev_info(dev, "alg name:%s\n", alg);
+
+ ops = lib80211_get_crypto_ops(alg);
+ if (ops == NULL) {
+ char tempbuf[100];
+
+ memset(tempbuf, 0x00, 100);
+ sprintf(tempbuf, "%s", module);
+ request_module("%s", tempbuf);
+ ops = lib80211_get_crypto_ops(alg);
+ }
+ if (ops == NULL) {
+ netdev_info(dev, "========>unknown crypto alg %d\n", ext->alg);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (*crypt == NULL || (*crypt)->ops != ops) {
+ struct lib80211_crypt_data *new_crypt;
+
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+
+ new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
+ if (new_crypt == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ new_crypt->ops = ops;
+ if (new_crypt->ops)
+ new_crypt->priv = new_crypt->ops->init(idx);
+
+ if (new_crypt->priv == NULL) {
+ kfree(new_crypt);
+ ret = -EINVAL;
+ goto done;
+ }
+ *crypt = new_crypt;
+
+ }
+
+ if (ext->key_len > 0 && (*crypt)->ops->set_key &&
+ (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
+ (*crypt)->priv) < 0) {
+ netdev_info(dev, "key setting failed\n");
+ ret = -EINVAL;
+ goto done;
+ }
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ ieee->crypt_info.tx_keyidx = idx;
+ sec.active_key = idx;
+ sec.flags |= SEC_ACTIVE_KEY;
+ }
+ if (ext->alg != IW_ENCODE_ALG_NONE) {
+ sec.key_sizes[idx] = ext->key_len;
+ sec.flags |= (1 << idx);
+ if (ext->alg == IW_ENCODE_ALG_WEP) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_1;
+ } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_2;
+ } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_3;
+ }
+ /* Don't set sec level for group keys. */
+ if (group_key)
+ sec.flags &= ~SEC_LEVEL;
+ }
+done:
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+
+ if (ieee->reset_on_keychange &&
+ ieee->iw_mode != IW_MODE_INFRA &&
+ ieee->reset_port && ieee->reset_port(dev)) {
+ RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev->name);
+ return -EINVAL;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(rtllib_wx_set_encode_ext);
+
+int rtllib_wx_get_encode_ext(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ struct lib80211_crypt_data *crypt;
+ int idx, max_key_len;
+
+ max_key_len = encoding->length - sizeof(*ext);
+ if (max_key_len < 0)
+ return -EINVAL;
+
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > NUM_WEP_KEYS)
+ return -EINVAL;
+ idx--;
+ } else {
+ idx = ieee->crypt_info.tx_keyidx;
+ }
+ if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
+ (ext->alg != IW_ENCODE_ALG_WEP))
+ if (idx != 0 || (ieee->iw_mode != IW_MODE_INFRA))
+ return -EINVAL;
+
+ crypt = ieee->crypt_info.crypt[idx];
+
+ encoding->flags = idx + 1;
+ memset(ext, 0, sizeof(*ext));
+
+ if (crypt == NULL || crypt->ops == NULL) {
+ ext->alg = IW_ENCODE_ALG_NONE;
+ ext->key_len = 0;
+ encoding->flags |= IW_ENCODE_DISABLED;
+ } else {
+ if (strcmp(crypt->ops->name, "R-WEP") == 0)
+ ext->alg = IW_ENCODE_ALG_WEP;
+ else if (strcmp(crypt->ops->name, "R-TKIP"))
+ ext->alg = IW_ENCODE_ALG_TKIP;
+ else if (strcmp(crypt->ops->name, "R-CCMP"))
+ ext->alg = IW_ENCODE_ALG_CCMP;
+ else
+ return -EINVAL;
+ ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN,
+ NULL, crypt->priv);
+ encoding->flags |= IW_ENCODE_ENABLED;
+ if (ext->key_len &&
+ (ext->alg == IW_ENCODE_ALG_TKIP ||
+ ext->alg == IW_ENCODE_ALG_CCMP))
+ ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
+
+ }
+
+ return 0;
+}
+
+int rtllib_wx_set_mlme(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ u8 i = 0;
+ bool deauth = false;
+ struct iw_mlme *mlme = (struct iw_mlme *) extra;
+
+ if (ieee->state != RTLLIB_LINKED)
+ return -ENOLINK;
+
+ down(&ieee->wx_sem);
+
+ switch (mlme->cmd) {
+ case IW_MLME_DEAUTH:
+ deauth = true;
+ /* leave break out intentionly */
+
+ case IW_MLME_DISASSOC:
+ if (deauth)
+ netdev_info(ieee->dev, "disauth packet !\n");
+ else
+ netdev_info(ieee->dev, "dis associate packet!\n");
+
+ ieee->cannot_notify = true;
+
+ SendDisassociation(ieee, deauth, mlme->reason_code);
+ rtllib_disassociate(ieee);
+
+ ieee->wap_set = 0;
+ for (i = 0; i < 6; i++)
+ ieee->current_network.bssid[i] = 0x55;
+
+ ieee->ssid_set = 0;
+ ieee->current_network.ssid[0] = '\0';
+ ieee->current_network.ssid_len = 0;
+ break;
+ default:
+ up(&ieee->wx_sem);
+ return -EOPNOTSUPP;
+ }
+
+ up(&ieee->wx_sem);
+
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_set_mlme);
+
+int rtllib_wx_set_auth(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra)
+{
+ switch (data->flags & IW_AUTH_INDEX) {
+ case IW_AUTH_WPA_VERSION:
+ break;
+ case IW_AUTH_CIPHER_PAIRWISE:
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_KEY_MGMT:
+ /* Host AP driver does not use these parameters and allows
+ * wpa_supplicant to control them internally.
+ */
+ break;
+ case IW_AUTH_TKIP_COUNTERMEASURES:
+ ieee->tkip_countermeasures = data->value;
+ break;
+ case IW_AUTH_DROP_UNENCRYPTED:
+ ieee->drop_unencrypted = data->value;
+ break;
+
+ case IW_AUTH_80211_AUTH_ALG:
+ if (data->value & IW_AUTH_ALG_SHARED_KEY) {
+ ieee->open_wep = 0;
+ ieee->auth_mode = 1;
+ } else if (data->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+ ieee->open_wep = 1;
+ ieee->auth_mode = 0;
+ } else if (data->value & IW_AUTH_ALG_LEAP) {
+ ieee->open_wep = 1;
+ ieee->auth_mode = 2;
+ } else
+ return -EINVAL;
+ break;
+
+ case IW_AUTH_WPA_ENABLED:
+ ieee->wpa_enabled = (data->value) ? 1 : 0;
+ break;
+
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+ ieee->ieee802_1x = data->value;
+ break;
+ case IW_AUTH_PRIVACY_INVOKED:
+ ieee->privacy_invoked = data->value;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_set_auth);
+
+int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len)
+{
+ u8 *buf;
+ u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
+
+ if (len > MAX_WPA_IE_LEN || (len && ie == NULL))
+ return -EINVAL;
+
+ if (len) {
+ eid = ie[0];
+ if ((eid == MFIE_TYPE_GENERIC) && (!memcmp(&ie[2],
+ wps_oui, 4))) {
+
+ ieee->wps_ie_len = (len < MAX_WZC_IE_LEN) ? (len) :
+ (MAX_WZC_IE_LEN);
+ buf = kmemdup(ie, ieee->wps_ie_len, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+ ieee->wps_ie = buf;
+ return 0;
+ }
+ }
+ ieee->wps_ie_len = 0;
+ kfree(ieee->wps_ie);
+ ieee->wps_ie = NULL;
+ if (len) {
+ if (len != ie[1]+2)
+ return -EINVAL;
+ buf = kmemdup(ie, len, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+ kfree(ieee->wpa_ie);
+ ieee->wpa_ie = buf;
+ ieee->wpa_ie_len = len;
+ } else {
+ kfree(ieee->wpa_ie);
+ ieee->wpa_ie = NULL;
+ ieee->wpa_ie_len = 0;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(rtllib_wx_set_gen_ie);