aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/rtl8192e
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rtl8192e')
-rw-r--r--drivers/staging/rtl8192e/ieee80211/dot11d.c218
-rw-r--r--drivers/staging/rtl8192e/ieee80211/dot11d.h102
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211.h2636
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c244
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.h85
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c483
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c809
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c296
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_module.c352
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c2676
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c3278
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c600
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c955
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c872
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_BA.h69
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c676
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h483
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c1732
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_Qos.h582
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h56
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c627
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl_crypto.h399
-rw-r--r--drivers/staging/rtl8192e/r8180_93cx6.c141
-rw-r--r--drivers/staging/rtl8192e/r8180_93cx6.h41
-rw-r--r--drivers/staging/rtl8192e/r8190_rtl8256.c677
-rw-r--r--drivers/staging/rtl8192e/r8190_rtl8256.h29
-rw-r--r--drivers/staging/rtl8192e/r8192E.h1148
-rw-r--r--drivers/staging/rtl8192e/r8192E_core.c5039
-rw-r--r--drivers/staging/rtl8192e/r8192E_dm.c2554
-rw-r--r--drivers/staging/rtl8192e/r8192E_dm.h228
-rw-r--r--drivers/staging/rtl8192e/r8192E_hw.h491
-rw-r--r--drivers/staging/rtl8192e/r8192E_wx.c1163
-rw-r--r--drivers/staging/rtl8192e/r8192E_wx.h18
-rw-r--r--drivers/staging/rtl8192e/r8192_pm.c123
-rw-r--r--drivers/staging/rtl8192e/r8192_pm.h24
-rw-r--r--drivers/staging/rtl8192e/r819xE_cmdpkt.c444
-rw-r--r--drivers/staging/rtl8192e/r819xE_cmdpkt.h207
-rw-r--r--drivers/staging/rtl8192e/r819xE_firmware.c351
-rw-r--r--drivers/staging/rtl8192e/r819xE_phy.c2225
-rw-r--r--drivers/staging/rtl8192e/r819xE_phy.h131
-rw-r--r--drivers/staging/rtl8192e/r819xE_phyreg.h915
41 files changed, 34179 insertions, 0 deletions
diff --git a/drivers/staging/rtl8192e/ieee80211/dot11d.c b/drivers/staging/rtl8192e/ieee80211/dot11d.c
new file mode 100644
index 00000000000..98e46487dc0
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/dot11d.c
@@ -0,0 +1,218 @@
1#ifdef ENABLE_DOT11D
2//-----------------------------------------------------------------------------
3// File:
4// Dot11d.c
5//
6// Description:
7// Implement 802.11d.
8//
9//-----------------------------------------------------------------------------
10
11#include "dot11d.h"
12
13void
14Dot11d_Init(struct ieee80211_device *ieee)
15{
16 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
17
18 pDot11dInfo->bEnabled = 0;
19
20 pDot11dInfo->State = DOT11D_STATE_NONE;
21 pDot11dInfo->CountryIeLen = 0;
22 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
23 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
24 RESET_CIE_WATCHDOG(ieee);
25
26 printk("Dot11d_Init()\n");
27}
28
29//
30// Description:
31// Reset to the state as we are just entering a regulatory domain.
32//
33void
34Dot11d_Reset(struct ieee80211_device *ieee)
35{
36 u32 i;
37 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
38#if 0
39 if(!pDot11dInfo->bEnabled)
40 return;
41#endif
42 // Clear old channel map
43 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
44 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
45 // Set new channel map
46 for (i=1; i<=11; i++) {
47 (pDot11dInfo->channel_map)[i] = 1;
48 }
49 for (i=12; i<=14; i++) {
50 (pDot11dInfo->channel_map)[i] = 2;
51 }
52
53 pDot11dInfo->State = DOT11D_STATE_NONE;
54 pDot11dInfo->CountryIeLen = 0;
55 RESET_CIE_WATCHDOG(ieee);
56}
57
58//
59// Description:
60// Update country IE from Beacon or Probe Resopnse
61// and configure PHY for operation in the regulatory domain.
62//
63// TODO:
64// Configure Tx power.
65//
66// Assumption:
67// 1. IS_DOT11D_ENABLE() is TRUE.
68// 2. Input IE is an valid one.
69//
70void
71Dot11d_UpdateCountryIe(
72 struct ieee80211_device *dev,
73 u8 * pTaddr,
74 u16 CoutryIeLen,
75 u8 * pCoutryIe
76 )
77{
78 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
79 u8 i, j, NumTriples, MaxChnlNum;
80 PCHNL_TXPOWER_TRIPLE pTriple;
81
82 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
83 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
84 MaxChnlNum = 0;
85 NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string.
86 pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
87 for(i = 0; i < NumTriples; i++)
88 {
89 if(MaxChnlNum >= pTriple->FirstChnl)
90 { // It is not in a monotonically increasing order, so stop processing.
91 printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
92 return;
93 }
94 if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls))
95 { // It is not a valid set of channel id, so stop processing.
96 printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
97 return;
98 }
99
100 for(j = 0 ; j < pTriple->NumChnls; j++)
101 {
102 pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
103 pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm;
104 MaxChnlNum = pTriple->FirstChnl + j;
105 }
106
107 pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3);
108 }
109#if 1
110 printk("Channel List:");
111 for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
112 if(pDot11dInfo->channel_map[i] > 0)
113 printk(" %d", i);
114 printk("\n");
115#endif
116
117 UPDATE_CIE_SRC(dev, pTaddr);
118
119 pDot11dInfo->CountryIeLen = CoutryIeLen;
120 memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen);
121 pDot11dInfo->State = DOT11D_STATE_LEARNED;
122}
123
124
125u8
126DOT11D_GetMaxTxPwrInDbm(
127 struct ieee80211_device *dev,
128 u8 Channel
129 )
130{
131 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
132 u8 MaxTxPwrInDbm = 255;
133
134 if(MAX_CHANNEL_NUMBER < Channel)
135 {
136 printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
137 return MaxTxPwrInDbm;
138 }
139 if(pDot11dInfo->channel_map[Channel])
140 {
141 MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
142 }
143
144 return MaxTxPwrInDbm;
145}
146
147
148void
149DOT11D_ScanComplete(
150 struct ieee80211_device * dev
151 )
152{
153 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
154
155 switch(pDot11dInfo->State)
156 {
157 case DOT11D_STATE_LEARNED:
158 pDot11dInfo->State = DOT11D_STATE_DONE;
159 break;
160
161 case DOT11D_STATE_DONE:
162 if( GET_CIE_WATCHDOG(dev) == 0 )
163 { // Reset country IE if previous one is gone.
164 Dot11d_Reset(dev);
165 }
166 break;
167 case DOT11D_STATE_NONE:
168 break;
169 }
170}
171
172int IsLegalChannel(
173 struct ieee80211_device * dev,
174 u8 channel
175)
176{
177 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
178
179 if(MAX_CHANNEL_NUMBER < channel)
180 {
181 printk("IsLegalChannel(): Invalid Channel\n");
182 return 0;
183 }
184 if(pDot11dInfo->channel_map[channel] > 0)
185 return 1;
186 return 0;
187}
188
189int ToLegalChannel(
190 struct ieee80211_device * dev,
191 u8 channel
192)
193{
194 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
195 u8 default_chn = 0;
196 u32 i = 0;
197
198 for (i=1; i<= MAX_CHANNEL_NUMBER; i++)
199 {
200 if(pDot11dInfo->channel_map[i] > 0)
201 {
202 default_chn = i;
203 break;
204 }
205 }
206
207 if(MAX_CHANNEL_NUMBER < channel)
208 {
209 printk("IsLegalChannel(): Invalid Channel\n");
210 return default_chn;
211 }
212
213 if(pDot11dInfo->channel_map[channel] > 0)
214 return channel;
215
216 return default_chn;
217}
218#endif
diff --git a/drivers/staging/rtl8192e/ieee80211/dot11d.h b/drivers/staging/rtl8192e/ieee80211/dot11d.h
new file mode 100644
index 00000000000..15b7a4ba37b
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/dot11d.h
@@ -0,0 +1,102 @@
1#ifndef __INC_DOT11D_H
2#define __INC_DOT11D_H
3
4#ifdef ENABLE_DOT11D
5#include "ieee80211.h"
6
7//#define ENABLE_DOT11D
8
9//#define DOT11D_MAX_CHNL_NUM 83
10
11typedef struct _CHNL_TXPOWER_TRIPLE {
12 u8 FirstChnl;
13 u8 NumChnls;
14 u8 MaxTxPowerInDbm;
15}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
16
17typedef enum _DOT11D_STATE {
18 DOT11D_STATE_NONE = 0,
19 DOT11D_STATE_LEARNED,
20 DOT11D_STATE_DONE,
21}DOT11D_STATE;
22
23typedef struct _RT_DOT11D_INFO {
24 //DECLARE_RT_OBJECT(RT_DOT11D_INFO);
25
26 bool bEnabled; // dot11MultiDomainCapabilityEnabled
27
28 u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element.
29 u8 CountryIeBuf[MAX_IE_LEN];
30 u8 CountryIeSrcAddr[6]; // Source AP of the country IE.
31 u8 CountryIeWatchdog;
32
33 u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan)
34 //u8 ChnlListLen; // #Bytes valid in ChnlList[].
35 //u8 ChnlList[DOT11D_MAX_CHNL_NUM];
36 u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
37
38 DOT11D_STATE State;
39}RT_DOT11D_INFO, *PRT_DOT11D_INFO;
40#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 )
41#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5])
42#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
43
44#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
45#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
46
47#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
48#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
49
50#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
51 (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
52 FALSE : \
53 (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
54
55#define CIE_WATCHDOG_TH 1
56#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
57#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
58#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
59
60#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
61
62
63void
64Dot11d_Init(
65 struct ieee80211_device *dev
66 );
67
68void
69Dot11d_Reset(
70 struct ieee80211_device *dev
71 );
72
73void
74Dot11d_UpdateCountryIe(
75 struct ieee80211_device *dev,
76 u8 * pTaddr,
77 u16 CoutryIeLen,
78 u8 * pCoutryIe
79 );
80
81u8
82DOT11D_GetMaxTxPwrInDbm(
83 struct ieee80211_device *dev,
84 u8 Channel
85 );
86
87void
88DOT11D_ScanComplete(
89 struct ieee80211_device * dev
90 );
91
92int IsLegalChannel(
93 struct ieee80211_device * dev,
94 u8 channel
95);
96
97int ToLegalChannel(
98 struct ieee80211_device * dev,
99 u8 channel
100);
101#endif //ENABLE_DOT11D
102#endif // #ifndef __INC_DOT11D_H
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211.h b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
new file mode 100644
index 00000000000..6d7963e5b6a
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
@@ -0,0 +1,2636 @@
1/*
2 * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11
3 * remains copyright by the original authors
4 *
5 * Portions of the merged code are based on Host AP (software wireless
6 * LAN access point) driver for Intersil Prism2/2.5/3.
7 *
8 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
9 * <jkmaline@cc.hut.fi>
10 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
11 *
12 * Adaption to a generic IEEE 802.11 stack by James Ketrenos
13 * <jketreno@linux.intel.com>
14 * Copyright (c) 2004, Intel Corporation
15 *
16 * Modified for Realtek's wi-fi cards by Andrea Merello
17 * <andreamrl@tiscali.it>
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License version 2 as
21 * published by the Free Software Foundation. See README and COPYING for
22 * more details.
23 */
24#ifndef IEEE80211_H
25#define IEEE80211_H
26#include <linux/if_ether.h> /* ETH_ALEN */
27#include <linux/kernel.h> /* ARRAY_SIZE */
28#include <linux/module.h>
29#include <linux/jiffies.h>
30#include <linux/timer.h>
31#include <linux/sched.h>
32#include <linux/semaphore.h>
33#include <linux/interrupt.h>
34
35#include <linux/delay.h>
36#include <linux/wireless.h>
37
38#include "rtl819x_HT.h"
39#include "rtl819x_BA.h"
40#include "rtl819x_TS.h"
41
42#ifndef IW_MODE_MONITOR
43#define IW_MODE_MONITOR 6
44#endif
45
46#ifndef IWEVCUSTOM
47#define IWEVCUSTOM 0x8c02
48#endif
49
50#ifndef container_of
51/**
52 * container_of - cast a member of a structure out to the containing structure
53 *
54 * @ptr: the pointer to the member.
55 * @type: the type of the container struct this is embedded in.
56 * @member: the name of the member within the struct.
57 *
58 */
59#define container_of(ptr, type, member) ({ \
60 const typeof( ((type *)0)->member ) *__mptr = (ptr); \
61 (type *)( (char *)__mptr - offsetof(type,member) );})
62#endif
63
64#define KEY_TYPE_NA 0x0
65#define KEY_TYPE_WEP40 0x1
66#define KEY_TYPE_TKIP 0x2
67#define KEY_TYPE_CCMP 0x4
68#define KEY_TYPE_WEP104 0x5
69
70/* added for rtl819x tx procedure */
71#define MAX_QUEUE_SIZE 0x10
72
73//
74// 8190 queue mapping
75//
76#define BK_QUEUE 0
77#define BE_QUEUE 1
78#define VI_QUEUE 2
79#define VO_QUEUE 3
80#define HCCA_QUEUE 4
81#define TXCMD_QUEUE 5
82#define MGNT_QUEUE 6
83#define HIGH_QUEUE 7
84#define BEACON_QUEUE 8
85
86#define LOW_QUEUE BE_QUEUE
87#define NORMAL_QUEUE MGNT_QUEUE
88
89//added by amy for ps
90#define SWRF_TIMEOUT 50
91
92//added by amy for LEAP related
93#define IE_CISCO_FLAG_POSITION 0x08 // Flag byte: byte 8, numbered from 0.
94#define SUPPORT_CKIP_MIC 0x08 // bit3
95#define SUPPORT_CKIP_PK 0x10 // bit4
96/* defined for skb cb field */
97/* At most 28 byte */
98typedef struct cb_desc {
99 /* Tx Desc Related flags (8-9) */
100 u8 bLastIniPkt:1;
101 u8 bCmdOrInit:1;
102 u8 bFirstSeg:1;
103 u8 bLastSeg:1;
104 u8 bEncrypt:1;
105 u8 bTxDisableRateFallBack:1;
106 u8 bTxUseDriverAssingedRate:1;
107 u8 bHwSec:1; //indicate whether use Hw security. WB
108
109 u8 reserved1;
110
111 /* Tx Firmware Relaged flags (10-11)*/
112 u8 bCTSEnable:1;
113 u8 bRTSEnable:1;
114 u8 bUseShortGI:1;
115 u8 bUseShortPreamble:1;
116 u8 bTxEnableFwCalcDur:1;
117 u8 bAMPDUEnable:1;
118 u8 bRTSSTBC:1;
119 u8 RTSSC:1;
120
121 u8 bRTSBW:1;
122 u8 bPacketBW:1;
123 u8 bRTSUseShortPreamble:1;
124 u8 bRTSUseShortGI:1;
125 u8 bMulticast:1;
126 u8 bBroadcast:1;
127 //u8 reserved2:2;
128 u8 drv_agg_enable:1;
129 u8 reserved2:1;
130
131 /* Tx Desc related element(12-19) */
132 u8 rata_index;
133 u8 queue_index;
134 //u8 reserved3;
135 //u8 reserved4;
136 u16 txbuf_size;
137 //u8 reserved5;
138 u8 RATRIndex;
139 u8 reserved6;
140 u8 reserved7;
141 u8 reserved8;
142
143 /* Tx firmware related element(20-27) */
144 u8 data_rate;
145 u8 rts_rate;
146 u8 ampdu_factor;
147 u8 ampdu_density;
148 //u8 reserved9;
149 //u8 reserved10;
150 //u8 reserved11;
151 u8 DrvAggrNum;
152 u16 pkt_size;
153 u8 reserved12;
154
155 u8 bdhcp;
156}cb_desc, *pcb_desc;
157
158/*--------------------------Define -------------------------------------------*/
159#define MGN_1M 0x02
160#define MGN_2M 0x04
161#define MGN_5_5M 0x0b
162#define MGN_11M 0x16
163
164#define MGN_6M 0x0c
165#define MGN_9M 0x12
166#define MGN_12M 0x18
167#define MGN_18M 0x24
168#define MGN_24M 0x30
169#define MGN_36M 0x48
170#define MGN_48M 0x60
171#define MGN_54M 0x6c
172
173#define MGN_MCS0 0x80
174#define MGN_MCS1 0x81
175#define MGN_MCS2 0x82
176#define MGN_MCS3 0x83
177#define MGN_MCS4 0x84
178#define MGN_MCS5 0x85
179#define MGN_MCS6 0x86
180#define MGN_MCS7 0x87
181#define MGN_MCS8 0x88
182#define MGN_MCS9 0x89
183#define MGN_MCS10 0x8a
184#define MGN_MCS11 0x8b
185#define MGN_MCS12 0x8c
186#define MGN_MCS13 0x8d
187#define MGN_MCS14 0x8e
188#define MGN_MCS15 0x8f
189
190//----------------------------------------------------------------------------
191// 802.11 Management frame Reason Code field
192//----------------------------------------------------------------------------
193enum _ReasonCode{
194 unspec_reason = 0x1,
195 auth_not_valid = 0x2,
196 deauth_lv_ss = 0x3,
197 inactivity = 0x4,
198 ap_overload = 0x5,
199 class2_err = 0x6,
200 class3_err = 0x7,
201 disas_lv_ss = 0x8,
202 asoc_not_auth = 0x9,
203
204 //----MIC_CHECK
205 mic_failure = 0xe,
206 //----END MIC_CHECK
207
208 // Reason code defined in 802.11i D10.0 p.28.
209 invalid_IE = 0x0d,
210 four_way_tmout = 0x0f,
211 two_way_tmout = 0x10,
212 IE_dismatch = 0x11,
213 invalid_Gcipher = 0x12,
214 invalid_Pcipher = 0x13,
215 invalid_AKMP = 0x14,
216 unsup_RSNIEver = 0x15,
217 invalid_RSNIE = 0x16,
218 auth_802_1x_fail= 0x17,
219 ciper_reject = 0x18,
220
221 // Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie, 2005-11-15.
222 QoS_unspec = 0x20, // 32
223 QAP_bandwidth = 0x21, // 33
224 poor_condition = 0x22, // 34
225 no_facility = 0x23, // 35
226 // Where is 36???
227 req_declined = 0x25, // 37
228 invalid_param = 0x26, // 38
229 req_not_honored= 0x27, // 39
230 TS_not_created = 0x2F, // 47
231 DL_not_allowed = 0x30, // 48
232 dest_not_exist = 0x31, // 49
233 dest_not_QSTA = 0x32, // 50
234};
235
236
237
238#define aSifsTime (((priv->ieee80211->current_network.mode == IEEE_A)||(priv->ieee80211->current_network.mode == IEEE_N_24G)||(priv->ieee80211->current_network.mode == IEEE_N_5G))? 16 : 10)
239
240#define MGMT_QUEUE_NUM 5
241
242#define IEEE_CMD_SET_WPA_PARAM 1
243#define IEEE_CMD_SET_WPA_IE 2
244#define IEEE_CMD_SET_ENCRYPTION 3
245#define IEEE_CMD_MLME 4
246
247#define IEEE_PARAM_WPA_ENABLED 1
248#define IEEE_PARAM_TKIP_COUNTERMEASURES 2
249#define IEEE_PARAM_DROP_UNENCRYPTED 3
250#define IEEE_PARAM_PRIVACY_INVOKED 4
251#define IEEE_PARAM_AUTH_ALGS 5
252#define IEEE_PARAM_IEEE_802_1X 6
253//It should consistent with the driver_XXX.c
254// David, 2006.9.26
255#define IEEE_PARAM_WPAX_SELECT 7
256//Added for notify the encryption type selection
257// David, 2006.9.26
258#define IEEE_PROTO_WPA 1
259#define IEEE_PROTO_RSN 2
260//Added for notify the encryption type selection
261// David, 2006.9.26
262#define IEEE_WPAX_USEGROUP 0
263#define IEEE_WPAX_WEP40 1
264#define IEEE_WPAX_TKIP 2
265#define IEEE_WPAX_WRAP 3
266#define IEEE_WPAX_CCMP 4
267#define IEEE_WPAX_WEP104 5
268
269#define IEEE_KEY_MGMT_IEEE8021X 1
270#define IEEE_KEY_MGMT_PSK 2
271
272#define IEEE_MLME_STA_DEAUTH 1
273#define IEEE_MLME_STA_DISASSOC 2
274
275
276#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2
277#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3
278#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4
279#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5
280#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6
281#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7
282
283
284#define IEEE_CRYPT_ALG_NAME_LEN 16
285
286#define MAX_IE_LEN 0xff
287
288// added for kernel conflict
289#define ieee80211_crypt_deinit_entries ieee80211_crypt_deinit_entries_rsl
290#define ieee80211_crypt_deinit_handler ieee80211_crypt_deinit_handler_rsl
291#define ieee80211_crypt_delayed_deinit ieee80211_crypt_delayed_deinit_rsl
292#define ieee80211_register_crypto_ops ieee80211_register_crypto_ops_rsl
293#define ieee80211_unregister_crypto_ops ieee80211_unregister_crypto_ops_rsl
294#define ieee80211_get_crypto_ops ieee80211_get_crypto_ops_rsl
295
296#define ieee80211_ccmp_null ieee80211_ccmp_null_rsl
297
298#define ieee80211_tkip_null ieee80211_tkip_null_rsl
299
300#define ieee80211_wep_null ieee80211_wep_null_rsl
301
302#define free_ieee80211 free_ieee80211_rsl
303#define alloc_ieee80211 alloc_ieee80211_rsl
304
305#define ieee80211_rx ieee80211_rx_rsl
306#define ieee80211_rx_mgt ieee80211_rx_mgt_rsl
307
308#define ieee80211_get_beacon ieee80211_get_beacon_rsl
309#define ieee80211_rtl_wake_queue ieee80211_rtl_wake_queue_rsl
310#define ieee80211_rtl_stop_queue ieee80211_rtl_stop_queue_rsl
311#define ieee80211_reset_queue ieee80211_reset_queue_rsl
312#define ieee80211_softmac_stop_protocol ieee80211_softmac_stop_protocol_rsl
313#define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl
314#define ieee80211_is_shortslot ieee80211_is_shortslot_rsl
315#define ieee80211_is_54g ieee80211_is_54g_rsl
316#define ieee80211_wpa_supplicant_ioctl ieee80211_wpa_supplicant_ioctl_rsl
317#define ieee80211_ps_tx_ack ieee80211_ps_tx_ack_rsl
318#define ieee80211_softmac_xmit ieee80211_softmac_xmit_rsl
319#define ieee80211_stop_send_beacons ieee80211_stop_send_beacons_rsl
320#define notify_wx_assoc_event notify_wx_assoc_event_rsl
321#define SendDisassociation SendDisassociation_rsl
322#define ieee80211_disassociate ieee80211_disassociate_rsl
323#define ieee80211_start_send_beacons ieee80211_start_send_beacons_rsl
324#define ieee80211_stop_scan ieee80211_stop_scan_rsl
325#define ieee80211_send_probe_requests ieee80211_send_probe_requests_rsl
326#define ieee80211_softmac_scan_syncro ieee80211_softmac_scan_syncro_rsl
327#define ieee80211_start_scan_syncro ieee80211_start_scan_syncro_rsl
328
329#define ieee80211_wx_get_essid ieee80211_wx_get_essid_rsl
330#define ieee80211_wx_set_essid ieee80211_wx_set_essid_rsl
331#define ieee80211_wx_set_rate ieee80211_wx_set_rate_rsl
332#define ieee80211_wx_get_rate ieee80211_wx_get_rate_rsl
333#define ieee80211_wx_set_wap ieee80211_wx_set_wap_rsl
334#define ieee80211_wx_get_wap ieee80211_wx_get_wap_rsl
335#define ieee80211_wx_set_mode ieee80211_wx_set_mode_rsl
336#define ieee80211_wx_get_mode ieee80211_wx_get_mode_rsl
337#define ieee80211_wx_set_scan ieee80211_wx_set_scan_rsl
338#define ieee80211_wx_get_freq ieee80211_wx_get_freq_rsl
339#define ieee80211_wx_set_freq ieee80211_wx_set_freq_rsl
340#define ieee80211_wx_set_rawtx ieee80211_wx_set_rawtx_rsl
341#define ieee80211_wx_get_name ieee80211_wx_get_name_rsl
342#define ieee80211_wx_set_power ieee80211_wx_set_power_rsl
343#define ieee80211_wx_get_power ieee80211_wx_get_power_rsl
344#define ieee80211_wlan_frequencies ieee80211_wlan_frequencies_rsl
345#define ieee80211_wx_set_rts ieee80211_wx_set_rts_rsl
346#define ieee80211_wx_get_rts ieee80211_wx_get_rts_rsl
347
348#define ieee80211_txb_free ieee80211_txb_free_rsl
349
350#define ieee80211_wx_set_gen_ie ieee80211_wx_set_gen_ie_rsl
351#define ieee80211_wx_get_scan ieee80211_wx_get_scan_rsl
352#define ieee80211_wx_set_encode ieee80211_wx_set_encode_rsl
353#define ieee80211_wx_get_encode ieee80211_wx_get_encode_rsl
354#define ieee80211_wx_set_mlme ieee80211_wx_set_mlme_rsl
355#define ieee80211_wx_set_auth ieee80211_wx_set_auth_rsl
356#define ieee80211_wx_set_encode_ext ieee80211_wx_set_encode_ext_rsl
357#define ieee80211_wx_get_encode_ext ieee80211_wx_get_encode_ext_rsl
358
359
360typedef struct ieee_param {
361 u32 cmd;
362 u8 sta_addr[ETH_ALEN];
363 union {
364 struct {
365 u8 name;
366 u32 value;
367 } wpa_param;
368 struct {
369 u32 len;
370 u8 reserved[32];
371 u8 data[0];
372 } wpa_ie;
373 struct{
374 int command;
375 int reason_code;
376 } mlme;
377 struct {
378 u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
379 u8 set_tx;
380 u32 err;
381 u8 idx;
382 u8 seq[8]; /* sequence counter (set: RX, get: TX) */
383 u16 key_len;
384 u8 key[0];
385 } crypt;
386 } u;
387}ieee_param;
388
389
390// linux under 2.6.9 release may not support it, so modify it for common use
391#define MSECS(t) msecs_to_jiffies(t)
392#define msleep_interruptible_rsl msleep_interruptible
393
394#define IEEE80211_DATA_LEN 2304
395/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
396 6.2.1.1.2.
397
398 The figure in section 7.1.2 suggests a body size of up to 2312
399 bytes is allowed, which is a bit confusing, I suspect this
400 represents the 2304 bytes of real data, plus a possible 8 bytes of
401 WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
402#define IEEE80211_1ADDR_LEN 10
403#define IEEE80211_2ADDR_LEN 16
404#define IEEE80211_3ADDR_LEN 24
405#define IEEE80211_4ADDR_LEN 30
406#define IEEE80211_FCS_LEN 4
407#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
408#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
409#define IEEE80211_MGMT_HDR_LEN 24
410#define IEEE80211_DATA_HDR3_LEN 24
411#define IEEE80211_DATA_HDR4_LEN 30
412
413#define MIN_FRAG_THRESHOLD 256U
414#define MAX_FRAG_THRESHOLD 2346U
415
416
417/* Frame control field constants */
418#define IEEE80211_FCTL_VERS 0x0003
419#define IEEE80211_FCTL_FTYPE 0x000c
420#define IEEE80211_FCTL_STYPE 0x00f0
421#define IEEE80211_FCTL_FRAMETYPE 0x00fc
422#define IEEE80211_FCTL_TODS 0x0100
423#define IEEE80211_FCTL_FROMDS 0x0200
424#define IEEE80211_FCTL_DSTODS 0x0300 //added by david
425#define IEEE80211_FCTL_MOREFRAGS 0x0400
426#define IEEE80211_FCTL_RETRY 0x0800
427#define IEEE80211_FCTL_PM 0x1000
428#define IEEE80211_FCTL_MOREDATA 0x2000
429#define IEEE80211_FCTL_WEP 0x4000
430#define IEEE80211_FCTL_ORDER 0x8000
431
432#define IEEE80211_FTYPE_MGMT 0x0000
433#define IEEE80211_FTYPE_CTL 0x0004
434#define IEEE80211_FTYPE_DATA 0x0008
435
436/* management */
437#define IEEE80211_STYPE_ASSOC_REQ 0x0000
438#define IEEE80211_STYPE_ASSOC_RESP 0x0010
439#define IEEE80211_STYPE_REASSOC_REQ 0x0020
440#define IEEE80211_STYPE_REASSOC_RESP 0x0030
441#define IEEE80211_STYPE_PROBE_REQ 0x0040
442#define IEEE80211_STYPE_PROBE_RESP 0x0050
443#define IEEE80211_STYPE_BEACON 0x0080
444#define IEEE80211_STYPE_ATIM 0x0090
445#define IEEE80211_STYPE_DISASSOC 0x00A0
446#define IEEE80211_STYPE_AUTH 0x00B0
447#define IEEE80211_STYPE_DEAUTH 0x00C0
448#define IEEE80211_STYPE_MANAGE_ACT 0x00D0
449
450/* control */
451#define IEEE80211_STYPE_PSPOLL 0x00A0
452#define IEEE80211_STYPE_RTS 0x00B0
453#define IEEE80211_STYPE_CTS 0x00C0
454#define IEEE80211_STYPE_ACK 0x00D0
455#define IEEE80211_STYPE_CFEND 0x00E0
456#define IEEE80211_STYPE_CFENDACK 0x00F0
457#define IEEE80211_STYPE_BLOCKACK 0x0094
458
459/* data */
460#define IEEE80211_STYPE_DATA 0x0000
461#define IEEE80211_STYPE_DATA_CFACK 0x0010
462#define IEEE80211_STYPE_DATA_CFPOLL 0x0020
463#define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030
464#define IEEE80211_STYPE_NULLFUNC 0x0040
465#define IEEE80211_STYPE_CFACK 0x0050
466#define IEEE80211_STYPE_CFPOLL 0x0060
467#define IEEE80211_STYPE_CFACKPOLL 0x0070
468#define IEEE80211_STYPE_QOS_DATA 0x0080 //added for WMM 2006/8/2
469#define IEEE80211_STYPE_QOS_NULL 0x00C0
470
471#define IEEE80211_SCTL_FRAG 0x000F
472#define IEEE80211_SCTL_SEQ 0xFFF0
473
474/* QOS control */
475#define IEEE80211_QCTL_TID 0x000F
476
477#define FC_QOS_BIT BIT7
478#define IsDataFrame(pdu) ( ((pdu[0] & 0x0C)==0x08) ? true : false )
479#define IsLegacyDataFrame(pdu) (IsDataFrame(pdu) && (!(pdu[0]&FC_QOS_BIT)) )
480//added by wb. Is this right?
481#define IsQoSDataFrame(pframe) ((*(u16*)pframe&(IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) == (IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA))
482#define Frame_Order(pframe) (*(u16*)pframe&IEEE80211_FCTL_ORDER)
483#define SN_LESS(a, b) (((a-b)&0x800)!=0)
484#define SN_EQUAL(a, b) (a == b)
485#define MAX_DEV_ADDR_SIZE 8
486typedef enum _ACT_CATEGORY{
487 ACT_CAT_QOS = 1,
488 ACT_CAT_DLS = 2,
489 ACT_CAT_BA = 3,
490 ACT_CAT_HT = 7,
491 ACT_CAT_WMM = 17,
492} ACT_CATEGORY, *PACT_CATEGORY;
493
494typedef enum _TS_ACTION{
495 ACT_ADDTSREQ = 0,
496 ACT_ADDTSRSP = 1,
497 ACT_DELTS = 2,
498 ACT_SCHEDULE = 3,
499} TS_ACTION, *PTS_ACTION;
500
501typedef enum _BA_ACTION{
502 ACT_ADDBAREQ = 0,
503 ACT_ADDBARSP = 1,
504 ACT_DELBA = 2,
505} BA_ACTION, *PBA_ACTION;
506
507typedef enum _InitialGainOpType{
508 IG_Backup=0,
509 IG_Restore,
510 IG_Max
511}InitialGainOpType;
512
513/* debug macros */
514#define CONFIG_IEEE80211_DEBUG
515#ifdef CONFIG_IEEE80211_DEBUG
516extern u32 ieee80211_debug_level;
517#define IEEE80211_DEBUG(level, fmt, args...) \
518do { if (ieee80211_debug_level & (level)) \
519 printk(KERN_DEBUG "ieee80211: " fmt, ## args); } while (0)
520//wb added to debug out data buf
521//if you want print DATA buffer related BA, please set ieee80211_debug_level to DATA|BA
522#define IEEE80211_DEBUG_DATA(level, data, datalen) \
523 do{ if ((ieee80211_debug_level & (level)) == (level)) \
524 { \
525 int i; \
526 u8* pdata = (u8*) data; \
527 printk(KERN_DEBUG "ieee80211: %s()\n", __FUNCTION__); \
528 for(i=0; i<(int)(datalen); i++) \
529 { \
530 printk("%2x ", pdata[i]); \
531 if ((i+1)%16 == 0) printk("\n"); \
532 } \
533 printk("\n"); \
534 } \
535 } while (0)
536#else
537#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
538#define IEEE80211_DEBUG_DATA(level, data, datalen) do {} while(0)
539#endif /* CONFIG_IEEE80211_DEBUG */
540
541/* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
542
543/*
544 * To use the debug system;
545 *
546 * If you are defining a new debug classification, simply add it to the #define
547 * list here in the form of:
548 *
549 * #define IEEE80211_DL_xxxx VALUE
550 *
551 * shifting value to the left one bit from the previous entry. xxxx should be
552 * the name of the classification (for example, WEP)
553 *
554 * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your
555 * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want
556 * to send output to that classification.
557 *
558 * To add your debug level to the list of levels seen when you perform
559 *
560 * % cat /proc/net/ipw/debug_level
561 *
562 * you simply need to add your entry to the ipw_debug_levels array.
563 *
564 * If you do not see debug_level in /proc/net/ipw then you do not have
565 * CONFIG_IEEE80211_DEBUG defined in your kernel configuration
566 *
567 */
568
569#define IEEE80211_DL_INFO (1<<0)
570#define IEEE80211_DL_WX (1<<1)
571#define IEEE80211_DL_SCAN (1<<2)
572#define IEEE80211_DL_STATE (1<<3)
573#define IEEE80211_DL_MGMT (1<<4)
574#define IEEE80211_DL_FRAG (1<<5)
575#define IEEE80211_DL_EAP (1<<6)
576#define IEEE80211_DL_DROP (1<<7)
577
578#define IEEE80211_DL_TX (1<<8)
579#define IEEE80211_DL_RX (1<<9)
580
581#define IEEE80211_DL_HT (1<<10) //HT
582#define IEEE80211_DL_BA (1<<11) //ba
583#define IEEE80211_DL_TS (1<<12) //TS
584#define IEEE80211_DL_QOS (1<<13)
585#define IEEE80211_DL_REORDER (1<<14)
586#define IEEE80211_DL_IOT (1<<15)
587#define IEEE80211_DL_IPS (1<<16)
588#define IEEE80211_DL_TRACE (1<<29) //trace function, need to user net_ratelimit() together in order not to print too much to the screen
589#define IEEE80211_DL_DATA (1<<30) //use this flag to control whether print data buf out.
590#define IEEE80211_DL_ERR (1<<31) //always open
591#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
592#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
593#define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a)
594
595#define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a)
596#define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a)
597#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a)
598#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a)
599#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a)
600#define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a)
601#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
602#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
603#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
604#define IEEE80211_DEBUG_QOS(f, a...) IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
605
606#ifdef CONFIG_IEEE80211_DEBUG
607/* Added by Annie, 2005-11-22. */
608#define MAX_STR_LEN 64
609/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. Annie, 2005-11-22.*/
610#define PRINTABLE(_ch) (_ch>'!' && _ch<'~')
611#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len) \
612 if((_Comp) & level) \
613 { \
614 int __i; \
615 u8 buffer[MAX_STR_LEN]; \
616 int length = (_Len<MAX_STR_LEN)? _Len : (MAX_STR_LEN-1) ; \
617 memset(buffer, 0, MAX_STR_LEN); \
618 memcpy(buffer, (u8 *)_Ptr, length ); \
619 for( __i=0; __i<MAX_STR_LEN; __i++ ) \
620 { \
621 if( !PRINTABLE(buffer[__i]) ) buffer[__i] = '?'; \
622 } \
623 buffer[length] = '\0'; \
624 printk("Rtl819x: "); \
625 printk(_TitleString); \
626 printk(": %d, <%s>\n", _Len, buffer); \
627 }
628#else
629#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len) do {} while (0)
630#endif
631
632#include <linux/netdevice.h>
633#include <linux/if_arp.h> /* ARPHRD_ETHER */
634
635#ifndef WIRELESS_SPY
636#define WIRELESS_SPY // enable iwspy support
637#endif
638#include <net/iw_handler.h> // new driver API
639
640#ifndef ETH_P_PAE
641#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
642#endif /* ETH_P_PAE */
643
644#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
645
646#ifndef ETH_P_80211_RAW
647#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
648#endif
649
650/* IEEE 802.11 defines */
651
652#define P80211_OUI_LEN 3
653
654struct ieee80211_snap_hdr {
655
656 u8 dsap; /* always 0xAA */
657 u8 ssap; /* always 0xAA */
658 u8 ctrl; /* always 0x03 */
659 u8 oui[P80211_OUI_LEN]; /* organizational universal id */
660
661} __attribute__ ((packed));
662
663#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
664
665#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS)
666#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
667#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
668#define WLAN_FC_MORE_DATA(fc) ((fc) & IEEE80211_FCTL_MOREDATA)
669
670
671#define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & IEEE80211_FCTL_FRAMETYPE)
672#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
673#define WLAN_GET_SEQ_SEQ(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
674
675/* Authentication algorithms */
676#define WLAN_AUTH_OPEN 0
677#define WLAN_AUTH_SHARED_KEY 1
678#define WLAN_AUTH_LEAP 2
679
680#define WLAN_AUTH_CHALLENGE_LEN 128
681
682#define WLAN_CAPABILITY_BSS (1<<0)
683#define WLAN_CAPABILITY_IBSS (1<<1)
684#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
685#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
686#define WLAN_CAPABILITY_PRIVACY (1<<4)
687#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
688#define WLAN_CAPABILITY_PBCC (1<<6)
689#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
690#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
691#define WLAN_CAPABILITY_QOS (1<<9)
692#define WLAN_CAPABILITY_SHORT_SLOT (1<<10)
693#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
694
695/* 802.11g ERP information element */
696#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
697#define WLAN_ERP_USE_PROTECTION (1<<1)
698#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
699
700/* Status codes */
701enum ieee80211_statuscode {
702 WLAN_STATUS_SUCCESS = 0,
703 WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
704 WLAN_STATUS_CAPS_UNSUPPORTED = 10,
705 WLAN_STATUS_REASSOC_NO_ASSOC = 11,
706 WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
707 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
708 WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
709 WLAN_STATUS_CHALLENGE_FAIL = 15,
710 WLAN_STATUS_AUTH_TIMEOUT = 16,
711 WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
712 WLAN_STATUS_ASSOC_DENIED_RATES = 18,
713 /* 802.11b */
714 WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
715 WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
716 WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
717 /* 802.11h */
718 WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
719 WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
720 WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
721 /* 802.11g */
722 WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
723 WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
724 /* 802.11i */
725 WLAN_STATUS_INVALID_IE = 40,
726 WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
727 WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
728 WLAN_STATUS_INVALID_AKMP = 43,
729 WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
730 WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
731 WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
732};
733
734/* Reason codes */
735enum ieee80211_reasoncode {
736 WLAN_REASON_UNSPECIFIED = 1,
737 WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
738 WLAN_REASON_DEAUTH_LEAVING = 3,
739 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
740 WLAN_REASON_DISASSOC_AP_BUSY = 5,
741 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
742 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
743 WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
744 WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
745 /* 802.11h */
746 WLAN_REASON_DISASSOC_BAD_POWER = 10,
747 WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
748 /* 802.11i */
749 WLAN_REASON_INVALID_IE = 13,
750 WLAN_REASON_MIC_FAILURE = 14,
751 WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
752 WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
753 WLAN_REASON_IE_DIFFERENT = 17,
754 WLAN_REASON_INVALID_GROUP_CIPHER = 18,
755 WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
756 WLAN_REASON_INVALID_AKMP = 20,
757 WLAN_REASON_UNSUPP_RSN_VERSION = 21,
758 WLAN_REASON_INVALID_RSN_IE_CAP = 22,
759 WLAN_REASON_IEEE8021X_FAILED = 23,
760 WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
761};
762
763#define IEEE80211_STATMASK_SIGNAL (1<<0)
764#define IEEE80211_STATMASK_RSSI (1<<1)
765#define IEEE80211_STATMASK_NOISE (1<<2)
766#define IEEE80211_STATMASK_RATE (1<<3)
767#define IEEE80211_STATMASK_WEMASK 0x7
768
769#define IEEE80211_CCK_MODULATION (1<<0)
770#define IEEE80211_OFDM_MODULATION (1<<1)
771
772#define IEEE80211_24GHZ_BAND (1<<0)
773#define IEEE80211_52GHZ_BAND (1<<1)
774
775#define IEEE80211_CCK_RATE_LEN 4
776#define IEEE80211_CCK_RATE_1MB 0x02
777#define IEEE80211_CCK_RATE_2MB 0x04
778#define IEEE80211_CCK_RATE_5MB 0x0B
779#define IEEE80211_CCK_RATE_11MB 0x16
780#define IEEE80211_OFDM_RATE_LEN 8
781#define IEEE80211_OFDM_RATE_6MB 0x0C
782#define IEEE80211_OFDM_RATE_9MB 0x12
783#define IEEE80211_OFDM_RATE_12MB 0x18
784#define IEEE80211_OFDM_RATE_18MB 0x24
785#define IEEE80211_OFDM_RATE_24MB 0x30
786#define IEEE80211_OFDM_RATE_36MB 0x48
787#define IEEE80211_OFDM_RATE_48MB 0x60
788#define IEEE80211_OFDM_RATE_54MB 0x6C
789#define IEEE80211_BASIC_RATE_MASK 0x80
790
791#define IEEE80211_CCK_RATE_1MB_MASK (1<<0)
792#define IEEE80211_CCK_RATE_2MB_MASK (1<<1)
793#define IEEE80211_CCK_RATE_5MB_MASK (1<<2)
794#define IEEE80211_CCK_RATE_11MB_MASK (1<<3)
795#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4)
796#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5)
797#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6)
798#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7)
799#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8)
800#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9)
801#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10)
802#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11)
803
804#define IEEE80211_CCK_RATES_MASK 0x0000000F
805#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \
806 IEEE80211_CCK_RATE_2MB_MASK)
807#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \
808 IEEE80211_CCK_RATE_5MB_MASK | \
809 IEEE80211_CCK_RATE_11MB_MASK)
810
811#define IEEE80211_OFDM_RATES_MASK 0x00000FF0
812#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \
813 IEEE80211_OFDM_RATE_12MB_MASK | \
814 IEEE80211_OFDM_RATE_24MB_MASK)
815#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \
816 IEEE80211_OFDM_RATE_9MB_MASK | \
817 IEEE80211_OFDM_RATE_18MB_MASK | \
818 IEEE80211_OFDM_RATE_36MB_MASK | \
819 IEEE80211_OFDM_RATE_48MB_MASK | \
820 IEEE80211_OFDM_RATE_54MB_MASK)
821#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
822 IEEE80211_CCK_DEFAULT_RATES_MASK)
823
824#define IEEE80211_NUM_OFDM_RATES 8
825#define IEEE80211_NUM_CCK_RATES 4
826#define IEEE80211_OFDM_SHIFT_MASK_A 4
827
828
829/* this is stolen and modified from the madwifi driver*/
830#define IEEE80211_FC0_TYPE_MASK 0x0c
831#define IEEE80211_FC0_TYPE_DATA 0x08
832#define IEEE80211_FC0_SUBTYPE_MASK 0xB0
833#define IEEE80211_FC0_SUBTYPE_QOS 0x80
834
835#define IEEE80211_QOS_HAS_SEQ(fc) \
836 (((fc) & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == \
837 (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
838
839/* this is stolen from ipw2200 driver */
840#define IEEE_IBSS_MAC_HASH_SIZE 31
841struct ieee_ibss_seq {
842 u8 mac[ETH_ALEN];
843 u16 seq_num[17];
844 u16 frag_num[17];
845 unsigned long packet_time[17];
846 struct list_head list;
847};
848
849/* NOTE: This data is for statistical purposes; not all hardware provides this
850 * information for frames received. Not setting these will not cause
851 * any adverse affects. */
852struct ieee80211_rx_stats {
853 u32 mac_time[2];
854 s8 rssi;
855 u8 signal;
856 u8 noise;
857 u16 rate; /* in 100 kbps */
858 u8 received_channel;
859 u8 control;
860 u8 mask;
861 u8 freq;
862 u16 len;
863 u64 tsf;
864 u32 beacon_time;
865 u8 nic_type;
866 u16 Length;
867 u8 SignalQuality; // in 0-100 index.
868 s32 RecvSignalPower; // Real power in dBm for this packet, no beautification and aggregation.
869 s8 RxPower; // in dBm Translate from PWdB
870 u8 SignalStrength; // in 0-100 index.
871 u16 bHwError:1;
872 u16 bCRC:1;
873 u16 bICV:1;
874 u16 bShortPreamble:1;
875 u16 Antenna:1; //for rtl8185
876 u16 Decrypted:1; //for rtl8185, rtl8187
877 u16 Wakeup:1; //for rtl8185
878 u16 Reserved0:1; //for rtl8185
879 u8 AGC;
880 u32 TimeStampLow;
881 u32 TimeStampHigh;
882 bool bShift;
883 bool bIsQosData; // Added by Annie, 2005-12-22.
884 u8 UserPriority;
885
886 //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
887 //1Attention Please!!!<11n or 8190 specific code should be put below this line>
888 //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
889
890 u8 RxDrvInfoSize;
891 u8 RxBufShift;
892 bool bIsAMPDU;
893 bool bFirstMPDU;
894 bool bContainHTC;
895 u32 RxPWDBAll;
896 u8 RxMIMOSignalStrength[4]; // in 0~100 index
897 s8 RxMIMOSignalQuality[2];
898 bool bPacketMatchBSSID;
899 bool bIsCCK;
900 bool bPacketToSelf;
901 u8* virtual_address;
902 bool bPacketBeacon; //cosa add for rssi
903 bool bToSelfBA; //cosa add for rssi
904 char cck_adc_pwdb[4]; //cosa add for rx path selection
905};
906
907/* IEEE 802.11 requires that STA supports concurrent reception of at least
908 * three fragmented frames. This define can be increased to support more
909 * concurrent frames, but it should be noted that each entry can consume about
910 * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
911#define IEEE80211_FRAG_CACHE_LEN 4
912
913struct ieee80211_frag_entry {
914 unsigned long first_frag_time;
915 unsigned int seq;
916 unsigned int last_frag;
917 struct sk_buff *skb;
918 u8 src_addr[ETH_ALEN];
919 u8 dst_addr[ETH_ALEN];
920};
921
922struct ieee80211_stats {
923 unsigned int tx_unicast_frames;
924 unsigned int tx_multicast_frames;
925 unsigned int tx_fragments;
926 unsigned int tx_unicast_octets;
927 unsigned int tx_multicast_octets;
928 unsigned int tx_deferred_transmissions;
929 unsigned int tx_single_retry_frames;
930 unsigned int tx_multiple_retry_frames;
931 unsigned int tx_retry_limit_exceeded;
932 unsigned int tx_discards;
933 unsigned int rx_unicast_frames;
934 unsigned int rx_multicast_frames;
935 unsigned int rx_fragments;
936 unsigned int rx_unicast_octets;
937 unsigned int rx_multicast_octets;
938 unsigned int rx_fcs_errors;
939 unsigned int rx_discards_no_buffer;
940 unsigned int tx_discards_wrong_sa;
941 unsigned int rx_discards_undecryptable;
942 unsigned int rx_message_in_msg_fragments;
943 unsigned int rx_message_in_bad_msg_fragments;
944};
945
946struct ieee80211_device;
947
948#include "ieee80211_crypt.h"
949
950#define SEC_KEY_1 (1<<0)
951#define SEC_KEY_2 (1<<1)
952#define SEC_KEY_3 (1<<2)
953#define SEC_KEY_4 (1<<3)
954#define SEC_ACTIVE_KEY (1<<4)
955#define SEC_AUTH_MODE (1<<5)
956#define SEC_UNICAST_GROUP (1<<6)
957#define SEC_LEVEL (1<<7)
958#define SEC_ENABLED (1<<8)
959#define SEC_ENCRYPT (1<<9)
960
961#define SEC_LEVEL_0 0 /* None */
962#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */
963#define SEC_LEVEL_2 2 /* Level 1 + TKIP */
964#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
965#define SEC_LEVEL_3 4 /* Level 2 + CCMP */
966
967#define SEC_ALG_NONE 0
968#define SEC_ALG_WEP 1
969#define SEC_ALG_TKIP 2
970#define SEC_ALG_CCMP 4
971
972#define WEP_KEYS 4
973#define WEP_KEY_LEN 13
974#define SCM_KEY_LEN 32
975#define SCM_TEMPORAL_KEY_LENGTH 16
976
977struct ieee80211_security {
978 u16 active_key:2,
979 enabled:1,
980 auth_mode:2,
981 auth_algo:4,
982 unicast_uses_group:1,
983 encrypt:1;
984 u8 key_sizes[WEP_KEYS];
985 u8 keys[WEP_KEYS][SCM_KEY_LEN];
986 u8 level;
987 u16 flags;
988} __attribute__ ((packed));
989
990
991/*
992 802.11 data frame from AP
993 ,-------------------------------------------------------------------.
994Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
995 |------|------|---------|---------|---------|------|---------|------|
996Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs |
997 | | tion | (BSSID) | | | ence | data | |
998 `-------------------------------------------------------------------'
999Total: 28-2340 bytes
1000*/
1001
1002/* Management Frame Information Element Types */
1003enum ieee80211_mfie {
1004 MFIE_TYPE_SSID = 0,
1005 MFIE_TYPE_RATES = 1,
1006 MFIE_TYPE_FH_SET = 2,
1007 MFIE_TYPE_DS_SET = 3,
1008 MFIE_TYPE_CF_SET = 4,
1009 MFIE_TYPE_TIM = 5,
1010 MFIE_TYPE_IBSS_SET = 6,
1011 MFIE_TYPE_COUNTRY = 7,
1012 MFIE_TYPE_HOP_PARAMS = 8,
1013 MFIE_TYPE_HOP_TABLE = 9,
1014 MFIE_TYPE_REQUEST = 10,
1015 MFIE_TYPE_CHALLENGE = 16,
1016 MFIE_TYPE_POWER_CONSTRAINT = 32,
1017 MFIE_TYPE_POWER_CAPABILITY = 33,
1018 MFIE_TYPE_TPC_REQUEST = 34,
1019 MFIE_TYPE_TPC_REPORT = 35,
1020 MFIE_TYPE_SUPP_CHANNELS = 36,
1021 MFIE_TYPE_CSA = 37,
1022 MFIE_TYPE_MEASURE_REQUEST = 38,
1023 MFIE_TYPE_MEASURE_REPORT = 39,
1024 MFIE_TYPE_QUIET = 40,
1025 MFIE_TYPE_IBSS_DFS = 41,
1026 MFIE_TYPE_ERP = 42,
1027 MFIE_TYPE_RSN = 48,
1028 MFIE_TYPE_RATES_EX = 50,
1029 MFIE_TYPE_HT_CAP= 45,
1030 MFIE_TYPE_HT_INFO= 61,
1031 MFIE_TYPE_AIRONET=133,
1032 MFIE_TYPE_GENERIC = 221,
1033 MFIE_TYPE_QOS_PARAMETER = 222,
1034};
1035
1036/* Minimal header; can be used for passing 802.11 frames with sufficient
1037 * information to determine what type of underlying data type is actually
1038 * stored in the data. */
1039 struct ieee80211_pspoll_hdr {
1040 __le16 frame_ctl;
1041 __le16 aid;
1042 u8 bssid[ETH_ALEN];
1043 u8 ta[ETH_ALEN];
1044 //u8 payload[0];
1045} __attribute__ ((packed));
1046
1047struct ieee80211_hdr {
1048 __le16 frame_ctl;
1049 __le16 duration_id;
1050 u8 payload[0];
1051} __attribute__ ((packed));
1052
1053struct ieee80211_hdr_1addr {
1054 __le16 frame_ctl;
1055 __le16 duration_id;
1056 u8 addr1[ETH_ALEN];
1057 u8 payload[0];
1058} __attribute__ ((packed));
1059
1060struct ieee80211_hdr_2addr {
1061 __le16 frame_ctl;
1062 __le16 duration_id;
1063 u8 addr1[ETH_ALEN];
1064 u8 addr2[ETH_ALEN];
1065 u8 payload[0];
1066} __attribute__ ((packed));
1067
1068struct ieee80211_hdr_3addr {
1069 __le16 frame_ctl;
1070 __le16 duration_id;
1071 u8 addr1[ETH_ALEN];
1072 u8 addr2[ETH_ALEN];
1073 u8 addr3[ETH_ALEN];
1074 __le16 seq_ctl;
1075 u8 payload[0];
1076} __attribute__ ((packed));
1077
1078struct ieee80211_hdr_4addr {
1079 __le16 frame_ctl;
1080 __le16 duration_id;
1081 u8 addr1[ETH_ALEN];
1082 u8 addr2[ETH_ALEN];
1083 u8 addr3[ETH_ALEN];
1084 __le16 seq_ctl;
1085 u8 addr4[ETH_ALEN];
1086 u8 payload[0];
1087} __attribute__ ((packed));
1088
1089struct ieee80211_hdr_3addrqos {
1090 __le16 frame_ctl;
1091 __le16 duration_id;
1092 u8 addr1[ETH_ALEN];
1093 u8 addr2[ETH_ALEN];
1094 u8 addr3[ETH_ALEN];
1095 __le16 seq_ctl;
1096 u8 payload[0];
1097 __le16 qos_ctl;
1098} __attribute__ ((packed));
1099
1100struct ieee80211_hdr_4addrqos {
1101 __le16 frame_ctl;
1102 __le16 duration_id;
1103 u8 addr1[ETH_ALEN];
1104 u8 addr2[ETH_ALEN];
1105 u8 addr3[ETH_ALEN];
1106 __le16 seq_ctl;
1107 u8 addr4[ETH_ALEN];
1108 u8 payload[0];
1109 __le16 qos_ctl;
1110} __attribute__ ((packed));
1111
1112struct ieee80211_info_element {
1113 u8 id;
1114 u8 len;
1115 u8 data[0];
1116} __attribute__ ((packed));
1117
1118struct ieee80211_authentication {
1119 struct ieee80211_hdr_3addr header;
1120 __le16 algorithm;
1121 __le16 transaction;
1122 __le16 status;
1123 /*challenge*/
1124 struct ieee80211_info_element info_element[0];
1125} __attribute__ ((packed));
1126
1127struct ieee80211_disassoc {
1128 struct ieee80211_hdr_3addr header;
1129 __le16 reason;
1130} __attribute__ ((packed));
1131
1132struct ieee80211_probe_request {
1133 struct ieee80211_hdr_3addr header;
1134 /* SSID, supported rates */
1135 struct ieee80211_info_element info_element[0];
1136} __attribute__ ((packed));
1137
1138struct ieee80211_probe_response {
1139 struct ieee80211_hdr_3addr header;
1140 u32 time_stamp[2];
1141 __le16 beacon_interval;
1142 __le16 capability;
1143 /* SSID, supported rates, FH params, DS params,
1144 * CF params, IBSS params, TIM (if beacon), RSN */
1145 struct ieee80211_info_element info_element[0];
1146} __attribute__ ((packed));
1147
1148/* Alias beacon for probe_response */
1149#define ieee80211_beacon ieee80211_probe_response
1150
1151struct ieee80211_assoc_request_frame {
1152 struct ieee80211_hdr_3addr header;
1153 __le16 capability;
1154 __le16 listen_interval;
1155 /* SSID, supported rates, RSN */
1156 struct ieee80211_info_element info_element[0];
1157} __attribute__ ((packed));
1158
1159struct ieee80211_reassoc_request_frame {
1160 struct ieee80211_hdr_3addr header;
1161 __le16 capability;
1162 __le16 listen_interval;
1163 u8 current_ap[ETH_ALEN];
1164 /* SSID, supported rates, RSN */
1165 struct ieee80211_info_element info_element[0];
1166} __attribute__ ((packed));
1167
1168struct ieee80211_assoc_response_frame {
1169 struct ieee80211_hdr_3addr header;
1170 __le16 capability;
1171 __le16 status;
1172 __le16 aid;
1173 struct ieee80211_info_element info_element[0]; /* supported rates */
1174} __attribute__ ((packed));
1175
1176struct ieee80211_txb {
1177 u8 nr_frags;
1178 u8 encrypted;
1179 u8 queue_index;
1180 u8 rts_included;
1181 u16 reserved;
1182 __le16 frag_size;
1183 __le16 payload_size;
1184 struct sk_buff *fragments[0];
1185};
1186
1187#define MAX_TX_AGG_COUNT 16
1188struct ieee80211_drv_agg_txb {
1189 u8 nr_drv_agg_frames;
1190 struct sk_buff *tx_agg_frames[MAX_TX_AGG_COUNT];
1191}__attribute__((packed));
1192
1193#define MAX_SUBFRAME_COUNT 64
1194struct ieee80211_rxb {
1195 u8 nr_subframes;
1196 struct sk_buff *subframes[MAX_SUBFRAME_COUNT];
1197 u8 dst[ETH_ALEN];
1198 u8 src[ETH_ALEN];
1199}__attribute__((packed));
1200
1201typedef union _frameqos {
1202 u16 shortdata;
1203 u8 chardata[2];
1204 struct {
1205 u16 tid:4;
1206 u16 eosp:1;
1207 u16 ack_policy:2;
1208 u16 reserved:1;
1209 u16 txop:8;
1210 }field;
1211}frameqos,*pframeqos;
1212
1213/* SWEEP TABLE ENTRIES NUMBER*/
1214#define MAX_SWEEP_TAB_ENTRIES 42
1215#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7
1216/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs
1217 * only use 8, and then use extended rates for the remaining supported
1218 * rates. Other APs, however, stick all of their supported rates on the
1219 * main rates information element... */
1220#define MAX_RATES_LENGTH ((u8)12)
1221#define MAX_RATES_EX_LENGTH ((u8)16)
1222#define MAX_NETWORK_COUNT 128
1223
1224#define MAX_CHANNEL_NUMBER 161
1225#define IEEE80211_SOFTMAC_SCAN_TIME 100
1226//(HZ / 2)
1227#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2)
1228
1229#define CRC_LENGTH 4U
1230
1231#define MAX_WPA_IE_LEN 64
1232
1233#define NETWORK_EMPTY_ESSID (1<<0)
1234#define NETWORK_HAS_OFDM (1<<1)
1235#define NETWORK_HAS_CCK (1<<2)
1236
1237/* QoS structure */
1238#define NETWORK_HAS_QOS_PARAMETERS (1<<3)
1239#define NETWORK_HAS_QOS_INFORMATION (1<<4)
1240#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \
1241 NETWORK_HAS_QOS_INFORMATION)
1242/* 802.11h */
1243#define NETWORK_HAS_POWER_CONSTRAINT (1<<5)
1244#define NETWORK_HAS_CSA (1<<6)
1245#define NETWORK_HAS_QUIET (1<<7)
1246#define NETWORK_HAS_IBSS_DFS (1<<8)
1247#define NETWORK_HAS_TPC_REPORT (1<<9)
1248
1249#define NETWORK_HAS_ERP_VALUE (1<<10)
1250
1251#define QOS_QUEUE_NUM 4
1252#define QOS_OUI_LEN 3
1253#define QOS_OUI_TYPE 2
1254#define QOS_ELEMENT_ID 221
1255#define QOS_OUI_INFO_SUB_TYPE 0
1256#define QOS_OUI_PARAM_SUB_TYPE 1
1257#define QOS_VERSION_1 1
1258#define QOS_AIFSN_MIN_VALUE 2
1259
1260struct ieee80211_qos_information_element {
1261 u8 elementID;
1262 u8 length;
1263 u8 qui[QOS_OUI_LEN];
1264 u8 qui_type;
1265 u8 qui_subtype;
1266 u8 version;
1267 u8 ac_info;
1268} __attribute__ ((packed));
1269
1270struct ieee80211_qos_ac_parameter {
1271 u8 aci_aifsn;
1272 u8 ecw_min_max;
1273 __le16 tx_op_limit;
1274} __attribute__ ((packed));
1275
1276struct ieee80211_qos_parameter_info {
1277 struct ieee80211_qos_information_element info_element;
1278 u8 reserved;
1279 struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
1280} __attribute__ ((packed));
1281
1282struct ieee80211_qos_parameters {
1283 __le16 cw_min[QOS_QUEUE_NUM];
1284 __le16 cw_max[QOS_QUEUE_NUM];
1285 u8 aifs[QOS_QUEUE_NUM];
1286 u8 flag[QOS_QUEUE_NUM];
1287 __le16 tx_op_limit[QOS_QUEUE_NUM];
1288} __attribute__ ((packed));
1289
1290struct ieee80211_qos_data {
1291 struct ieee80211_qos_parameters parameters;
1292 int active;
1293 int supported;
1294 u8 param_count;
1295 u8 old_param_count;
1296};
1297
1298struct ieee80211_tim_parameters {
1299 u8 tim_count;
1300 u8 tim_period;
1301} __attribute__ ((packed));
1302
1303//#else
1304struct ieee80211_wmm_ac_param {
1305 u8 ac_aci_acm_aifsn;
1306 u8 ac_ecwmin_ecwmax;
1307 u16 ac_txop_limit;
1308};
1309
1310struct ieee80211_wmm_ts_info {
1311 u8 ac_dir_tid;
1312 u8 ac_up_psb;
1313 u8 reserved;
1314} __attribute__ ((packed));
1315
1316struct ieee80211_wmm_tspec_elem {
1317 struct ieee80211_wmm_ts_info ts_info;
1318 u16 norm_msdu_size;
1319 u16 max_msdu_size;
1320 u32 min_serv_inter;
1321 u32 max_serv_inter;
1322 u32 inact_inter;
1323 u32 suspen_inter;
1324 u32 serv_start_time;
1325 u32 min_data_rate;
1326 u32 mean_data_rate;
1327 u32 peak_data_rate;
1328 u32 max_burst_size;
1329 u32 delay_bound;
1330 u32 min_phy_rate;
1331 u16 surp_band_allow;
1332 u16 medium_time;
1333}__attribute__((packed));
1334
1335enum eap_type {
1336 EAP_PACKET = 0,
1337 EAPOL_START,
1338 EAPOL_LOGOFF,
1339 EAPOL_KEY,
1340 EAPOL_ENCAP_ASF_ALERT
1341};
1342
1343static const char *eap_types[] = {
1344 [EAP_PACKET] = "EAP-Packet",
1345 [EAPOL_START] = "EAPOL-Start",
1346 [EAPOL_LOGOFF] = "EAPOL-Logoff",
1347 [EAPOL_KEY] = "EAPOL-Key",
1348 [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert"
1349};
1350
1351static inline const char *eap_get_type(int type)
1352{
1353 return ((u32)type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type];
1354}
1355//added by amy for reorder
1356static inline u8 Frame_QoSTID(u8* buf)
1357{
1358 struct ieee80211_hdr_3addr *hdr;
1359 u16 fc;
1360 hdr = (struct ieee80211_hdr_3addr *)buf;
1361 fc = le16_to_cpu(hdr->frame_ctl);
1362 return (u8)((frameqos*)(buf + (((fc & IEEE80211_FCTL_TODS)&&(fc & IEEE80211_FCTL_FROMDS))? 30 : 24)))->field.tid;
1363}
1364
1365//added by amy for reorder
1366
1367struct eapol {
1368 u8 snap[6];
1369 u16 ethertype;
1370 u8 version;
1371 u8 type;
1372 u16 length;
1373} __attribute__ ((packed));
1374
1375struct ieee80211_softmac_stats{
1376 unsigned int rx_ass_ok;
1377 unsigned int rx_ass_err;
1378 unsigned int rx_probe_rq;
1379 unsigned int tx_probe_rs;
1380 unsigned int tx_beacons;
1381 unsigned int rx_auth_rq;
1382 unsigned int rx_auth_rs_ok;
1383 unsigned int rx_auth_rs_err;
1384 unsigned int tx_auth_rq;
1385 unsigned int no_auth_rs;
1386 unsigned int no_ass_rs;
1387 unsigned int tx_ass_rq;
1388 unsigned int rx_ass_rq;
1389 unsigned int tx_probe_rq;
1390 unsigned int reassoc;
1391 unsigned int swtxstop;
1392 unsigned int swtxawake;
1393 unsigned char CurrentShowTxate;
1394 unsigned char last_packet_rate;
1395 unsigned int txretrycount;
1396};
1397
1398#define BEACON_PROBE_SSID_ID_POSITION 12
1399
1400struct ieee80211_info_element_hdr {
1401 u8 id;
1402 u8 len;
1403} __attribute__ ((packed));
1404
1405/*
1406 * These are the data types that can make up management packets
1407 *
1408 u16 auth_algorithm;
1409 u16 auth_sequence;
1410 u16 beacon_interval;
1411 u16 capability;
1412 u8 current_ap[ETH_ALEN];
1413 u16 listen_interval;
1414 struct {
1415 u16 association_id:14, reserved:2;
1416 } __attribute__ ((packed));
1417 u32 time_stamp[2];
1418 u16 reason;
1419 u16 status;
1420*/
1421
1422#define IEEE80211_DEFAULT_TX_ESSID "Penguin"
1423#define IEEE80211_DEFAULT_BASIC_RATE 2 //1Mbps
1424
1425enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
1426#define MAX_SP_Len (WMM_all_frame << 4)
1427#define IEEE80211_QOS_TID 0x0f
1428#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5)
1429
1430#define IEEE80211_DTIM_MBCAST 4
1431#define IEEE80211_DTIM_UCAST 2
1432#define IEEE80211_DTIM_VALID 1
1433#define IEEE80211_DTIM_INVALID 0
1434
1435#define IEEE80211_PS_DISABLED 0
1436#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST
1437#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST
1438
1439//added by David for QoS 2006/6/30
1440//#define WMM_Hang_8187
1441#ifdef WMM_Hang_8187
1442#undef WMM_Hang_8187
1443#endif
1444
1445#define WME_AC_BK 0x00
1446#define WME_AC_BE 0x01
1447#define WME_AC_VI 0x02
1448#define WME_AC_VO 0x03
1449#define WME_ACI_MASK 0x03
1450#define WME_AIFSN_MASK 0x03
1451#define WME_AC_PRAM_LEN 16
1452
1453#define MAX_RECEIVE_BUFFER_SIZE 9100
1454
1455//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP
1456#define UP2AC(up) ( \
1457 ((up) < 1) ? WME_AC_BE : \
1458 ((up) < 3) ? WME_AC_BK : \
1459 ((up) < 4) ? WME_AC_BE : \
1460 ((up) < 6) ? WME_AC_VI : \
1461 WME_AC_VO)
1462
1463//AC Mapping to UP, using in Tx part for selecting the corresponding TX queue
1464#define AC2UP(_ac) ( \
1465 ((_ac) == WME_AC_VO) ? 6 : \
1466 ((_ac) == WME_AC_VI) ? 5 : \
1467 ((_ac) == WME_AC_BK) ? 1 : \
1468 0)
1469
1470#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */
1471#define ETHERNET_HEADER_SIZE 14 /* length of two Ethernet address plus ether type*/
1472
1473struct ether_header {
1474 u8 ether_dhost[ETHER_ADDR_LEN];
1475 u8 ether_shost[ETHER_ADDR_LEN];
1476 u16 ether_type;
1477} __attribute__((packed));
1478
1479#ifndef ETHERTYPE_PAE
1480#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */
1481#endif
1482#ifndef ETHERTYPE_IP
1483#define ETHERTYPE_IP 0x0800 /* IP protocol */
1484#endif
1485
1486typedef struct _bss_ht{
1487
1488 bool support_ht;
1489
1490 // HT related elements
1491 u8 ht_cap_buf[32];
1492 u16 ht_cap_len;
1493 u8 ht_info_buf[32];
1494 u16 ht_info_len;
1495
1496 HT_SPEC_VER ht_spec_ver;
1497
1498 bool aggregation;
1499 bool long_slot_time;
1500}bss_ht, *pbss_ht;
1501
1502typedef enum _erp_t{
1503 ERP_NonERPpresent = 0x01,
1504 ERP_UseProtection = 0x02,
1505 ERP_BarkerPreambleMode = 0x04,
1506} erp_t;
1507
1508
1509struct ieee80211_network {
1510 /* These entries are used to identify a unique network */
1511 u8 bssid[ETH_ALEN];
1512 u8 channel;
1513 /* Ensure null-terminated for any debug msgs */
1514 u8 ssid[IW_ESSID_MAX_SIZE + 1];
1515 u8 ssid_len;
1516 struct ieee80211_qos_data qos_data;
1517
1518 //added by amy for LEAP
1519 bool bWithAironetIE;
1520 bool bCkipSupported;
1521 bool bCcxRmEnable;
1522 u16 CcxRmState[2];
1523 // CCXv4 S59, MBSSID.
1524 bool bMBssidValid;
1525 u8 MBssidMask;
1526 u8 MBssid[6];
1527 // CCX 2 S38, WLAN Device Version Number element. Annie, 2006-08-20.
1528 bool bWithCcxVerNum;
1529 u8 BssCcxVerNumber;
1530 /* These are network statistics */
1531 struct ieee80211_rx_stats stats;
1532 u16 capability;
1533 u8 rates[MAX_RATES_LENGTH];
1534 u8 rates_len;
1535 u8 rates_ex[MAX_RATES_EX_LENGTH];
1536 u8 rates_ex_len;
1537 unsigned long last_scanned;
1538 u8 mode;
1539 u32 flags;
1540 u32 last_associate;
1541 u32 time_stamp[2];
1542 u16 beacon_interval;
1543 u16 listen_interval;
1544 u16 atim_window;
1545 u8 erp_value;
1546 u8 wpa_ie[MAX_WPA_IE_LEN];
1547 size_t wpa_ie_len;
1548 u8 rsn_ie[MAX_WPA_IE_LEN];
1549 size_t rsn_ie_len;
1550
1551 struct ieee80211_tim_parameters tim;
1552 u8 dtim_period;
1553 u8 dtim_data;
1554 u32 last_dtim_sta_time[2];
1555
1556 //appeded for QoS
1557 u8 wmm_info;
1558 struct ieee80211_wmm_ac_param wmm_param[4];
1559 u8 QoS_Enable;
1560#ifdef THOMAS_TURBO
1561 u8 Turbo_Enable;//enable turbo mode, added by thomas
1562#endif
1563#ifdef ENABLE_DOT11D
1564 u16 CountryIeLen;
1565 u8 CountryIeBuf[MAX_IE_LEN];
1566#endif
1567 // HT Related, by amy, 2008.04.29
1568 BSS_HT bssht;
1569 // Add to handle broadcom AP management frame CCK rate.
1570 bool broadcom_cap_exist;
1571 bool ralink_cap_exist;
1572 bool atheros_cap_exist;
1573 bool cisco_cap_exist;
1574 bool marvell_cap_exist;
1575 bool unknown_cap_exist;
1576// u8 berp_info;
1577 bool berp_info_valid;
1578 bool buseprotection;
1579 //put at the end of the structure.
1580 struct list_head list;
1581};
1582
1583enum ieee80211_state {
1584
1585 /* the card is not linked at all */
1586 IEEE80211_NOLINK = 0,
1587
1588 /* IEEE80211_ASSOCIATING* are for BSS client mode
1589 * the driver shall not perform RX filtering unless
1590 * the state is LINKED.
1591 * The driver shall just check for the state LINKED and
1592 * defaults to NOLINK for ALL the other states (including
1593 * LINKED_SCANNING)
1594 */
1595
1596 /* the association procedure will start (wq scheduling)*/
1597 IEEE80211_ASSOCIATING,
1598 IEEE80211_ASSOCIATING_RETRY,
1599
1600 /* the association procedure is sending AUTH request*/
1601 IEEE80211_ASSOCIATING_AUTHENTICATING,
1602
1603 /* the association procedure has successfully authentcated
1604 * and is sending association request
1605 */
1606 IEEE80211_ASSOCIATING_AUTHENTICATED,
1607
1608 /* the link is ok. the card associated to a BSS or linked
1609 * to a ibss cell or acting as an AP and creating the bss
1610 */
1611 IEEE80211_LINKED,
1612
1613 /* same as LINKED, but the driver shall apply RX filter
1614 * rules as we are in NO_LINK mode. As the card is still
1615 * logically linked, but it is doing a syncro site survey
1616 * then it will be back to LINKED state.
1617 */
1618 IEEE80211_LINKED_SCANNING,
1619
1620};
1621
1622#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
1623#define DEFAULT_FTS 2346
1624
1625#define CFG_IEEE80211_RESERVE_FCS (1<<0)
1626#define CFG_IEEE80211_COMPUTE_FCS (1<<1)
1627#define CFG_IEEE80211_RTS (1<<2)
1628
1629#define IEEE80211_24GHZ_MIN_CHANNEL 1
1630#define IEEE80211_24GHZ_MAX_CHANNEL 14
1631#define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \
1632 IEEE80211_24GHZ_MIN_CHANNEL + 1)
1633
1634#define IEEE80211_52GHZ_MIN_CHANNEL 34
1635#define IEEE80211_52GHZ_MAX_CHANNEL 165
1636#define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \
1637 IEEE80211_52GHZ_MIN_CHANNEL + 1)
1638
1639typedef struct tx_pending_t{
1640 int frag;
1641 struct ieee80211_txb *txb;
1642}tx_pending_t;
1643
1644typedef struct _bandwidth_autoswitch
1645{
1646 long threshold_20Mhzto40Mhz;
1647 long threshold_40Mhzto20Mhz;
1648 bool bforced_tx20Mhz;
1649 bool bautoswitch_enable;
1650}bandwidth_autoswitch,*pbandwidth_autoswitch;
1651
1652
1653//added by amy for order
1654
1655#define REORDER_WIN_SIZE 128
1656#define REORDER_ENTRY_NUM 128
1657typedef struct _RX_REORDER_ENTRY
1658{
1659 struct list_head List;
1660 u16 SeqNum;
1661 struct ieee80211_rxb* prxb;
1662} RX_REORDER_ENTRY, *PRX_REORDER_ENTRY;
1663//added by amy for order
1664typedef enum _Fsync_State{
1665 Default_Fsync,
1666 HW_Fsync,
1667 SW_Fsync
1668}Fsync_State;
1669
1670typedef struct _IbssParms{
1671 u16 atimWin;
1672}IbssParms, *PIbssParms;
1673#define MAX_NUM_RATES 264 // Max num of support rates element: 8, Max num of ext. support rate: 255. 061122, by rcnjko.
1674
1675#ifdef ENABLE_DOT11D
1676typedef enum
1677{
1678 COUNTRY_CODE_FCC = 0,
1679 COUNTRY_CODE_IC = 1,
1680 COUNTRY_CODE_ETSI = 2,
1681 COUNTRY_CODE_SPAIN = 3,
1682 COUNTRY_CODE_FRANCE = 4,
1683 COUNTRY_CODE_MKK = 5,
1684 COUNTRY_CODE_MKK1 = 6,
1685 COUNTRY_CODE_ISRAEL = 7,
1686 COUNTRY_CODE_TELEC,
1687 COUNTRY_CODE_MIC,
1688 COUNTRY_CODE_GLOBAL_DOMAIN
1689}country_code_type_t;
1690#endif
1691
1692#define RT_MAX_LD_SLOT_NUM 10
1693typedef struct _RT_LINK_DETECT_T{
1694
1695 u32 NumRecvBcnInPeriod;
1696 u32 NumRecvDataInPeriod;
1697
1698 u32 RxBcnNum[RT_MAX_LD_SLOT_NUM]; // number of Rx beacon / CheckForHang_period to determine link status
1699 u32 RxDataNum[RT_MAX_LD_SLOT_NUM]; // number of Rx data / CheckForHang_period to determine link status
1700 u16 SlotNum; // number of CheckForHang period to determine link status
1701 u16 SlotIndex;
1702
1703 u32 NumTxOkInPeriod;
1704 u32 NumRxOkInPeriod;
1705 u32 NumRxUnicastOkInPeriod;
1706 bool bBusyTraffic;
1707}RT_LINK_DETECT_T, *PRT_LINK_DETECT_T;
1708
1709//added by amy 090330
1710typedef enum _HW_VARIABLES{
1711 HW_VAR_ETHER_ADDR,
1712 HW_VAR_MULTICAST_REG,
1713 HW_VAR_BASIC_RATE,
1714 HW_VAR_BSSID,
1715 HW_VAR_MEDIA_STATUS,
1716 HW_VAR_SECURITY_CONF,
1717 HW_VAR_BEACON_INTERVAL,
1718 HW_VAR_ATIM_WINDOW,
1719 HW_VAR_LISTEN_INTERVAL,
1720 HW_VAR_CS_COUNTER,
1721 HW_VAR_DEFAULTKEY0,
1722 HW_VAR_DEFAULTKEY1,
1723 HW_VAR_DEFAULTKEY2,
1724 HW_VAR_DEFAULTKEY3,
1725 HW_VAR_SIFS,
1726 HW_VAR_DIFS,
1727 HW_VAR_EIFS,
1728 HW_VAR_SLOT_TIME,
1729 HW_VAR_ACK_PREAMBLE,
1730 HW_VAR_CW_CONFIG,
1731 HW_VAR_CW_VALUES,
1732 HW_VAR_RATE_FALLBACK_CONTROL,
1733 HW_VAR_CONTENTION_WINDOW,
1734 HW_VAR_RETRY_COUNT,
1735 HW_VAR_TR_SWITCH,
1736 HW_VAR_COMMAND, // For Command Register, Annie, 2006-04-07.
1737 HW_VAR_WPA_CONFIG, //2004/08/23, kcwu, for 8187 Security config
1738 HW_VAR_AMPDU_MIN_SPACE, // The spacing between sub-frame. Roger, 2008.07.04.
1739 HW_VAR_SHORTGI_DENSITY, // The density for shortGI. Roger, 2008.07.04.
1740 HW_VAR_AMPDU_FACTOR,
1741 HW_VAR_MCS_RATE_AVAILABLE,
1742 HW_VAR_AC_PARAM, // For AC Parameters, 2005.12.01, by rcnjko.
1743 HW_VAR_ACM_CTRL, // For ACM Control, Annie, 2005-12-13.
1744 HW_VAR_DIS_Req_Qsize, // For DIS_Reg_Qsize, Joseph
1745 HW_VAR_CCX_CHNL_LOAD, // For CCX 2 channel load request, 2006.05.04.
1746 HW_VAR_CCX_NOISE_HISTOGRAM, // For CCX 2 noise histogram request, 2006.05.04.
1747 HW_VAR_CCX_CLM_NHM, // For CCX 2 parallel channel load request and noise histogram request, 2006.05.12.
1748 HW_VAR_TxOPLimit, // For turbo mode related settings, added by Roger, 2006.12.07
1749 HW_VAR_TURBO_MODE, // For turbo mode related settings, added by Roger, 2006.12.15.
1750 HW_VAR_RF_STATE, // For change or query RF power state, 061214, rcnjko.
1751 HW_VAR_RF_OFF_BY_HW, // For UI to query if external HW signal disable RF, 061229, rcnjko.
1752 HW_VAR_BUS_SPEED, // In unit of bps. 2006.07.03, by rcnjko.
1753 HW_VAR_SET_DEV_POWER, // Set to low power, added by LanHsin, 2007.
1754
1755 //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
1756 //1Attention Please!!!<11n or 8190 specific code should be put below this line>
1757 //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
1758 HW_VAR_RCR, //for RCR, David 2006,05,11
1759 HW_VAR_RATR_0,
1760 HW_VAR_RRSR,
1761 HW_VAR_CPU_RST,
1762 HW_VAR_CHECK_BSSID,
1763 HW_VAR_LBK_MODE, // Set lookback mode, 2008.06.11. added by Roger.
1764 // Set HW related setting for 11N AES bug.
1765 HW_VAR_AES_11N_FIX,
1766 // Set Usb Rx Aggregation
1767 HW_VAR_USB_RX_AGGR,
1768 HW_VAR_USER_CONTROL_TURBO_MODE,
1769 HW_VAR_RETRY_LIMIT,
1770#ifndef _RTL8192_EXT_PATCH_
1771 HW_VAR_INIT_TX_RATE, //Get Current Tx rate register. 2008.12.10. Added by tynli
1772#endif
1773 HW_VAR_TX_RATE_REG, //Get Current Tx rate register. 2008.12.10. Added by tynli
1774 HW_VAR_EFUSE_USAGE, //Get current EFUSE utilization. 2008.12.19. Added by Roger.
1775 HW_VAR_EFUSE_BYTES,
1776 HW_VAR_AUTOLOAD_STATUS, //Get current autoload status, 0: autoload success, 1: autoload fail. 2008.12.19. Added by Roger.
1777 HW_VAR_RF_2R_DISABLE, // 2R disable
1778 HW_VAR_SET_RPWM,
1779 HW_VAR_H2C_FW_PWRMODE, // For setting FW related H2C cmd structure. by tynli. 2009.2.18
1780 HW_VAR_H2C_FW_JOINBSSRPT, // For setting FW related H2C cmd structure. by tynli. 2009.2.18
1781 HW_VAR_1X1_RECV_COMBINE, // For 1T2R but only 1SS, Add by hpfan 2009.04.16 hpfan
1782 HW_VAR_STOP_SEND_BEACON,
1783 HW_VAR_TSF_TIMER, // Read from TSF register to get the current TSF timer, by Bruce, 2009-07-22.
1784 HW_VAR_IO_CMD,
1785 HW_VAR_HANDLE_FW_C2H, //Added by tynli. For handling FW C2H command. 2009.10.07.
1786 HW_VAR_DL_FW_RSVD_PAGE, //Added by tynli. Download the packets that FW will use to RSVD page. 2009.10.14.
1787 HW_VAR_AID, //Added by tynli.
1788 HW_VAR_HW_SEQ_ENABLE, //Added by tynli. 2009.10.20.
1789 HW_VAR_UPDATE_TSF, //Added by tynli. 2009.10.22. For Hw count TBTT time.
1790 HW_VAR_BCN_VALID, //Added by tynli.
1791 HW_VAR_FWLPS_RF_ON //Added by tynli. 2009.11.09. For checking if Fw finishs RF on sequence.
1792}HW_VARIABLES;
1793
1794#define RT_CHECK_FOR_HANG_PERIOD 2
1795
1796struct ieee80211_device {
1797 struct net_device *dev;
1798 struct ieee80211_security sec;
1799
1800 bool need_sw_enc;
1801#ifdef ENABLE_LPS
1802 bool bAwakePktSent;
1803 u8 LPSDelayCnt;
1804 bool bIsAggregateFrame;
1805 bool polling;
1806 void (*LeisurePSLeave)(struct ieee80211_device *ieee);
1807#endif
1808
1809#ifdef ENABLE_IPS
1810 bool proto_stoppping;
1811 bool wx_set_enc;
1812 struct semaphore ips_sem;
1813 struct work_struct ips_leave_wq;
1814 void (*ieee80211_ips_leave_wq) (struct ieee80211_device *ieee);
1815 void (*ieee80211_ips_leave)(struct ieee80211_device *ieee);
1816#endif
1817 void (*SetHwRegHandler)(struct ieee80211_device *ieee, u8 variable, u8 *val);
1818 u8 (*rtllib_ap_sec_type)(struct ieee80211_device *ieee);
1819
1820 //hw security related
1821 u8 hwsec_active; //hw security active.
1822 bool is_silent_reset;
1823 bool is_roaming;
1824 bool ieee_up;
1825 bool bSupportRemoteWakeUp;
1826 bool actscanning;
1827 bool beinretry;
1828 bool is_set_key;
1829 //11n spec related I wonder if These info structure need to be moved out of ieee80211_device
1830
1831 //11n HT below
1832 PRT_HIGH_THROUGHPUT pHTInfo;
1833 spinlock_t bw_spinlock;
1834
1835 spinlock_t reorder_spinlock;
1836 // for HT operation rate set. we use this one for HT data rate to separate different descriptors
1837 //the way fill this is the same as in the IE
1838 u8 Regdot11HTOperationalRateSet[16]; //use RATR format
1839 u8 dot11HTOperationalRateSet[16]; //use RATR format
1840 u8 RegHTSuppRateSet[16];
1841 u8 HTCurrentOperaRate;
1842 u8 HTHighestOperaRate;
1843 //wb added for rate operation mode to firmware
1844 u8 bTxDisableRateFallBack;
1845 u8 bTxUseDriverAssingedRate;
1846 atomic_t atm_chnlop;
1847 atomic_t atm_swbw;
1848
1849 // 802.11e and WMM Traffic Stream Info (TX)
1850 struct list_head Tx_TS_Admit_List;
1851 struct list_head Tx_TS_Pending_List;
1852 struct list_head Tx_TS_Unused_List;
1853 TX_TS_RECORD TxTsRecord[TOTAL_TS_NUM];
1854 // 802.11e and WMM Traffic Stream Info (RX)
1855 struct list_head Rx_TS_Admit_List;
1856 struct list_head Rx_TS_Pending_List;
1857 struct list_head Rx_TS_Unused_List;
1858 RX_TS_RECORD RxTsRecord[TOTAL_TS_NUM];
1859 RX_REORDER_ENTRY RxReorderEntry[128];
1860 struct list_head RxReorder_Unused_List;
1861 u8 ForcedPriority; // Force per-packet priority 1~7. (default: 0, not to force it.)
1862
1863
1864 /* Bookkeeping structures */
1865 struct net_device_stats stats;
1866 struct ieee80211_stats ieee_stats;
1867 struct ieee80211_softmac_stats softmac_stats;
1868
1869 /* Probe / Beacon management */
1870 struct list_head network_free_list;
1871 struct list_head network_list;
1872 struct ieee80211_network *networks;
1873 int scans;
1874 int scan_age;
1875
1876 int iw_mode; /* operating mode (IW_MODE_*) */
1877 struct iw_spy_data spy_data;
1878
1879 spinlock_t lock;
1880 spinlock_t wpax_suitlist_lock;
1881
1882 int tx_headroom; /* Set to size of any additional room needed at front
1883 * of allocated Tx SKBs */
1884 u32 config;
1885
1886 /* WEP and other encryption related settings at the device level */
1887 int open_wep; /* Set to 1 to allow unencrypted frames */
1888 int auth_mode;
1889 int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
1890 * WEP key changes */
1891
1892 /* If the host performs {en,de}cryption, then set to 1 */
1893 int host_encrypt;
1894 int host_encrypt_msdu;
1895 int host_decrypt;
1896 /* host performs multicast decryption */
1897 int host_mc_decrypt;
1898
1899 /* host should strip IV and ICV from protected frames */
1900 /* meaningful only when hardware decryption is being used */
1901 int host_strip_iv_icv;
1902
1903 int host_open_frag;
1904 int host_build_iv;
1905 int ieee802_1x; /* is IEEE 802.1X used */
1906
1907 /* WPA data */
1908 bool bHalfWirelessN24GMode;
1909 int wpa_enabled;
1910 int drop_unencrypted;
1911 int tkip_countermeasures;
1912 int privacy_invoked;
1913 size_t wpa_ie_len;
1914 u8 *wpa_ie;
1915 u8 ap_mac_addr[6];
1916 u16 pairwise_key_type;
1917 u16 group_key_type;
1918 struct list_head crypt_deinit_list;
1919 struct ieee80211_crypt_data *crypt[WEP_KEYS];
1920 int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
1921 struct timer_list crypt_deinit_timer;
1922 int crypt_quiesced;
1923
1924 int bcrx_sta_key; /* use individual keys to override default keys even
1925 * with RX of broad/multicast frames */
1926
1927 /* Fragmentation structures */
1928 // each streaming contain a entry
1929 struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN];
1930 unsigned int frag_next_idx[17];
1931 u16 fts; /* Fragmentation Threshold */
1932#define DEFAULT_RTS_THRESHOLD 2346U
1933#define MIN_RTS_THRESHOLD 1
1934#define MAX_RTS_THRESHOLD 2346U
1935 u16 rts; /* RTS threshold */
1936
1937 /* Association info */
1938 u8 bssid[ETH_ALEN];
1939
1940 /* This stores infos for the current network.
1941 * Either the network we are associated in INFRASTRUCTURE
1942 * or the network that we are creating in MASTER mode.
1943 * ad-hoc is a mixture ;-).
1944 * Note that in infrastructure mode, even when not associated,
1945 * fields bssid and essid may be valid (if wpa_set and essid_set
1946 * are true) as thy carry the value set by the user via iwconfig
1947 */
1948 struct ieee80211_network current_network;
1949
1950 enum ieee80211_state state;
1951
1952 int short_slot;
1953 int reg_mode;
1954 int mode; /* A, B, G */
1955 int modulation; /* CCK, OFDM */
1956 int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */
1957 int abg_true; /* ABG flag */
1958
1959 /* used for forcing the ibss workqueue to terminate
1960 * without wait for the syncro scan to terminate
1961 */
1962 short sync_scan_hurryup;
1963
1964 int perfect_rssi;
1965 int worst_rssi;
1966
1967 u16 prev_seq_ctl; /* used to drop duplicate frames */
1968
1969 /* map of allowed channels. 0 is dummy */
1970 // FIXME: remember to default to a basic channel plan depending of the PHY type
1971#ifdef ENABLE_DOT11D
1972 void* pDot11dInfo;
1973 bool bGlobalDomain;
1974#else
1975 int channel_map[MAX_CHANNEL_NUMBER+1];
1976#endif
1977 int rate; /* current rate */
1978 int basic_rate;
1979 //FIXME: pleace callback, see if redundant with softmac_features
1980 short active_scan;
1981
1982 /* this contains flags for selectively enable softmac support */
1983 u16 softmac_features;
1984
1985 /* if the sequence control field is not filled by HW */
1986 u16 seq_ctrl[5];
1987
1988 /* association procedure transaction sequence number */
1989 u16 associate_seq;
1990
1991 /* AID for RTXed association responses */
1992 u16 assoc_id;
1993
1994 /* power save mode related*/
1995 u8 ack_tx_to_ieee;
1996 short ps;
1997 short sta_sleep;
1998 int ps_timeout;
1999 int ps_period;
2000 struct tasklet_struct ps_task;
2001 u32 ps_th;
2002 u32 ps_tl;
2003
2004 short raw_tx;
2005 /* used if IEEE_SOFTMAC_TX_QUEUE is set */
2006 short queue_stop;
2007 short scanning;
2008 short proto_started;
2009
2010 struct semaphore wx_sem;
2011 struct semaphore scan_sem;
2012
2013 spinlock_t mgmt_tx_lock;
2014 spinlock_t beacon_lock;
2015
2016 short beacon_txing;
2017
2018 short wap_set;
2019 short ssid_set;
2020
2021 u8 wpax_type_set; //{added by David, 2006.9.28}
2022 u32 wpax_type_notify; //{added by David, 2006.9.26}
2023
2024 /* QoS related flag */
2025 char init_wmmparam_flag;
2026 /* set on initialization */
2027 u8 qos_support;
2028
2029 /* for discarding duplicated packets in IBSS */
2030 struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE];
2031
2032 /* for discarding duplicated packets in BSS */
2033 u16 last_rxseq_num[17]; /* rx seq previous per-tid */
2034 u16 last_rxfrag_num[17];/* tx frag previous per-tid */
2035 unsigned long last_packet_time[17];
2036
2037 /* for PS mode */
2038 unsigned long last_rx_ps_time;
2039 u8 LPSAwakeIntvl;
2040 u8 RegMaxLPSAwakeIntvl;
2041
2042 /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */
2043 struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM];
2044 int mgmt_queue_head;
2045 int mgmt_queue_tail;
2046#define IEEE80211_QUEUE_LIMIT 128
2047 u8 AsocRetryCount;
2048 unsigned int hw_header;
2049 struct sk_buff_head skb_waitQ[MAX_QUEUE_SIZE];
2050 struct sk_buff_head skb_aggQ[MAX_QUEUE_SIZE];
2051 struct sk_buff_head skb_drv_aggQ[MAX_QUEUE_SIZE];
2052 u32 sta_edca_param[4];
2053 bool aggregation;
2054 // Enable/Disable Rx immediate BA capability.
2055 bool enable_rx_imm_BA;
2056 bool bibsscoordinator;
2057
2058 //+by amy for DM ,080515
2059 //Dynamic Tx power for near/far range enable/Disable , by amy , 2008-05-15
2060 bool bdynamic_txpower_enable;
2061
2062 bool bCTSToSelfEnable;
2063 u8 CTSToSelfTH;
2064
2065 u32 fsync_time_interval;
2066 u32 fsync_rate_bitmap;
2067 u8 fsync_rssi_threshold;
2068 bool bfsync_enable;
2069
2070 u8 fsync_multiple_timeinterval; // FsyncMultipleTimeInterval * FsyncTimeInterval
2071 u32 fsync_firstdiff_ratethreshold; // low threshold
2072 u32 fsync_seconddiff_ratethreshold; // decrease threshold
2073 Fsync_State fsync_state;
2074 bool bis_any_nonbepkts;
2075 //20Mhz 40Mhz AutoSwitch Threshold
2076 bandwidth_autoswitch bandwidth_auto_switch;
2077 //for txpower tracking
2078 bool FwRWRF;
2079
2080 //added by amy for AP roaming
2081 RT_LINK_DETECT_T LinkDetectInfo;
2082
2083 /* used if IEEE_SOFTMAC_TX_QUEUE is set */
2084 struct tx_pending_t tx_pending;
2085
2086 /* used if IEEE_SOFTMAC_ASSOCIATE is set */
2087 struct timer_list associate_timer;
2088
2089 /* used if IEEE_SOFTMAC_BEACONS is set */
2090 struct timer_list beacon_timer;
2091 struct work_struct associate_complete_wq;
2092 struct work_struct associate_procedure_wq;
2093 struct delayed_work softmac_scan_wq;
2094 struct delayed_work associate_retry_wq;
2095 struct delayed_work start_ibss_wq;
2096 struct delayed_work hw_wakeup_wq;
2097
2098 struct work_struct wx_sync_scan_wq;
2099 struct workqueue_struct *wq;
2100
2101 /* Callback functions */
2102 void (*set_security)(struct ieee80211_device *ieee,
2103 struct ieee80211_security *sec);
2104
2105 /* Used to TX data frame by using txb structs.
2106 * this is not used if in the softmac_features
2107 * is set the flag IEEE_SOFTMAC_TX_QUEUE
2108 */
2109 int (*hard_start_xmit)(struct ieee80211_txb *txb,
2110 struct ieee80211_device *ieee);
2111
2112 int (*reset_port)(struct ieee80211_device *ieee);
2113 int (*is_queue_full) (struct ieee80211_device *ieee, int pri);
2114
2115 int (*handle_management) (struct ieee80211_device *ieee,
2116 struct ieee80211_network * network, u16 type);
2117 int (*is_qos_active) (struct ieee80211_device *ieee, struct sk_buff *skb);
2118
2119 /* Softmac-generated frames (mamagement) are TXed via this
2120 * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
2121 * not set. As some cards may have different HW queues that
2122 * one might want to use for data and management frames
2123 * the option to have two callbacks might be useful.
2124 * This function can't sleep.
2125 */
2126 int (*softmac_hard_start_xmit)(struct sk_buff *skb,
2127 struct ieee80211_device *ieee80211);
2128
2129 /* used instead of hard_start_xmit (not softmac_hard_start_xmit)
2130 * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
2131 * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
2132 * then also management frames are sent via this callback.
2133 * This function can't sleep.
2134 */
2135 void (*softmac_data_hard_start_xmit)(struct sk_buff *skb,
2136 struct ieee80211_device *ieee80211, int rate);
2137
2138 /* stops the HW queue for DATA frames. Useful to avoid
2139 * waste time to TX data frame when we are reassociating
2140 * This function can sleep.
2141 */
2142 void (*data_hard_stop)(struct ieee80211_device *ieee80211);
2143
2144 /* OK this is complementar to data_poll_hard_stop */
2145 void (*data_hard_resume)(struct ieee80211_device *ieee80211);
2146
2147 /* ask to the driver to retune the radio .
2148 * This function can sleep. the driver should ensure
2149 * the radio has been swithced before return.
2150 */
2151 void (*set_chan)(struct ieee80211_device *ieee80211, short ch);
2152
2153 /* These are not used if the ieee stack takes care of
2154 * scanning (IEEE_SOFTMAC_SCAN feature set).
2155 * In this case only the set_chan is used.
2156 *
2157 * The syncro version is similar to the start_scan but
2158 * does not return until all channels has been scanned.
2159 * this is called in user context and should sleep,
2160 * it is called in a work_queue when swithcing to ad-hoc mode
2161 * or in behalf of iwlist scan when the card is associated
2162 * and root user ask for a scan.
2163 * the function stop_scan should stop both the syncro and
2164 * background scanning and can sleep.
2165 * The function start_scan should initiate the background
2166 * scanning and can't sleep.
2167 */
2168 void (*scan_syncro)(struct ieee80211_device *ieee80211);
2169 void (*start_scan)(struct ieee80211_device *ieee80211);
2170 void (*stop_scan)(struct ieee80211_device *ieee80211);
2171
2172 /* indicate the driver that the link state is changed
2173 * for example it may indicate the card is associated now.
2174 * Driver might be interested in this to apply RX filter
2175 * rules or simply light the LINK led
2176 */
2177 void (*link_change)(struct ieee80211_device *ieee80211);
2178
2179 /* these two function indicates to the HW when to start
2180 * and stop to send beacons. This is used when the
2181 * IEEE_SOFTMAC_BEACONS is not set. For now the
2182 * stop_send_bacons is NOT guaranteed to be called only
2183 * after start_send_beacons.
2184 */
2185 void (*start_send_beacons) (struct ieee80211_device *dev);
2186 void (*stop_send_beacons) (struct ieee80211_device *dev);
2187
2188 /* power save mode related */
2189 void (*sta_wake_up) (struct ieee80211_device *ieee80211);
2190 void (*enter_sleep_state) (struct ieee80211_device *ieee80211, u32 th, u32 tl);
2191 short (*ps_is_queue_empty) (struct ieee80211_device *ieee80211);
2192 int (*handle_beacon) (struct ieee80211_device *ieee80211, struct ieee80211_beacon *beacon, struct ieee80211_network *network);
2193 int (*handle_assoc_response) (struct ieee80211_device *ieee80211, struct ieee80211_assoc_response_frame *resp, struct ieee80211_network *network);
2194
2195 /* check whether Tx hw resouce available */
2196 short (*check_nic_enough_desc)(struct ieee80211_device *ieee80211, int queue_index);
2197 //added by wb for HT related
2198 void (*SetBWModeHandler)(struct ieee80211_device *ieee80211, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
2199 bool (*GetNmodeSupportBySecCfg)(struct ieee80211_device *ieee80211);
2200 void (*SetWirelessMode)(struct ieee80211_device *ieee80211, u8 wireless_mode);
2201 bool (*GetHalfNmodeSupportByAPsHandler)(struct ieee80211_device *ieee80211);
2202 void (*InitialGainHandler)(struct ieee80211_device *ieee80211, u8 Operation);
2203
2204 /* This must be the last item so that it points to the data
2205 * allocated beyond this structure by alloc_ieee80211 */
2206 u8 priv[0];
2207};
2208
2209#define RT_RF_OFF_LEVL_ASPM BIT0 // PCI ASPM
2210#define RT_RF_OFF_LEVL_CLK_REQ BIT1 // PCI clock request
2211#define RT_RF_OFF_LEVL_PCI_D3 BIT2 // PCI D3 mode
2212#define RT_RF_OFF_LEVL_HALT_NIC BIT3 // NIC halt, re-initialize hw parameters
2213#define RT_RF_OFF_LEVL_FREE_FW BIT4 // FW free, re-download the FW
2214#define RT_RF_OFF_LEVL_FW_32K BIT5 // FW in 32k
2215#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT6 // Always enable ASPM and Clock Req in initialization.
2216#define RT_RF_LPS_DISALBE_2R BIT30 // When LPS is on, disable 2R if no packet is received or transmittd.
2217#define RT_RF_LPS_LEVEL_ASPM BIT31 // LPS with ASPM
2218#define RT_IN_PS_LEVEL(pPSC, _PS_FLAG) ((pPSC->CurPsLevel & _PS_FLAG) ? true : false)
2219#define RT_CLEAR_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel &= (~(_PS_FLAG)))
2220#define RT_SET_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel |= _PS_FLAG)
2221
2222#define IEEE_A (1<<0)
2223#define IEEE_B (1<<1)
2224#define IEEE_G (1<<2)
2225#define IEEE_N_24G (1<<4)
2226#define IEEE_N_5G (1<<5)
2227#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G)
2228
2229/* Generate a 802.11 header */
2230
2231/* Uses the channel change callback directly
2232 * instead of [start/stop] scan callbacks
2233 */
2234#define IEEE_SOFTMAC_SCAN (1<<2)
2235
2236/* Perform authentication and association handshake */
2237#define IEEE_SOFTMAC_ASSOCIATE (1<<3)
2238
2239/* Generate probe requests */
2240#define IEEE_SOFTMAC_PROBERQ (1<<4)
2241
2242/* Generate respones to probe requests */
2243#define IEEE_SOFTMAC_PROBERS (1<<5)
2244
2245/* The ieee802.11 stack will manages the netif queue
2246 * wake/stop for the driver, taking care of 802.11
2247 * fragmentation. See softmac.c for details. */
2248#define IEEE_SOFTMAC_TX_QUEUE (1<<7)
2249
2250/* Uses only the softmac_data_hard_start_xmit
2251 * even for TX management frames.
2252 */
2253#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8)
2254
2255/* Generate beacons. The stack will enqueue beacons
2256 * to the card
2257 */
2258#define IEEE_SOFTMAC_BEACONS (1<<6)
2259
2260static inline void *ieee80211_priv(struct net_device *dev)
2261{
2262 return ((struct ieee80211_device *)netdev_priv(dev))->priv;
2263}
2264
2265extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
2266{
2267 /* Single white space is for Linksys APs */
2268 if (essid_len == 1 && essid[0] == ' ')
2269 return 1;
2270
2271 /* Otherwise, if the entire essid is 0, we assume it is hidden */
2272 while (essid_len) {
2273 essid_len--;
2274 if (essid[essid_len] != '\0')
2275 return 0;
2276 }
2277
2278 return 1;
2279}
2280
2281extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
2282{
2283 /*
2284 * It is possible for both access points and our device to support
2285 * combinations of modes, so as long as there is one valid combination
2286 * of ap/device supported modes, then return success
2287 *
2288 */
2289 if ((mode & IEEE_A) &&
2290 (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
2291 (ieee->freq_band & IEEE80211_52GHZ_BAND))
2292 return 1;
2293
2294 if ((mode & IEEE_G) &&
2295 (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
2296 (ieee->freq_band & IEEE80211_24GHZ_BAND))
2297 return 1;
2298
2299 if ((mode & IEEE_B) &&
2300 (ieee->modulation & IEEE80211_CCK_MODULATION) &&
2301 (ieee->freq_band & IEEE80211_24GHZ_BAND))
2302 return 1;
2303
2304 return 0;
2305}
2306
2307extern inline int ieee80211_get_hdrlen(u16 fc)
2308{
2309 int hdrlen = IEEE80211_3ADDR_LEN;
2310
2311 switch (WLAN_FC_GET_TYPE(fc)) {
2312 case IEEE80211_FTYPE_DATA:
2313 if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
2314 hdrlen = IEEE80211_4ADDR_LEN; /* Addr4 */
2315 if(IEEE80211_QOS_HAS_SEQ(fc))
2316 hdrlen += 2; /* QOS ctrl*/
2317 break;
2318 case IEEE80211_FTYPE_CTL:
2319 switch (WLAN_FC_GET_STYPE(fc)) {
2320 case IEEE80211_STYPE_CTS:
2321 case IEEE80211_STYPE_ACK:
2322 hdrlen = IEEE80211_1ADDR_LEN;
2323 break;
2324 default:
2325 hdrlen = IEEE80211_2ADDR_LEN;
2326 break;
2327 }
2328 break;
2329 }
2330
2331 return hdrlen;
2332}
2333
2334static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr)
2335{
2336 switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) {
2337 case IEEE80211_1ADDR_LEN:
2338 return ((struct ieee80211_hdr_1addr *)hdr)->payload;
2339 case IEEE80211_2ADDR_LEN:
2340 return ((struct ieee80211_hdr_2addr *)hdr)->payload;
2341 case IEEE80211_3ADDR_LEN:
2342 return ((struct ieee80211_hdr_3addr *)hdr)->payload;
2343 case IEEE80211_4ADDR_LEN:
2344 return ((struct ieee80211_hdr_4addr *)hdr)->payload;
2345 }
2346 return NULL;
2347}
2348
2349static inline int ieee80211_is_ofdm_rate(u8 rate)
2350{
2351 switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
2352 case IEEE80211_OFDM_RATE_6MB:
2353 case IEEE80211_OFDM_RATE_9MB:
2354 case IEEE80211_OFDM_RATE_12MB:
2355 case IEEE80211_OFDM_RATE_18MB:
2356 case IEEE80211_OFDM_RATE_24MB:
2357 case IEEE80211_OFDM_RATE_36MB:
2358 case IEEE80211_OFDM_RATE_48MB:
2359 case IEEE80211_OFDM_RATE_54MB:
2360 return 1;
2361 }
2362 return 0;
2363}
2364
2365static inline int ieee80211_is_cck_rate(u8 rate)
2366{
2367 switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
2368 case IEEE80211_CCK_RATE_1MB:
2369 case IEEE80211_CCK_RATE_2MB:
2370 case IEEE80211_CCK_RATE_5MB:
2371 case IEEE80211_CCK_RATE_11MB:
2372 return 1;
2373 }
2374 return 0;
2375}
2376
2377
2378/* ieee80211.c */
2379void free_ieee80211(struct net_device *dev);
2380struct net_device *alloc_ieee80211(int sizeof_priv);
2381
2382int ieee80211_set_encryption(struct ieee80211_device *ieee);
2383
2384/* ieee80211_tx.c */
2385
2386int ieee80211_encrypt_fragment(
2387 struct ieee80211_device *ieee,
2388 struct sk_buff *frag,
2389 int hdr_len);
2390
2391int ieee80211_rtl_xmit(struct sk_buff *skb,
2392 struct net_device *dev);
2393void ieee80211_txb_free(struct ieee80211_txb *);
2394
2395
2396/* ieee80211_rx.c */
2397int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
2398 struct ieee80211_rx_stats *rx_stats);
2399void ieee80211_rx_mgt(struct ieee80211_device *ieee,
2400 struct ieee80211_hdr_4addr *header,
2401 struct ieee80211_rx_stats *stats);
2402
2403/* ieee80211_wx.c */
2404int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
2405 struct iw_request_info *info,
2406 union iwreq_data *wrqu, char *key);
2407int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
2408 struct iw_request_info *info,
2409 union iwreq_data *wrqu, char *key);
2410int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
2411 struct iw_request_info *info,
2412 union iwreq_data *wrqu, char *key);
2413int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
2414 struct iw_request_info *info,
2415 union iwreq_data* wrqu, char *extra);
2416int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
2417 struct iw_request_info *info,
2418 union iwreq_data* wrqu, char *extra);
2419int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
2420 struct iw_request_info *info,
2421 struct iw_param *data, char *extra);
2422int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
2423 struct iw_request_info *info,
2424 union iwreq_data *wrqu, char *extra);
2425int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
2426
2427/* ieee80211_softmac.c */
2428short ieee80211_is_54g(struct ieee80211_network net);
2429short ieee80211_is_shortslot(struct ieee80211_network net);
2430int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
2431 struct ieee80211_rx_stats *rx_stats, u16 type,
2432 u16 stype);
2433void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net);
2434
2435void SendDisassociation(struct ieee80211_device *ieee, u8* asSta, u8 asRsn);
2436void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee);
2437
2438void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
2439void notify_wx_assoc_event(struct ieee80211_device *ieee);
2440void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
2441void ieee80211_start_bss(struct ieee80211_device *ieee);
2442void ieee80211_start_master_bss(struct ieee80211_device *ieee);
2443void ieee80211_start_ibss(struct ieee80211_device *ieee);
2444void ieee80211_softmac_init(struct ieee80211_device *ieee);
2445void ieee80211_softmac_free(struct ieee80211_device *ieee);
2446void ieee80211_associate_abort(struct ieee80211_device *ieee);
2447void ieee80211_disassociate(struct ieee80211_device *ieee);
2448void ieee80211_stop_scan(struct ieee80211_device *ieee);
2449void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
2450void ieee80211_check_all_nets(struct ieee80211_device *ieee);
2451void ieee80211_start_protocol(struct ieee80211_device *ieee);
2452void ieee80211_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
2453void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
2454void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
2455void ieee80211_reset_queue(struct ieee80211_device *ieee);
2456void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
2457void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
2458struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
2459void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
2460void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
2461int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p);
2462void notify_wx_assoc_event(struct ieee80211_device *ieee);
2463void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
2464
2465void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee);
2466
2467/* ieee80211_crypt_ccmp&tkip&wep.c */
2468void ieee80211_tkip_null(void);
2469void ieee80211_wep_null(void);
2470void ieee80211_ccmp_null(void);
2471
2472/* ieee80211_softmac_wx.c */
2473
2474int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
2475 struct iw_request_info *info,
2476 union iwreq_data *wrqu, char *ext);
2477
2478int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
2479 struct iw_request_info *info,
2480 union iwreq_data *awrq,
2481 char *extra);
2482
2483int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b);
2484
2485int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
2486 struct iw_request_info *info,
2487 union iwreq_data *wrqu, char *extra);
2488
2489int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
2490 struct iw_request_info *info,
2491 union iwreq_data *wrqu, char *extra);
2492
2493int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
2494 union iwreq_data *wrqu, char *b);
2495
2496int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
2497 union iwreq_data *wrqu, char *b);
2498
2499int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
2500 struct iw_request_info *a,
2501 union iwreq_data *wrqu, char *extra);
2502
2503int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
2504 union iwreq_data *wrqu, char *b);
2505
2506int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
2507 union iwreq_data *wrqu, char *b);
2508
2509int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
2510 union iwreq_data *wrqu, char *b);
2511
2512void ieee80211_wx_sync_scan_wq(struct work_struct *work);
2513
2514int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
2515 struct iw_request_info *info,
2516 union iwreq_data *wrqu, char *extra);
2517
2518int ieee80211_wx_get_name(struct ieee80211_device *ieee,
2519 struct iw_request_info *info,
2520 union iwreq_data *wrqu, char *extra);
2521
2522int ieee80211_wx_set_power(struct ieee80211_device *ieee,
2523 struct iw_request_info *info,
2524 union iwreq_data *wrqu, char *extra);
2525
2526int ieee80211_wx_get_power(struct ieee80211_device *ieee,
2527 struct iw_request_info *info,
2528 union iwreq_data *wrqu, char *extra);
2529
2530int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
2531 struct iw_request_info *info,
2532 union iwreq_data *wrqu, char *extra);
2533
2534int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
2535 struct iw_request_info *info,
2536 union iwreq_data *wrqu, char *extra);
2537//HT
2538#define MAX_RECEIVE_BUFFER_SIZE 9100
2539void HTDebugHTCapability(u8 *CapIE, u8 *TitleString );
2540void HTDebugHTInfo(u8 *InfoIE, u8 *TitleString);
2541
2542void HTSetConnectBwMode(struct ieee80211_device *ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
2543void HTUpdateDefaultSetting(struct ieee80211_device *ieee);
2544void HTConstructCapabilityElement(struct ieee80211_device *ieee, u8 *posHTCap, u8 *len, u8 isEncrypt);
2545void HTConstructInfoElement(struct ieee80211_device *ieee, u8 *posHTInfo, u8 *len, u8 isEncrypt);
2546void HTConstructRT2RTAggElement(struct ieee80211_device *ieee, u8 *posRT2RTAgg, u8 *len);
2547void HTOnAssocRsp(struct ieee80211_device *ieee);
2548void HTInitializeHTInfo(struct ieee80211_device *ieee);
2549void HTInitializeBssDesc(PBSS_HT pBssHT);
2550void HTResetSelfAndSavePeerSetting(struct ieee80211_device *ieee, struct ieee80211_network *pNetwork);
2551void HTUpdateSelfAndPeerSetting(struct ieee80211_device *ieee, struct ieee80211_network *pNetwork);
2552u8 HTGetHighestMCSRate(struct ieee80211_device *ieee, u8 *pMCSRateSet, u8 *pMCSFilter);
2553extern u8 MCS_FILTER_ALL[];
2554extern u16 MCS_DATA_RATE[2][2][77] ;
2555
2556u8 HTCCheck(struct ieee80211_device *ieee, u8 *pFrame);
2557void HTResetIOTSetting(PRT_HIGH_THROUGHPUT pHTInfo);
2558bool IsHTHalfNmodeAPs(struct ieee80211_device *ieee);
2559u16 HTHalfMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate);
2560u16 HTMcsToDataRate( struct ieee80211_device *ieee, u8 nMcsRate);
2561u16 TxCountToDataRate( struct ieee80211_device *ieee, u8 nDataRate);
2562int ieee80211_rx_ADDBAReq( struct ieee80211_device *ieee, struct sk_buff *skb);
2563int ieee80211_rx_ADDBARsp( struct ieee80211_device *ieee, struct sk_buff *skb);
2564int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb);
2565void TsInitAddBA( struct ieee80211_device *ieee, PTX_TS_RECORD pTS, u8 Policy, u8 bOverwritePending);
2566void TsInitDelBA( struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect);
2567void BaSetupTimeOut(unsigned long data);
2568void TxBaInactTimeout(unsigned long data);
2569void RxBaInactTimeout(unsigned long data);
2570void ResetBaEntry( PBA_RECORD pBA);
2571//function in TS.c
2572bool GetTs(
2573 struct ieee80211_device* ieee,
2574 PTS_COMMON_INFO *ppTS,
2575 u8* Addr,
2576 u8 TID,
2577 TR_SELECT TxRxSelect, //Rx:1, Tx:0
2578 bool bAddNewTs
2579 );
2580void TSInitialize(struct ieee80211_device *ieee);
2581void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTS);
2582void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr);
2583void RemoveAllTS(struct ieee80211_device *ieee);
2584void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee);
2585
2586extern const long ieee80211_wlan_frequencies[];
2587
2588extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
2589{
2590 ieee->scans++;
2591}
2592
2593extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
2594{
2595 return ieee->scans;
2596}
2597
2598static inline const char *escape_essid(const char *essid, u8 essid_len) {
2599 static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
2600 const char *s = essid;
2601 char *d = escaped;
2602
2603 if (ieee80211_is_empty_essid(essid, essid_len)) {
2604 memcpy(escaped, "<hidden>", sizeof("<hidden>"));
2605 return escaped;
2606 }
2607
2608 essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
2609 while (essid_len--) {
2610 if (*s == '\0') {
2611 *d++ = '\\';
2612 *d++ = '0';
2613 s++;
2614 } else {
2615 *d++ = *s++;
2616 }
2617 }
2618 *d = '\0';
2619 return escaped;
2620}
2621
2622/* For the function is more related to hardware setting, it's better to use the
2623 * ieee handler to refer to it.
2624 */
2625int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev);
2626int ieee80211_parse_info_param(struct ieee80211_device *ieee,
2627 struct ieee80211_info_element *info_element,
2628 u16 length,
2629 struct ieee80211_network *network,
2630 struct ieee80211_rx_stats *stats);
2631
2632void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8 index);
2633void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr);
2634void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee);
2635#define RT_ASOC_RETRY_LIMIT 5
2636#endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
new file mode 100644
index 00000000000..61fd4ced452
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
@@ -0,0 +1,244 @@
1/*
2 * Host AP crypto routines
3 *
4 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
5 * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. See README and COPYING for
10 * more details.
11 *
12 */
13
14//#include <linux/config.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <asm/string.h>
19#include <asm/errno.h>
20
21#include "ieee80211.h"
22
23//MODULE_AUTHOR("Jouni Malinen");
24//MODULE_DESCRIPTION("HostAP crypto");
25//MODULE_LICENSE("GPL");
26
27struct ieee80211_crypto_alg {
28 struct list_head list;
29 struct ieee80211_crypto_ops *ops;
30};
31
32
33struct ieee80211_crypto {
34 struct list_head algs;
35 spinlock_t lock;
36};
37
38static struct ieee80211_crypto *hcrypt;
39
40void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
41 int force)
42{
43 struct list_head *ptr, *n;
44 struct ieee80211_crypt_data *entry;
45
46 for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
47 ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
48 entry = list_entry(ptr, struct ieee80211_crypt_data, list);
49
50 if (atomic_read(&entry->refcnt) != 0 && !force)
51 continue;
52
53 list_del(ptr);
54
55 if (entry->ops)
56 entry->ops->deinit(entry->priv);
57 kfree(entry);
58 }
59}
60
61void ieee80211_crypt_deinit_handler(unsigned long data)
62{
63 struct ieee80211_device *ieee = (struct ieee80211_device *)data;
64 unsigned long flags;
65
66 spin_lock_irqsave(&ieee->lock, flags);
67 ieee80211_crypt_deinit_entries(ieee, 0);
68 if (!list_empty(&ieee->crypt_deinit_list)) {
69 printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
70 "deletion list\n", ieee->dev->name);
71 ieee->crypt_deinit_timer.expires = jiffies + HZ;
72 add_timer(&ieee->crypt_deinit_timer);
73 }
74 spin_unlock_irqrestore(&ieee->lock, flags);
75
76}
77
78void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
79 struct ieee80211_crypt_data **crypt)
80{
81 struct ieee80211_crypt_data *tmp;
82 unsigned long flags;
83
84 if (*crypt == NULL)
85 return;
86
87 tmp = *crypt;
88 *crypt = NULL;
89
90 /* must not run ops->deinit() while there may be pending encrypt or
91 * decrypt operations. Use a list of delayed deinits to avoid needing
92 * locking. */
93
94 spin_lock_irqsave(&ieee->lock, flags);
95 list_add(&tmp->list, &ieee->crypt_deinit_list);
96 if (!timer_pending(&ieee->crypt_deinit_timer)) {
97 ieee->crypt_deinit_timer.expires = jiffies + HZ;
98 add_timer(&ieee->crypt_deinit_timer);
99 }
100 spin_unlock_irqrestore(&ieee->lock, flags);
101}
102
103int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
104{
105 unsigned long flags;
106 struct ieee80211_crypto_alg *alg;
107
108 if (hcrypt == NULL)
109 return -1;
110
111 alg = kzalloc(sizeof(*alg), GFP_KERNEL);
112 if (alg == NULL)
113 return -ENOMEM;
114
115 alg->ops = ops;
116
117 spin_lock_irqsave(&hcrypt->lock, flags);
118 list_add(&alg->list, &hcrypt->algs);
119 spin_unlock_irqrestore(&hcrypt->lock, flags);
120
121 printk(KERN_DEBUG "ieee80211_crypt: registered algorithm '%s'\n",
122 ops->name);
123
124 return 0;
125}
126
127int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
128{
129 unsigned long flags;
130 struct list_head *ptr;
131 struct ieee80211_crypto_alg *del_alg = NULL;
132
133 if (hcrypt == NULL)
134 return -1;
135
136 spin_lock_irqsave(&hcrypt->lock, flags);
137 for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
138 struct ieee80211_crypto_alg *alg =
139 (struct ieee80211_crypto_alg *) ptr;
140 if (alg->ops == ops) {
141 list_del(&alg->list);
142 del_alg = alg;
143 break;
144 }
145 }
146 spin_unlock_irqrestore(&hcrypt->lock, flags);
147
148 if (del_alg) {
149 printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
150 "'%s'\n", ops->name);
151 kfree(del_alg);
152 }
153
154 return del_alg ? 0 : -1;
155}
156
157
158struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name)
159{
160 unsigned long flags;
161 struct list_head *ptr;
162 struct ieee80211_crypto_alg *found_alg = NULL;
163
164 if (hcrypt == NULL)
165 return NULL;
166
167 spin_lock_irqsave(&hcrypt->lock, flags);
168 for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
169 struct ieee80211_crypto_alg *alg =
170 (struct ieee80211_crypto_alg *) ptr;
171 if (strcmp(alg->ops->name, name) == 0) {
172 found_alg = alg;
173 break;
174 }
175 }
176 spin_unlock_irqrestore(&hcrypt->lock, flags);
177
178 if (found_alg)
179 return found_alg->ops;
180 else
181 return NULL;
182}
183
184
185static void * ieee80211_crypt_null_init(int keyidx) { return (void *) 1; }
186static void ieee80211_crypt_null_deinit(void *priv) {}
187
188static struct ieee80211_crypto_ops ieee80211_crypt_null = {
189 .name = "NULL",
190 .init = ieee80211_crypt_null_init,
191 .deinit = ieee80211_crypt_null_deinit,
192 .encrypt_mpdu = NULL,
193 .decrypt_mpdu = NULL,
194 .encrypt_msdu = NULL,
195 .decrypt_msdu = NULL,
196 .set_key = NULL,
197 .get_key = NULL,
198 .extra_prefix_len = 0,
199 .extra_postfix_len = 0,
200 .owner = THIS_MODULE,
201};
202
203
204int __init ieee80211_crypto_init(void)
205{
206 int ret = -ENOMEM;
207
208 hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL);
209 if (!hcrypt)
210 goto out;
211
212 INIT_LIST_HEAD(&hcrypt->algs);
213 spin_lock_init(&hcrypt->lock);
214
215 ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
216 if (ret < 0) {
217 kfree(hcrypt);
218 hcrypt = NULL;
219 }
220out:
221 return ret;
222}
223
224
225void ieee80211_crypto_deinit(void)
226{
227 struct list_head *ptr, *n;
228
229 if (hcrypt == NULL)
230 return;
231
232 for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
233 ptr = n, n = ptr->next) {
234 struct ieee80211_crypto_alg *alg =
235 (struct ieee80211_crypto_alg *) ptr;
236 list_del(ptr);
237 printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
238 "'%s' (deinit)\n", alg->ops->name);
239 kfree(alg);
240 }
241
242 kfree(hcrypt);
243}
244
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.h
new file mode 100644
index 00000000000..ca7dd0dda82
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.h
@@ -0,0 +1,85 @@
1/*
2 * Original code based on Host AP (software wireless LAN access point) driver
3 * for Intersil Prism2/2.5/3.
4 *
5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
8 *
9 * Adaption to a generic IEEE 802.11 stack by James Ketrenos
10 * <jketreno@linux.intel.com>
11 *
12 * Copyright (c) 2004, Intel Corporation
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation. See README and COPYING for
17 * more details.
18 */
19
20/*
21 * This file defines the interface to the ieee80211 crypto module.
22 */
23#ifndef IEEE80211_CRYPT_H
24#define IEEE80211_CRYPT_H
25
26#include <linux/skbuff.h>
27
28struct ieee80211_crypto_ops {
29 const char *name;
30
31 /* init new crypto context (e.g., allocate private data space,
32 * select IV, etc.); returns NULL on failure or pointer to allocated
33 * private data on success */
34 void * (*init)(int keyidx);
35
36 /* deinitialize crypto context and free allocated private data */
37 void (*deinit)(void *priv);
38
39 /* encrypt/decrypt return < 0 on error or >= 0 on success. The return
40 * value from decrypt_mpdu is passed as the keyidx value for
41 * decrypt_msdu. skb must have enough head and tail room for the
42 * encryption; if not, error will be returned; these functions are
43 * called for all MPDUs (i.e., fragments).
44 */
45 int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
46 int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
47
48 /* These functions are called for full MSDUs, i.e. full frames.
49 * These can be NULL if full MSDU operations are not needed. */
50 int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
51 int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
52 void *priv);
53
54 int (*set_key)(void *key, int len, u8 *seq, void *priv);
55 int (*get_key)(void *key, int len, u8 *seq, void *priv);
56
57 /* procfs handler for printing out key information and possible
58 * statistics */
59 char * (*print_stats)(char *p, void *priv);
60
61 /* maximum number of bytes added by encryption; encrypt buf is
62 * allocated with extra_prefix_len bytes, copy of in_buf, and
63 * extra_postfix_len; encrypt need not use all this space, but
64 * the result must start at the beginning of the buffer and correct
65 * length must be returned */
66 int extra_prefix_len, extra_postfix_len;
67
68 struct module *owner;
69};
70
71struct ieee80211_crypt_data {
72 struct list_head list; /* delayed deletion list */
73 struct ieee80211_crypto_ops *ops;
74 void *priv;
75 atomic_t refcnt;
76};
77
78int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
79int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
80struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name);
81void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
82void ieee80211_crypt_deinit_handler(unsigned long);
83void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
84 struct ieee80211_crypt_data **crypt);
85#endif
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
new file mode 100644
index 00000000000..48267a058d1
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
@@ -0,0 +1,483 @@
1/*
2 * Host AP crypt: host-based CCMP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12//#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/random.h>
17#include <linux/skbuff.h>
18#include <linux/netdevice.h>
19#include <linux/if_ether.h>
20#include <linux/if_arp.h>
21#include <asm/string.h>
22#include <linux/wireless.h>
23
24#include "ieee80211.h"
25
26#include <linux/crypto.h>
27
28 #include <linux/scatterlist.h>
29
30MODULE_AUTHOR("Jouni Malinen");
31MODULE_DESCRIPTION("Host AP crypt: CCMP");
32MODULE_LICENSE("GPL");
33
34#ifndef OPENSUSE_SLED
35#define OPENSUSE_SLED 0
36#endif
37
38#define AES_BLOCK_LEN 16
39#define CCMP_HDR_LEN 8
40#define CCMP_MIC_LEN 8
41#define CCMP_TK_LEN 16
42#define CCMP_PN_LEN 6
43
44struct ieee80211_ccmp_data {
45 u8 key[CCMP_TK_LEN];
46 int key_set;
47
48 u8 tx_pn[CCMP_PN_LEN];
49 u8 rx_pn[CCMP_PN_LEN];
50
51 u32 dot11RSNAStatsCCMPFormatErrors;
52 u32 dot11RSNAStatsCCMPReplays;
53 u32 dot11RSNAStatsCCMPDecryptErrors;
54
55 int key_idx;
56
57 struct crypto_tfm *tfm;
58
59 /* scratch buffers for virt_to_page() (crypto API) */
60 u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN],
61 tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN];
62 u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN];
63};
64
65void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm,
66 const u8 pt[16], u8 ct[16])
67{
68 crypto_cipher_encrypt_one((void*)tfm, ct, pt);
69}
70
71static void * ieee80211_ccmp_init(int key_idx)
72{
73 struct ieee80211_ccmp_data *priv;
74
75 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
76 if (priv == NULL)
77 goto fail;
78 priv->key_idx = key_idx;
79
80 priv->tfm = (void*)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
81 if (IS_ERR(priv->tfm)) {
82 printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate "
83 "crypto API aes\n");
84 priv->tfm = NULL;
85 goto fail;
86 }
87 return priv;
88
89fail:
90 if (priv) {
91 if (priv->tfm)
92 crypto_free_cipher((void*)priv->tfm);
93 kfree(priv);
94 }
95
96 return NULL;
97}
98
99
100static void ieee80211_ccmp_deinit(void *priv)
101{
102 struct ieee80211_ccmp_data *_priv = priv;
103 if (_priv && _priv->tfm)
104 crypto_free_cipher((void*)_priv->tfm);
105 kfree(priv);
106}
107
108
109static inline void xor_block(u8 *b, u8 *a, size_t len)
110{
111 int i;
112 for (i = 0; i < len; i++)
113 b[i] ^= a[i];
114}
115
116
117
118static void ccmp_init_blocks(struct crypto_tfm *tfm,
119 struct ieee80211_hdr_4addr *hdr,
120 u8 *pn, size_t dlen, u8 *b0, u8 *auth,
121 u8 *s0)
122{
123 u8 *pos, qc = 0;
124 size_t aad_len;
125 u16 fc;
126 int a4_included, qc_included;
127 u8 aad[2 * AES_BLOCK_LEN];
128
129 fc = le16_to_cpu(hdr->frame_ctl);
130 a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
131 (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS));
132 /*
133 qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
134 (WLAN_FC_GET_STYPE(fc) & 0x08));
135 */
136 // fixed by David :2006.9.6
137 qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) &&
138 (WLAN_FC_GET_STYPE(fc) & 0x80));
139 aad_len = 22;
140 if (a4_included)
141 aad_len += 6;
142 if (qc_included) {
143 pos = (u8 *) &hdr->addr4;
144 if (a4_included)
145 pos += 6;
146 qc = *pos & 0x0f;
147 aad_len += 2;
148 }
149 /* CCM Initial Block:
150 * Flag (Include authentication header, M=3 (8-octet MIC),
151 * L=1 (2-octet Dlen))
152 * Nonce: 0x00 | A2 | PN
153 * Dlen */
154 b0[0] = 0x59;
155 b0[1] = qc;
156 memcpy(b0 + 2, hdr->addr2, ETH_ALEN);
157 memcpy(b0 + 8, pn, CCMP_PN_LEN);
158 b0[14] = (dlen >> 8) & 0xff;
159 b0[15] = dlen & 0xff;
160
161 /* AAD:
162 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
163 * A1 | A2 | A3
164 * SC with bits 4..15 (seq#) masked to zero
165 * A4 (if present)
166 * QC (if present)
167 */
168 pos = (u8 *) hdr;
169 aad[0] = 0; /* aad_len >> 8 */
170 aad[1] = aad_len & 0xff;
171 aad[2] = pos[0] & 0x8f;
172 aad[3] = pos[1] & 0xc7;
173 memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN);
174 pos = (u8 *) &hdr->seq_ctl;
175 aad[22] = pos[0] & 0x0f;
176 aad[23] = 0; /* all bits masked */
177 memset(aad + 24, 0, 8);
178 if (a4_included)
179 memcpy(aad + 24, hdr->addr4, ETH_ALEN);
180 if (qc_included) {
181 aad[a4_included ? 30 : 24] = qc;
182 /* rest of QC masked */
183 }
184
185 /* Start with the first block and AAD */
186 ieee80211_ccmp_aes_encrypt(tfm, b0, auth);
187 xor_block(auth, aad, AES_BLOCK_LEN);
188 ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
189 xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN);
190 ieee80211_ccmp_aes_encrypt(tfm, auth, auth);
191 b0[0] &= 0x07;
192 b0[14] = b0[15] = 0;
193 ieee80211_ccmp_aes_encrypt(tfm, b0, s0);
194}
195
196
197
198static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
199{
200 struct ieee80211_ccmp_data *key = priv;
201 int data_len, i;
202 u8 *pos;
203 struct ieee80211_hdr_4addr *hdr;
204 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
205
206 if (skb_headroom(skb) < CCMP_HDR_LEN ||
207 skb_tailroom(skb) < CCMP_MIC_LEN ||
208 skb->len < hdr_len)
209 return -1;
210
211 data_len = skb->len - hdr_len;
212 pos = skb_push(skb, CCMP_HDR_LEN);
213 memmove(pos, pos + CCMP_HDR_LEN, hdr_len);
214 pos += hdr_len;
215// mic = skb_put(skb, CCMP_MIC_LEN);
216
217 i = CCMP_PN_LEN - 1;
218 while (i >= 0) {
219 key->tx_pn[i]++;
220 if (key->tx_pn[i] != 0)
221 break;
222 i--;
223 }
224
225 *pos++ = key->tx_pn[5];
226 *pos++ = key->tx_pn[4];
227 *pos++ = 0;
228 *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */;
229 *pos++ = key->tx_pn[3];
230 *pos++ = key->tx_pn[2];
231 *pos++ = key->tx_pn[1];
232 *pos++ = key->tx_pn[0];
233
234
235 hdr = (struct ieee80211_hdr_4addr *) skb->data;
236 if (!tcb_desc->bHwSec)
237 {
238 int blocks, last, len;
239 u8 *mic;
240 u8 *b0 = key->tx_b0;
241 u8 *b = key->tx_b;
242 u8 *e = key->tx_e;
243 u8 *s0 = key->tx_s0;
244
245 //mic is moved to here by john
246 mic = skb_put(skb, CCMP_MIC_LEN);
247
248 ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0);
249
250 blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
251 last = data_len % AES_BLOCK_LEN;
252
253 for (i = 1; i <= blocks; i++) {
254 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
255 /* Authentication */
256 xor_block(b, pos, len);
257 ieee80211_ccmp_aes_encrypt(key->tfm, b, b);
258 /* Encryption, with counter */
259 b0[14] = (i >> 8) & 0xff;
260 b0[15] = i & 0xff;
261 ieee80211_ccmp_aes_encrypt(key->tfm, b0, e);
262 xor_block(pos, e, len);
263 pos += len;
264 }
265
266 for (i = 0; i < CCMP_MIC_LEN; i++)
267 mic[i] = b[i] ^ s0[i];
268 }
269 return 0;
270}
271
272
273static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
274{
275 struct ieee80211_ccmp_data *key = priv;
276 u8 keyidx, *pos;
277 struct ieee80211_hdr_4addr *hdr;
278 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
279 u8 pn[6];
280
281 if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) {
282 key->dot11RSNAStatsCCMPFormatErrors++;
283 return -1;
284 }
285
286 hdr = (struct ieee80211_hdr_4addr *) skb->data;
287 pos = skb->data + hdr_len;
288 keyidx = pos[3];
289 if (!(keyidx & (1 << 5))) {
290 if (net_ratelimit()) {
291 printk(KERN_DEBUG "CCMP: received packet without ExtIV"
292 " flag from %pM\n", hdr->addr2);
293 }
294 key->dot11RSNAStatsCCMPFormatErrors++;
295 return -2;
296 }
297 keyidx >>= 6;
298 if (key->key_idx != keyidx) {
299 printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame "
300 "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv);
301 return -6;
302 }
303 if (!key->key_set) {
304 if (net_ratelimit()) {
305 printk(KERN_DEBUG "CCMP: received packet from %pM"
306 " with keyid=%d that does not have a configured"
307 " key\n", hdr->addr2, keyidx);
308 }
309 return -3;
310 }
311
312 pn[0] = pos[7];
313 pn[1] = pos[6];
314 pn[2] = pos[5];
315 pn[3] = pos[4];
316 pn[4] = pos[1];
317 pn[5] = pos[0];
318 pos += 8;
319
320 if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
321 key->dot11RSNAStatsCCMPReplays++;
322 return -4;
323 }
324 if (!tcb_desc->bHwSec)
325 {
326 size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN;
327 u8 *mic = skb->data + skb->len - CCMP_MIC_LEN;
328 u8 *b0 = key->rx_b0;
329 u8 *b = key->rx_b;
330 u8 *a = key->rx_a;
331 int i, blocks, last, len;
332
333
334 ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b);
335 xor_block(mic, b, CCMP_MIC_LEN);
336
337 blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
338 last = data_len % AES_BLOCK_LEN;
339
340 for (i = 1; i <= blocks; i++) {
341 len = (i == blocks && last) ? last : AES_BLOCK_LEN;
342 /* Decrypt, with counter */
343 b0[14] = (i >> 8) & 0xff;
344 b0[15] = i & 0xff;
345 ieee80211_ccmp_aes_encrypt(key->tfm, b0, b);
346 xor_block(pos, b, len);
347 /* Authentication */
348 xor_block(a, pos, len);
349 ieee80211_ccmp_aes_encrypt(key->tfm, a, a);
350 pos += len;
351 }
352
353 if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
354 if (net_ratelimit()) {
355 printk(KERN_DEBUG "CCMP: decrypt failed: STA="
356 "%pM\n", hdr->addr2);
357 }
358 key->dot11RSNAStatsCCMPDecryptErrors++;
359 return -5;
360 }
361
362 memcpy(key->rx_pn, pn, CCMP_PN_LEN);
363 }
364 /* Remove hdr and MIC */
365 memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len);
366 skb_pull(skb, CCMP_HDR_LEN);
367 skb_trim(skb, skb->len - CCMP_MIC_LEN);
368
369 return keyidx;
370}
371
372
373static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv)
374{
375 struct ieee80211_ccmp_data *data = priv;
376 int keyidx;
377 struct crypto_tfm *tfm = data->tfm;
378
379 keyidx = data->key_idx;
380 memset(data, 0, sizeof(*data));
381 data->key_idx = keyidx;
382 data->tfm = tfm;
383 if (len == CCMP_TK_LEN) {
384 memcpy(data->key, key, CCMP_TK_LEN);
385 data->key_set = 1;
386 if (seq) {
387 data->rx_pn[0] = seq[5];
388 data->rx_pn[1] = seq[4];
389 data->rx_pn[2] = seq[3];
390 data->rx_pn[3] = seq[2];
391 data->rx_pn[4] = seq[1];
392 data->rx_pn[5] = seq[0];
393 }
394 crypto_cipher_setkey((void*)data->tfm, data->key, CCMP_TK_LEN);
395 } else if (len == 0)
396 data->key_set = 0;
397 else
398 return -1;
399
400 return 0;
401}
402
403
404static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
405{
406 struct ieee80211_ccmp_data *data = priv;
407
408 if (len < CCMP_TK_LEN)
409 return -1;
410
411 if (!data->key_set)
412 return 0;
413 memcpy(key, data->key, CCMP_TK_LEN);
414
415 if (seq) {
416 seq[0] = data->tx_pn[5];
417 seq[1] = data->tx_pn[4];
418 seq[2] = data->tx_pn[3];
419 seq[3] = data->tx_pn[2];
420 seq[4] = data->tx_pn[1];
421 seq[5] = data->tx_pn[0];
422 }
423
424 return CCMP_TK_LEN;
425}
426
427
428static char * ieee80211_ccmp_print_stats(char *p, void *priv)
429{
430 struct ieee80211_ccmp_data *ccmp = priv;
431 int i;
432
433 p += sprintf(p, "key[%d] alg=CCMP key_set=%d tx_pn=",
434 ccmp->key_idx, ccmp->key_set);
435
436 for (i = 0; i < ARRAY_SIZE(ccmp->tx_pn); i++)
437 p += sprintf(p, "%02x", ccmp->tx_pn[i]);
438
439 sprintf(p, " rx_pn=");
440 for (i = 0; i < ARRAY_SIZE(ccmp->rx_pn); i++)
441 p += sprintf(p, "%02x", ccmp->tx_pn[i]);
442
443 p += sprintf(p, " format_errors=%d replays=%d decrypt_errors=%d\n",
444 ccmp->dot11RSNAStatsCCMPFormatErrors,
445 ccmp->dot11RSNAStatsCCMPReplays,
446 ccmp->dot11RSNAStatsCCMPDecryptErrors);
447
448 return p;
449}
450
451void ieee80211_ccmp_null(void)
452{
453 return;
454}
455
456static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = {
457 .name = "CCMP",
458 .init = ieee80211_ccmp_init,
459 .deinit = ieee80211_ccmp_deinit,
460 .encrypt_mpdu = ieee80211_ccmp_encrypt,
461 .decrypt_mpdu = ieee80211_ccmp_decrypt,
462 .encrypt_msdu = NULL,
463 .decrypt_msdu = NULL,
464 .set_key = ieee80211_ccmp_set_key,
465 .get_key = ieee80211_ccmp_get_key,
466 .print_stats = ieee80211_ccmp_print_stats,
467 .extra_prefix_len = CCMP_HDR_LEN,
468 .extra_postfix_len = CCMP_MIC_LEN,
469 .owner = THIS_MODULE,
470};
471
472
473int __init ieee80211_crypto_ccmp_init(void)
474{
475 return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp);
476}
477
478
479void ieee80211_crypto_ccmp_exit(void)
480{
481 ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
482}
483
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
new file mode 100644
index 00000000000..ed623a911e4
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
@@ -0,0 +1,809 @@
1/*
2 * Host AP crypt: host-based TKIP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12//#include <linux/config.h>
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/random.h>
17#include <linux/skbuff.h>
18#include <linux/netdevice.h>
19#include <linux/if_ether.h>
20#include <linux/if_arp.h>
21#include <asm/string.h>
22
23#include "ieee80211.h"
24
25
26#include <linux/crypto.h>
27#include <linux/scatterlist.h>
28
29#include <linux/crc32.h>
30
31MODULE_AUTHOR("Jouni Malinen");
32MODULE_DESCRIPTION("Host AP crypt: TKIP");
33MODULE_LICENSE("GPL");
34
35#ifndef OPENSUSE_SLED
36#define OPENSUSE_SLED 0
37#endif
38
39struct ieee80211_tkip_data {
40#define TKIP_KEY_LEN 32
41 u8 key[TKIP_KEY_LEN];
42 int key_set;
43
44 u32 tx_iv32;
45 u16 tx_iv16;
46 u16 tx_ttak[5];
47 int tx_phase1_done;
48
49 u32 rx_iv32;
50 u16 rx_iv16;
51 u16 rx_ttak[5];
52 int rx_phase1_done;
53 u32 rx_iv32_new;
54 u16 rx_iv16_new;
55
56 u32 dot11RSNAStatsTKIPReplays;
57 u32 dot11RSNAStatsTKIPICVErrors;
58 u32 dot11RSNAStatsTKIPLocalMICFailures;
59
60 int key_idx;
61 struct crypto_blkcipher *rx_tfm_arc4;
62 struct crypto_hash *rx_tfm_michael;
63 struct crypto_blkcipher *tx_tfm_arc4;
64 struct crypto_hash *tx_tfm_michael;
65 /* scratch buffers for virt_to_page() (crypto API) */
66 u8 rx_hdr[16], tx_hdr[16];
67};
68
69static void * ieee80211_tkip_init(int key_idx)
70{
71 struct ieee80211_tkip_data *priv;
72
73 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
74 if (priv == NULL)
75 goto fail;
76 priv->key_idx = key_idx;
77 priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
78 CRYPTO_ALG_ASYNC);
79 if (IS_ERR(priv->tx_tfm_arc4)) {
80 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
81 "crypto API arc4\n");
82 priv->tx_tfm_arc4 = NULL;
83 goto fail;
84 }
85
86 priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
87 CRYPTO_ALG_ASYNC);
88 if (IS_ERR(priv->tx_tfm_michael)) {
89 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
90 "crypto API michael_mic\n");
91 priv->tx_tfm_michael = NULL;
92 goto fail;
93 }
94
95 priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0,
96 CRYPTO_ALG_ASYNC);
97 if (IS_ERR(priv->rx_tfm_arc4)) {
98 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
99 "crypto API arc4\n");
100 priv->rx_tfm_arc4 = NULL;
101 goto fail;
102 }
103
104 priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0,
105 CRYPTO_ALG_ASYNC);
106 if (IS_ERR(priv->rx_tfm_michael)) {
107 printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate "
108 "crypto API michael_mic\n");
109 priv->rx_tfm_michael = NULL;
110 goto fail;
111 }
112 return priv;
113
114fail:
115 if (priv) {
116 if (priv->tx_tfm_michael)
117 crypto_free_hash(priv->tx_tfm_michael);
118 if (priv->tx_tfm_arc4)
119 crypto_free_blkcipher(priv->tx_tfm_arc4);
120 if (priv->rx_tfm_michael)
121 crypto_free_hash(priv->rx_tfm_michael);
122 if (priv->rx_tfm_arc4)
123 crypto_free_blkcipher(priv->rx_tfm_arc4);
124 kfree(priv);
125 }
126
127 return NULL;
128}
129
130
131static void ieee80211_tkip_deinit(void *priv)
132{
133 struct ieee80211_tkip_data *_priv = priv;
134 if (_priv) {
135 if (_priv->tx_tfm_michael)
136 crypto_free_hash(_priv->tx_tfm_michael);
137 if (_priv->tx_tfm_arc4)
138 crypto_free_blkcipher(_priv->tx_tfm_arc4);
139 if (_priv->rx_tfm_michael)
140 crypto_free_hash(_priv->rx_tfm_michael);
141 if (_priv->rx_tfm_arc4)
142 crypto_free_blkcipher(_priv->rx_tfm_arc4);
143 }
144 kfree(priv);
145}
146
147
148static inline u16 RotR1(u16 val)
149{
150 return (val >> 1) | (val << 15);
151}
152
153
154static inline u8 Lo8(u16 val)
155{
156 return val & 0xff;
157}
158
159
160static inline u8 Hi8(u16 val)
161{
162 return val >> 8;
163}
164
165
166static inline u16 Lo16(u32 val)
167{
168 return val & 0xffff;
169}
170
171
172static inline u16 Hi16(u32 val)
173{
174 return val >> 16;
175}
176
177
178static inline u16 Mk16(u8 hi, u8 lo)
179{
180 return lo | (((u16) hi) << 8);
181}
182
183
184static inline u16 Mk16_le(u16 *v)
185{
186 return le16_to_cpu(*v);
187}
188
189
190static const u16 Sbox[256] =
191{
192 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
193 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
194 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
195 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
196 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
197 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
198 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
199 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
200 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
201 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
202 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
203 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
204 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
205 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
206 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
207 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
208 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
209 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
210 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
211 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
212 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
213 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
214 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
215 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
216 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
217 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
218 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
219 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
220 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
221 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
222 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
223 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
224};
225
226
227static inline u16 _S_(u16 v)
228{
229 u16 t = Sbox[Hi8(v)];
230 return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8));
231}
232
233
234#define PHASE1_LOOP_COUNT 8
235
236
237static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32)
238{
239 int i, j;
240
241 /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */
242 TTAK[0] = Lo16(IV32);
243 TTAK[1] = Hi16(IV32);
244 TTAK[2] = Mk16(TA[1], TA[0]);
245 TTAK[3] = Mk16(TA[3], TA[2]);
246 TTAK[4] = Mk16(TA[5], TA[4]);
247
248 for (i = 0; i < PHASE1_LOOP_COUNT; i++) {
249 j = 2 * (i & 1);
250 TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j]));
251 TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j]));
252 TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j]));
253 TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j]));
254 TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i;
255 }
256}
257
258
259static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK,
260 u16 IV16)
261{
262 /* Make temporary area overlap WEP seed so that the final copy can be
263 * avoided on little endian hosts. */
264 u16 *PPK = (u16 *) &WEPSeed[4];
265
266 /* Step 1 - make copy of TTAK and bring in TSC */
267 PPK[0] = TTAK[0];
268 PPK[1] = TTAK[1];
269 PPK[2] = TTAK[2];
270 PPK[3] = TTAK[3];
271 PPK[4] = TTAK[4];
272 PPK[5] = TTAK[4] + IV16;
273
274 /* Step 2 - 96-bit bijective mixing using S-box */
275 PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0]));
276 PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2]));
277 PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4]));
278 PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6]));
279 PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8]));
280 PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10]));
281
282 PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12]));
283 PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14]));
284 PPK[2] += RotR1(PPK[1]);
285 PPK[3] += RotR1(PPK[2]);
286 PPK[4] += RotR1(PPK[3]);
287 PPK[5] += RotR1(PPK[4]);
288
289 /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value
290 * WEPSeed[0..2] is transmitted as WEP IV */
291 WEPSeed[0] = Hi8(IV16);
292 WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F;
293 WEPSeed[2] = Lo8(IV16);
294 WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1);
295
296#ifdef __BIG_ENDIAN
297 {
298 int i;
299 for (i = 0; i < 6; i++)
300 PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8);
301 }
302#endif
303}
304
305
306static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
307{
308 struct ieee80211_tkip_data *tkey = priv;
309 int len;
310 u8 *pos;
311 struct ieee80211_hdr_4addr *hdr;
312 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
313
314 struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4};
315 int ret = 0;
316 u8 rc4key[16], *icv;
317 u32 crc;
318 struct scatterlist sg;
319
320 if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 ||
321 skb->len < hdr_len)
322 return -1;
323
324 hdr = (struct ieee80211_hdr_4addr *) skb->data;
325
326 if (!tcb_desc->bHwSec)
327 {
328 if (!tkey->tx_phase1_done) {
329 tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2,
330 tkey->tx_iv32);
331 tkey->tx_phase1_done = 1;
332 }
333 tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16);
334 }
335 else
336 tkey->tx_phase1_done = 1;
337
338
339 len = skb->len - hdr_len;
340 pos = skb_push(skb, 8);
341 memmove(pos, pos + 8, hdr_len);
342 pos += hdr_len;
343
344 if (tcb_desc->bHwSec)
345 {
346 *pos++ = Hi8(tkey->tx_iv16);
347 *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F;
348 *pos++ = Lo8(tkey->tx_iv16);
349 }
350 else
351 {
352 *pos++ = rc4key[0];
353 *pos++ = rc4key[1];
354 *pos++ = rc4key[2];
355 }
356
357 *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */;
358 *pos++ = tkey->tx_iv32 & 0xff;
359 *pos++ = (tkey->tx_iv32 >> 8) & 0xff;
360 *pos++ = (tkey->tx_iv32 >> 16) & 0xff;
361 *pos++ = (tkey->tx_iv32 >> 24) & 0xff;
362
363 if (!tcb_desc->bHwSec)
364 {
365 icv = skb_put(skb, 4);
366 crc = ~crc32_le(~0, pos, len);
367 icv[0] = crc;
368 icv[1] = crc >> 8;
369 icv[2] = crc >> 16;
370 icv[3] = crc >> 24;
371 crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16);
372 sg_init_one(&sg, pos, len+4);
373 ret= crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
374
375 }
376
377 tkey->tx_iv16++;
378 if (tkey->tx_iv16 == 0) {
379 tkey->tx_phase1_done = 0;
380 tkey->tx_iv32++;
381 }
382
383 if (!tcb_desc->bHwSec)
384 return ret;
385 else
386 return 0;
387
388
389}
390
391static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
392{
393 struct ieee80211_tkip_data *tkey = priv;
394 u8 keyidx, *pos;
395 u32 iv32;
396 u16 iv16;
397 struct ieee80211_hdr_4addr *hdr;
398 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
399 struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4};
400 u8 rc4key[16];
401 u8 icv[4];
402 u32 crc;
403 struct scatterlist sg;
404 int plen;
405 if (skb->len < hdr_len + 8 + 4)
406 return -1;
407
408 hdr = (struct ieee80211_hdr_4addr *) skb->data;
409 pos = skb->data + hdr_len;
410 keyidx = pos[3];
411 if (!(keyidx & (1 << 5))) {
412 if (net_ratelimit()) {
413 printk(KERN_DEBUG "TKIP: received packet without ExtIV"
414 " flag from %pM\n", hdr->addr2);
415 }
416 return -2;
417 }
418 keyidx >>= 6;
419 if (tkey->key_idx != keyidx) {
420 printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame "
421 "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv);
422 return -6;
423 }
424 if (!tkey->key_set) {
425 if (net_ratelimit()) {
426 printk(KERN_DEBUG "TKIP: received packet from %pM"
427 " with keyid=%d that does not have a configured"
428 " key\n", hdr->addr2, keyidx);
429 }
430 return -3;
431 }
432 iv16 = (pos[0] << 8) | pos[2];
433 iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24);
434 pos += 8;
435
436 if (!tcb_desc->bHwSec)
437 {
438 if (iv32 < tkey->rx_iv32 ||
439 (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
440 if (net_ratelimit()) {
441 printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
442 " previous TSC %08x%04x received TSC "
443 "%08x%04x\n", hdr->addr2,
444 tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
445 }
446 tkey->dot11RSNAStatsTKIPReplays++;
447 return -4;
448 }
449
450 if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) {
451 tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32);
452 tkey->rx_phase1_done = 1;
453 }
454 tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16);
455
456 plen = skb->len - hdr_len - 12;
457
458 crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16);
459 sg_init_one(&sg, pos, plen+4);
460 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
461 if (net_ratelimit()) {
462 printk(KERN_DEBUG ": TKIP: failed to decrypt "
463 "received packet from %pM\n",
464 hdr->addr2);
465 }
466 return -7;
467 }
468
469 crc = ~crc32_le(~0, pos, plen);
470 icv[0] = crc;
471 icv[1] = crc >> 8;
472 icv[2] = crc >> 16;
473 icv[3] = crc >> 24;
474
475 if (memcmp(icv, pos + plen, 4) != 0) {
476 if (iv32 != tkey->rx_iv32) {
477 /* Previously cached Phase1 result was already lost, so
478 * it needs to be recalculated for the next packet. */
479 tkey->rx_phase1_done = 0;
480 }
481 if (net_ratelimit()) {
482 printk(KERN_DEBUG
483 "TKIP: ICV error detected: STA=%pM\n",
484 hdr->addr2);
485 }
486 tkey->dot11RSNAStatsTKIPICVErrors++;
487 return -5;
488 }
489
490 }
491
492 /* Update real counters only after Michael MIC verification has
493 * completed */
494 tkey->rx_iv32_new = iv32;
495 tkey->rx_iv16_new = iv16;
496
497 /* Remove IV and ICV */
498 memmove(skb->data + 8, skb->data, hdr_len);
499 skb_pull(skb, 8);
500 skb_trim(skb, skb->len - 4);
501
502 return keyidx;
503}
504
505
506static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr,
507 u8 * data, size_t data_len, u8 * mic)
508{
509 struct hash_desc desc;
510 struct scatterlist sg[2];
511
512 if (tfm_michael == NULL) {
513 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
514 return -1;
515 }
516 sg_init_table(sg, 2);
517 sg_set_buf(&sg[0], hdr, 16);
518 sg_set_buf(&sg[1], data, data_len);
519
520 if (crypto_hash_setkey(tfm_michael, key, 8))
521 return -1;
522
523 desc.tfm = tfm_michael;
524 desc.flags = 0;
525 return crypto_hash_digest(&desc, sg, data_len + 16, mic);
526}
527
528
529
530static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr)
531{
532 struct ieee80211_hdr_4addr *hdr11;
533
534 hdr11 = (struct ieee80211_hdr_4addr *) skb->data;
535 switch (le16_to_cpu(hdr11->frame_ctl) &
536 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
537 case IEEE80211_FCTL_TODS:
538 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
539 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
540 break;
541 case IEEE80211_FCTL_FROMDS:
542 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
543 memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */
544 break;
545 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
546 memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */
547 memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */
548 break;
549 case 0:
550 memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */
551 memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */
552 break;
553 }
554
555 hdr[12] = 0; /* priority */
556
557 hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */
558}
559
560
561static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv)
562{
563 struct ieee80211_tkip_data *tkey = priv;
564 u8 *pos;
565 struct ieee80211_hdr_4addr *hdr;
566
567 hdr = (struct ieee80211_hdr_4addr *) skb->data;
568
569 if (skb_tailroom(skb) < 8 || skb->len < hdr_len) {
570 printk(KERN_DEBUG "Invalid packet for Michael MIC add "
571 "(tailroom=%d hdr_len=%d skb->len=%d)\n",
572 skb_tailroom(skb), hdr_len, skb->len);
573 return -1;
574 }
575
576 michael_mic_hdr(skb, tkey->tx_hdr);
577
578 // { david, 2006.9.1
579 // fix the wpa process with wmm enabled.
580 if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) {
581 tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
582 }
583 // }
584 pos = skb_put(skb, 8);
585 if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr,
586 skb->data + hdr_len, skb->len - 8 - hdr_len, pos))
587 return -1;
588
589 return 0;
590}
591
592
593#if WIRELESS_EXT >= 18
594static void ieee80211_michael_mic_failure(struct net_device *dev,
595 struct ieee80211_hdr_4addr *hdr,
596 int keyidx)
597{
598 union iwreq_data wrqu;
599 struct iw_michaelmicfailure ev;
600
601 /* TODO: needed parameters: count, keyid, key type, TSC */
602 memset(&ev, 0, sizeof(ev));
603 ev.flags = keyidx & IW_MICFAILURE_KEY_ID;
604 if (hdr->addr1[0] & 0x01)
605 ev.flags |= IW_MICFAILURE_GROUP;
606 else
607 ev.flags |= IW_MICFAILURE_PAIRWISE;
608 ev.src_addr.sa_family = ARPHRD_ETHER;
609 memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN);
610 memset(&wrqu, 0, sizeof(wrqu));
611 wrqu.data.length = sizeof(ev);
612 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev);
613}
614#elif WIRELESS_EXT >= 15
615static void ieee80211_michael_mic_failure(struct net_device *dev,
616 struct ieee80211_hdr_4addr *hdr,
617 int keyidx)
618{
619 union iwreq_data wrqu;
620 char buf[128];
621
622 /* TODO: needed parameters: count, keyid, key type, TSC */
623 sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
624 "%pM)", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
625 hdr->addr2);
626 memset(&wrqu, 0, sizeof(wrqu));
627 wrqu.data.length = strlen(buf);
628 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
629}
630#else /* WIRELESS_EXT >= 15 */
631static inline void ieee80211_michael_mic_failure(struct net_device *dev,
632 struct ieee80211_hdr_4addr *hdr,
633 int keyidx)
634{
635}
636#endif /* WIRELESS_EXT >= 15 */
637
638static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
639 int hdr_len, void *priv)
640{
641 struct ieee80211_tkip_data *tkey = priv;
642 u8 mic[8];
643 struct ieee80211_hdr_4addr *hdr;
644
645 hdr = (struct ieee80211_hdr_4addr *) skb->data;
646
647 if (!tkey->key_set)
648 return -1;
649
650 michael_mic_hdr(skb, tkey->rx_hdr);
651 // { david, 2006.9.1
652 // fix the wpa process with wmm enabled.
653 if(IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) {
654 tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07;
655 }
656 // }
657
658 if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr,
659 skb->data + hdr_len, skb->len - 8 - hdr_len, mic))
660 return -1;
661 if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) {
662 struct ieee80211_hdr_4addr *hdr;
663 hdr = (struct ieee80211_hdr_4addr *) skb->data;
664 printk(KERN_DEBUG "%s: Michael MIC verification failed for "
665 "MSDU from %pM keyidx=%d\n",
666 skb->dev ? skb->dev->name : "N/A", hdr->addr2,
667 keyidx);
668 if (skb->dev)
669 ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
670 tkey->dot11RSNAStatsTKIPLocalMICFailures++;
671 return -1;
672 }
673
674 /* Update TSC counters for RX now that the packet verification has
675 * completed. */
676 tkey->rx_iv32 = tkey->rx_iv32_new;
677 tkey->rx_iv16 = tkey->rx_iv16_new;
678
679 skb_trim(skb, skb->len - 8);
680
681 return 0;
682}
683
684
685static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv)
686{
687 struct ieee80211_tkip_data *tkey = priv;
688 int keyidx;
689 struct crypto_hash *tfm = tkey->tx_tfm_michael;
690 struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4;
691 struct crypto_hash *tfm3 = tkey->rx_tfm_michael;
692 struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4;
693
694 keyidx = tkey->key_idx;
695 memset(tkey, 0, sizeof(*tkey));
696 tkey->key_idx = keyidx;
697 tkey->tx_tfm_michael = tfm;
698 tkey->tx_tfm_arc4 = tfm2;
699 tkey->rx_tfm_michael = tfm3;
700 tkey->rx_tfm_arc4 = tfm4;
701
702 if (len == TKIP_KEY_LEN) {
703 memcpy(tkey->key, key, TKIP_KEY_LEN);
704 tkey->key_set = 1;
705 tkey->tx_iv16 = 1; /* TSC is initialized to 1 */
706 if (seq) {
707 tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) |
708 (seq[3] << 8) | seq[2];
709 tkey->rx_iv16 = (seq[1] << 8) | seq[0];
710 }
711 } else if (len == 0)
712 tkey->key_set = 0;
713 else
714 return -1;
715
716 return 0;
717}
718
719
720static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv)
721{
722 struct ieee80211_tkip_data *tkey = priv;
723
724 if (len < TKIP_KEY_LEN)
725 return -1;
726
727 if (!tkey->key_set)
728 return 0;
729 memcpy(key, tkey->key, TKIP_KEY_LEN);
730
731 if (seq) {
732 /* Return the sequence number of the last transmitted frame. */
733 u16 iv16 = tkey->tx_iv16;
734 u32 iv32 = tkey->tx_iv32;
735 if (iv16 == 0)
736 iv32--;
737 iv16--;
738 seq[0] = tkey->tx_iv16;
739 seq[1] = tkey->tx_iv16 >> 8;
740 seq[2] = tkey->tx_iv32;
741 seq[3] = tkey->tx_iv32 >> 8;
742 seq[4] = tkey->tx_iv32 >> 16;
743 seq[5] = tkey->tx_iv32 >> 24;
744 }
745
746 return TKIP_KEY_LEN;
747}
748
749
750static char * ieee80211_tkip_print_stats(char *p, void *priv)
751{
752 struct ieee80211_tkip_data *tkip = priv;
753 p += sprintf(p, "key[%d] alg=TKIP key_set=%d "
754 "tx_pn=%02x%02x%02x%02x%02x%02x "
755 "rx_pn=%02x%02x%02x%02x%02x%02x "
756 "replays=%d icv_errors=%d local_mic_failures=%d\n",
757 tkip->key_idx, tkip->key_set,
758 (tkip->tx_iv32 >> 24) & 0xff,
759 (tkip->tx_iv32 >> 16) & 0xff,
760 (tkip->tx_iv32 >> 8) & 0xff,
761 tkip->tx_iv32 & 0xff,
762 (tkip->tx_iv16 >> 8) & 0xff,
763 tkip->tx_iv16 & 0xff,
764 (tkip->rx_iv32 >> 24) & 0xff,
765 (tkip->rx_iv32 >> 16) & 0xff,
766 (tkip->rx_iv32 >> 8) & 0xff,
767 tkip->rx_iv32 & 0xff,
768 (tkip->rx_iv16 >> 8) & 0xff,
769 tkip->rx_iv16 & 0xff,
770 tkip->dot11RSNAStatsTKIPReplays,
771 tkip->dot11RSNAStatsTKIPICVErrors,
772 tkip->dot11RSNAStatsTKIPLocalMICFailures);
773 return p;
774}
775
776
777static struct ieee80211_crypto_ops ieee80211_crypt_tkip = {
778 .name = "TKIP",
779 .init = ieee80211_tkip_init,
780 .deinit = ieee80211_tkip_deinit,
781 .encrypt_mpdu = ieee80211_tkip_encrypt,
782 .decrypt_mpdu = ieee80211_tkip_decrypt,
783 .encrypt_msdu = ieee80211_michael_mic_add,
784 .decrypt_msdu = ieee80211_michael_mic_verify,
785 .set_key = ieee80211_tkip_set_key,
786 .get_key = ieee80211_tkip_get_key,
787 .print_stats = ieee80211_tkip_print_stats,
788 .extra_prefix_len = 4 + 4, /* IV + ExtIV */
789 .extra_postfix_len = 8 + 4, /* MIC + ICV */
790 .owner = THIS_MODULE,
791};
792
793
794int __init ieee80211_crypto_tkip_init(void)
795{
796 return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip);
797}
798
799
800void ieee80211_crypto_tkip_exit(void)
801{
802 ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
803}
804
805void ieee80211_tkip_null(void)
806{
807 return;
808}
809
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c
new file mode 100644
index 00000000000..55043913afc
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c
@@ -0,0 +1,296 @@
1/*
2 * Host AP crypt: host-based WEP encryption implementation for Host AP driver
3 *
4 * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. See README and COPYING for
9 * more details.
10 */
11
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/slab.h>
15#include <linux/random.h>
16#include <linux/skbuff.h>
17#include <asm/string.h>
18
19#include "ieee80211.h"
20
21
22#include <linux/crypto.h>
23
24#include <linux/scatterlist.h>
25#include <linux/crc32.h>
26
27MODULE_AUTHOR("Jouni Malinen");
28MODULE_DESCRIPTION("Host AP crypt: WEP");
29MODULE_LICENSE("GPL");
30#ifndef OPENSUSE_SLED
31#define OPENSUSE_SLED 0
32#endif
33
34struct prism2_wep_data {
35 u32 iv;
36#define WEP_KEY_LEN 13
37 u8 key[WEP_KEY_LEN + 1];
38 u8 key_len;
39 u8 key_idx;
40 struct crypto_blkcipher *tx_tfm;
41 struct crypto_blkcipher *rx_tfm;
42};
43
44
45static void * prism2_wep_init(int keyidx)
46{
47 struct prism2_wep_data *priv;
48
49 priv = kzalloc(sizeof(*priv), GFP_ATOMIC);
50 if (priv == NULL)
51 goto fail;
52 priv->key_idx = keyidx;
53
54 priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
55 if (IS_ERR(priv->tx_tfm)) {
56 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
57 "crypto API arc4\n");
58 priv->tx_tfm = NULL;
59 goto fail;
60 }
61 priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC);
62 if (IS_ERR(priv->rx_tfm)) {
63 printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate "
64 "crypto API arc4\n");
65 priv->rx_tfm = NULL;
66 goto fail;
67 }
68
69 /* start WEP IV from a random value */
70 get_random_bytes(&priv->iv, 4);
71
72 return priv;
73
74fail:
75 if (priv) {
76 if (priv->tx_tfm)
77 crypto_free_blkcipher(priv->tx_tfm);
78 if (priv->rx_tfm)
79 crypto_free_blkcipher(priv->rx_tfm);
80 kfree(priv);
81 }
82 return NULL;
83}
84
85
86static void prism2_wep_deinit(void *priv)
87{
88 struct prism2_wep_data *_priv = priv;
89 if (_priv) {
90 if (_priv->tx_tfm)
91 crypto_free_blkcipher(_priv->tx_tfm);
92 if (_priv->rx_tfm)
93 crypto_free_blkcipher(_priv->rx_tfm);
94 }
95 kfree(priv);
96}
97
98/* Perform WEP encryption on given skb that has at least 4 bytes of headroom
99 * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted,
100 * so the payload length increases with 8 bytes.
101 *
102 * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data))
103 */
104static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
105{
106 struct prism2_wep_data *wep = priv;
107 u32 klen, len;
108 u8 key[WEP_KEY_LEN + 3];
109 u8 *pos;
110 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
111 struct blkcipher_desc desc = {.tfm = wep->tx_tfm};
112 u32 crc;
113 u8 *icv;
114 struct scatterlist sg;
115 if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 ||
116 skb->len < hdr_len)
117 return -1;
118
119 len = skb->len - hdr_len;
120 pos = skb_push(skb, 4);
121 memmove(pos, pos + 4, hdr_len);
122 pos += hdr_len;
123
124 klen = 3 + wep->key_len;
125
126 wep->iv++;
127
128 /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key
129 * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N)
130 * can be used to speedup attacks, so avoid using them. */
131 if ((wep->iv & 0xff00) == 0xff00) {
132 u8 B = (wep->iv >> 16) & 0xff;
133 if (B >= 3 && B < klen)
134 wep->iv += 0x0100;
135 }
136
137 /* Prepend 24-bit IV to RC4 key and TX frame */
138 *pos++ = key[0] = (wep->iv >> 16) & 0xff;
139 *pos++ = key[1] = (wep->iv >> 8) & 0xff;
140 *pos++ = key[2] = wep->iv & 0xff;
141 *pos++ = wep->key_idx << 6;
142
143 /* Copy rest of the WEP key (the secret part) */
144 memcpy(key + 3, wep->key, wep->key_len);
145
146 if (!tcb_desc->bHwSec)
147 {
148
149 /* Append little-endian CRC32 and encrypt it to produce ICV */
150 crc = ~crc32_le(~0, pos, len);
151 icv = skb_put(skb, 4);
152 icv[0] = crc;
153 icv[1] = crc >> 8;
154 icv[2] = crc >> 16;
155 icv[3] = crc >> 24;
156
157 crypto_blkcipher_setkey(wep->tx_tfm, key, klen);
158 sg_init_one(&sg, pos, len+4);
159 return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4);
160 }
161
162 return 0;
163}
164
165
166/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of
167 * the frame: IV (4 bytes), encrypted payload (including SNAP header),
168 * ICV (4 bytes). len includes both IV and ICV.
169 *
170 * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on
171 * failure. If frame is OK, IV and ICV will be removed.
172 */
173static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
174{
175 struct prism2_wep_data *wep = priv;
176 u32 klen, plen;
177 u8 key[WEP_KEY_LEN + 3];
178 u8 keyidx, *pos;
179 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
180 struct blkcipher_desc desc = {.tfm = wep->rx_tfm};
181 u32 crc;
182 u8 icv[4];
183 struct scatterlist sg;
184 if (skb->len < hdr_len + 8)
185 return -1;
186
187 pos = skb->data + hdr_len;
188 key[0] = *pos++;
189 key[1] = *pos++;
190 key[2] = *pos++;
191 keyidx = *pos++ >> 6;
192 if (keyidx != wep->key_idx)
193 return -1;
194
195 klen = 3 + wep->key_len;
196
197 /* Copy rest of the WEP key (the secret part) */
198 memcpy(key + 3, wep->key, wep->key_len);
199
200 /* Apply RC4 to data and compute CRC32 over decrypted data */
201 plen = skb->len - hdr_len - 8;
202
203 if (!tcb_desc->bHwSec)
204 {
205 crypto_blkcipher_setkey(wep->rx_tfm, key, klen);
206 sg_init_one(&sg, pos, plen+4);
207 if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4))
208 return -7;
209 crc = ~crc32_le(~0, pos, plen);
210 icv[0] = crc;
211 icv[1] = crc >> 8;
212 icv[2] = crc >> 16;
213 icv[3] = crc >> 24;
214 if (memcmp(icv, pos + plen, 4) != 0) {
215 /* ICV mismatch - drop frame */
216 return -2;
217 }
218 }
219 /* Remove IV and ICV */
220 memmove(skb->data + 4, skb->data, hdr_len);
221 skb_pull(skb, 4);
222 skb_trim(skb, skb->len - 4);
223
224 return 0;
225}
226
227
228static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv)
229{
230 struct prism2_wep_data *wep = priv;
231
232 if (len < 0 || len > WEP_KEY_LEN)
233 return -1;
234
235 memcpy(wep->key, key, len);
236 wep->key_len = len;
237
238 return 0;
239}
240
241
242static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv)
243{
244 struct prism2_wep_data *wep = priv;
245
246 if (len < wep->key_len)
247 return -1;
248
249 memcpy(key, wep->key, wep->key_len);
250
251 return wep->key_len;
252}
253
254
255static char * prism2_wep_print_stats(char *p, void *priv)
256{
257 struct prism2_wep_data *wep = priv;
258 p += sprintf(p, "key[%d] alg=WEP len=%d\n",
259 wep->key_idx, wep->key_len);
260 return p;
261}
262
263
264static struct ieee80211_crypto_ops ieee80211_crypt_wep = {
265 .name = "WEP",
266 .init = prism2_wep_init,
267 .deinit = prism2_wep_deinit,
268 .encrypt_mpdu = prism2_wep_encrypt,
269 .decrypt_mpdu = prism2_wep_decrypt,
270 .encrypt_msdu = NULL,
271 .decrypt_msdu = NULL,
272 .set_key = prism2_wep_set_key,
273 .get_key = prism2_wep_get_key,
274 .print_stats = prism2_wep_print_stats,
275 .extra_prefix_len = 4, /* IV */
276 .extra_postfix_len = 4, /* ICV */
277 .owner = THIS_MODULE,
278};
279
280
281int __init ieee80211_crypto_wep_init(void)
282{
283 return ieee80211_register_crypto_ops(&ieee80211_crypt_wep);
284}
285
286
287void __exit ieee80211_crypto_wep_exit(void)
288{
289 ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep);
290}
291
292void ieee80211_wep_null(void)
293{
294 return;
295}
296
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
new file mode 100644
index 00000000000..37a65ff4b12
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
@@ -0,0 +1,352 @@
1/*******************************************************************************
2
3 Copyright(c) 2004 Intel Corporation. All rights reserved.
4
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31*******************************************************************************/
32
33#include <linux/compiler.h>
34#include <linux/errno.h>
35#include <linux/if_arp.h>
36#include <linux/in6.h>
37#include <linux/in.h>
38#include <linux/ip.h>
39#include <linux/kernel.h>
40#include <linux/module.h>
41#include <linux/netdevice.h>
42#include <linux/pci.h>
43#include <linux/proc_fs.h>
44#include <linux/skbuff.h>
45#include <linux/slab.h>
46#include <linux/tcp.h>
47#include <linux/types.h>
48#include <linux/wireless.h>
49#include <linux/etherdevice.h>
50#include <asm/uaccess.h>
51#include <net/arp.h>
52
53#include "ieee80211.h"
54
55MODULE_DESCRIPTION("802.11 data/management/control stack");
56MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation <jketreno@linux.intel.com>");
57MODULE_LICENSE("GPL");
58
59#define DRV_NAME "ieee80211"
60
61static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee)
62{
63 if (ieee->networks)
64 return 0;
65
66 ieee->networks = kcalloc(
67 MAX_NETWORK_COUNT, sizeof(struct ieee80211_network),
68 GFP_KERNEL);
69 if (!ieee->networks) {
70 printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
71 ieee->dev->name);
72 return -ENOMEM;
73 }
74
75 return 0;
76}
77
78static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
79{
80 if (!ieee->networks)
81 return;
82 kfree(ieee->networks);
83 ieee->networks = NULL;
84}
85
86static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee)
87{
88 int i;
89
90 INIT_LIST_HEAD(&ieee->network_free_list);
91 INIT_LIST_HEAD(&ieee->network_list);
92 for (i = 0; i < MAX_NETWORK_COUNT; i++)
93 list_add_tail(&ieee->networks[i].list, &ieee->network_free_list);
94}
95
96
97struct net_device *alloc_ieee80211(int sizeof_priv)
98{
99 struct ieee80211_device *ieee;
100 struct net_device *dev;
101 int i, err;
102
103 IEEE80211_DEBUG_INFO("Initializing...\n");
104
105 dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
106 if (!dev) {
107 IEEE80211_ERROR("Unable to network device.\n");
108 goto failed;
109 }
110
111 ieee = netdev_priv(dev);
112
113 memset(ieee, 0, sizeof(struct ieee80211_device) + sizeof_priv);
114 ieee->dev = dev;
115
116 err = ieee80211_networks_allocate(ieee);
117 if (err) {
118 IEEE80211_ERROR("Unable to allocate beacon storage: %d\n",
119 err);
120 goto failed;
121 }
122 ieee80211_networks_initialize(ieee);
123
124
125 /* Default fragmentation threshold is maximum payload size */
126 ieee->fts = DEFAULT_FTS;
127 ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
128 ieee->open_wep = 1;
129
130 /* Default to enabling full open WEP with host based encrypt/decrypt */
131 ieee->host_encrypt = 1;
132 ieee->host_decrypt = 1;
133 ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
134
135 INIT_LIST_HEAD(&ieee->crypt_deinit_list);
136 init_timer(&ieee->crypt_deinit_timer);
137 ieee->crypt_deinit_timer.data = (unsigned long)ieee;
138 ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler;
139
140 spin_lock_init(&ieee->lock);
141 spin_lock_init(&ieee->wpax_suitlist_lock);
142 spin_lock_init(&ieee->bw_spinlock);
143 spin_lock_init(&ieee->reorder_spinlock);
144
145 /* added by WB */
146 atomic_set(&(ieee->atm_chnlop), 0);
147 atomic_set(&(ieee->atm_swbw), 0);
148
149 ieee->wpax_type_set = 0;
150 ieee->wpa_enabled = 0;
151 ieee->tkip_countermeasures = 0;
152 ieee->drop_unencrypted = 0;
153 ieee->privacy_invoked = 0;
154 ieee->ieee802_1x = 1;
155 ieee->raw_tx = 0;
156 /* ieee->hwsec_support = 1; default support hw security: use module_param instead */
157 ieee->hwsec_active = 0; /* disable hwsec, switch it on when necessary */
158
159 ieee80211_softmac_init(ieee);
160
161 ieee->pHTInfo = kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL);
162 if (ieee->pHTInfo == NULL)
163 {
164 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for HTInfo\n");
165 return NULL;
166 }
167 HTUpdateDefaultSetting(ieee);
168 HTInitializeHTInfo(ieee); /* may move to other place */
169 TSInitialize(ieee);
170 for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++)
171 INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]);
172
173 for (i = 0; i < 17; i++) {
174 ieee->last_rxseq_num[i] = -1;
175 ieee->last_rxfrag_num[i] = -1;
176 ieee->last_packet_time[i] = 0;
177 }
178
179 /* Functions to load crypt module automatically */
180 ieee80211_tkip_null();
181 ieee80211_wep_null();
182 ieee80211_ccmp_null();
183
184 return dev;
185
186failed:
187 if (dev)
188 free_netdev(dev);
189 return NULL;
190}
191
192
193void free_ieee80211(struct net_device *dev)
194{
195 struct ieee80211_device *ieee = netdev_priv(dev);
196 int i;
197 kfree(ieee->pHTInfo);
198 ieee->pHTInfo = NULL;
199 RemoveAllTS(ieee);
200 ieee80211_softmac_free(ieee);
201 del_timer_sync(&ieee->crypt_deinit_timer);
202 ieee80211_crypt_deinit_entries(ieee, 1);
203
204 for (i = 0; i < WEP_KEYS; i++) {
205 struct ieee80211_crypt_data *crypt = ieee->crypt[i];
206 if (crypt) {
207 if (crypt->ops)
208 crypt->ops->deinit(crypt->priv);
209 kfree(crypt);
210 ieee->crypt[i] = NULL;
211 }
212 }
213
214 ieee80211_networks_free(ieee);
215 free_netdev(dev);
216}
217
218#ifdef CONFIG_IEEE80211_DEBUG
219
220u32 ieee80211_debug_level = 0;
221static int debug =
222 /* IEEE80211_DL_INFO | */
223 /* IEEE80211_DL_WX | */
224 /* IEEE80211_DL_SCAN | */
225 /* IEEE80211_DL_STATE | */
226 /* IEEE80211_DL_MGMT | */
227 /* IEEE80211_DL_FRAG | */
228 /* IEEE80211_DL_EAP | */
229 /* IEEE80211_DL_DROP | */
230 /* IEEE80211_DL_TX | */
231 /* IEEE80211_DL_RX | */
232 /* IEEE80211_DL_QOS | */
233 /* IEEE80211_DL_HT | */
234 /* IEEE80211_DL_TS | */
235 /* IEEE80211_DL_BA | */
236 /* IEEE80211_DL_REORDER | */
237 /* IEEE80211_DL_TRACE | */
238 /* IEEE80211_DL_DATA | */
239 IEEE80211_DL_ERR /* always open this flag to show error out */
240 ;
241struct proc_dir_entry *ieee80211_proc = NULL;
242
243static int show_debug_level(char *page, char **start, off_t offset,
244 int count, int *eof, void *data)
245{
246 return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
247}
248
249static int store_debug_level(struct file *file, const char *buffer,
250 unsigned long count, void *data)
251{
252 char buf[] = "0x00000000";
253 unsigned long len = min(sizeof(buf) - 1, (u32)count);
254 char *p = (char *)buf;
255 unsigned long val;
256
257 if (copy_from_user(buf, buffer, len))
258 return count;
259 buf[len] = 0;
260 if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
261 p++;
262 if (p[0] == 'x' || p[0] == 'X')
263 p++;
264 val = simple_strtoul(p, &p, 16);
265 } else
266 val = simple_strtoul(p, &p, 10);
267 if (p == buf)
268 printk(KERN_INFO DRV_NAME
269 ": %s is not in hex or decimal form.\n", buf);
270 else
271 ieee80211_debug_level = val;
272
273 return strnlen(buf, count);
274}
275
276extern int ieee80211_crypto_init(void);
277extern void ieee80211_crypto_deinit(void);
278extern int ieee80211_crypto_tkip_init(void);
279extern void ieee80211_crypto_tkip_exit(void);
280extern int ieee80211_crypto_ccmp_init(void);
281extern void ieee80211_crypto_ccmp_exit(void);
282extern int ieee80211_crypto_wep_init(void);
283extern void ieee80211_crypto_wep_exit(void);
284
285int __init ieee80211_rtl_init(void)
286{
287 struct proc_dir_entry *e;
288 int retval;
289
290 retval = ieee80211_crypto_init();
291 if (retval)
292 return retval;
293 retval = ieee80211_crypto_tkip_init();
294 if (retval) {
295 ieee80211_crypto_deinit();
296 return retval;
297 }
298 retval = ieee80211_crypto_ccmp_init();
299 if (retval) {
300 ieee80211_crypto_tkip_exit();
301 ieee80211_crypto_deinit();
302 return retval;
303 }
304 retval = ieee80211_crypto_wep_init();
305 if (retval) {
306 ieee80211_crypto_ccmp_exit();
307 ieee80211_crypto_tkip_exit();
308 ieee80211_crypto_deinit();
309 return retval;
310 }
311
312 ieee80211_debug_level = debug;
313 ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
314 if (ieee80211_proc == NULL) {
315 IEEE80211_ERROR("Unable to create " DRV_NAME
316 " proc directory\n");
317 return -EIO;
318 }
319 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
320 ieee80211_proc);
321 if (!e) {
322 remove_proc_entry(DRV_NAME, init_net.proc_net);
323 ieee80211_proc = NULL;
324 return -EIO;
325 }
326 e->read_proc = show_debug_level;
327 e->write_proc = store_debug_level;
328 e->data = NULL;
329
330 return 0;
331}
332
333void __exit ieee80211_rtl_exit(void)
334{
335 if (ieee80211_proc) {
336 remove_proc_entry("debug_level", ieee80211_proc);
337 remove_proc_entry(DRV_NAME, init_net.proc_net);
338 ieee80211_proc = NULL;
339 }
340 ieee80211_crypto_wep_exit();
341 ieee80211_crypto_ccmp_exit();
342 ieee80211_crypto_tkip_exit();
343 ieee80211_crypto_deinit();
344}
345
346#include <linux/moduleparam.h>
347module_param(debug, int, 0444);
348MODULE_PARM_DESC(debug, "debug output mask");
349
350
351#endif
352
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
new file mode 100644
index 00000000000..022086d2a3f
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
@@ -0,0 +1,2676 @@
1/*
2 * Original code based Host AP (software wireless LAN access point) driver
3 * for Intersil Prism2/2.5/3 - hostap.o module, common routines
4 *
5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
8 * Copyright (c) 2004, Intel Corporation
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. See README and COPYING for
13 * more details.
14 ******************************************************************************
15
16 Few modifications for Realtek's Wi-Fi drivers by
17 Andrea Merello <andreamrl@tiscali.it>
18
19 A special thanks goes to Realtek for their support !
20
21******************************************************************************/
22
23
24#include <linux/compiler.h>
25#include <linux/errno.h>
26#include <linux/if_arp.h>
27#include <linux/in6.h>
28#include <linux/in.h>
29#include <linux/ip.h>
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/netdevice.h>
33#include <linux/pci.h>
34#include <linux/proc_fs.h>
35#include <linux/skbuff.h>
36#include <linux/slab.h>
37#include <linux/tcp.h>
38#include <linux/types.h>
39#include <linux/wireless.h>
40#include <linux/etherdevice.h>
41#include <asm/uaccess.h>
42#include <linux/ctype.h>
43
44#include "ieee80211.h"
45#ifdef ENABLE_DOT11D
46#include "dot11d.h"
47#endif
48static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
49 struct sk_buff *skb,
50 struct ieee80211_rx_stats *rx_stats)
51{
52 struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *)skb->data;
53 u16 fc = le16_to_cpu(hdr->frame_ctl);
54
55 skb->dev = ieee->dev;
56 skb_reset_mac_header(skb);
57
58 skb_pull(skb, ieee80211_get_hdrlen(fc));
59 skb->pkt_type = PACKET_OTHERHOST;
60 skb->protocol = __constant_htons(ETH_P_80211_RAW);
61 memset(skb->cb, 0, sizeof(skb->cb));
62 netif_rx(skb);
63}
64
65
66/* Called only as a tasklet (software IRQ) */
67static struct ieee80211_frag_entry *
68ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
69 unsigned int frag, u8 tid,u8 *src, u8 *dst)
70{
71 struct ieee80211_frag_entry *entry;
72 int i;
73
74 for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
75 entry = &ieee->frag_cache[tid][i];
76 if (entry->skb != NULL &&
77 time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
78 IEEE80211_DEBUG_FRAG(
79 "expiring fragment cache entry "
80 "seq=%u last_frag=%u\n",
81 entry->seq, entry->last_frag);
82 dev_kfree_skb_any(entry->skb);
83 entry->skb = NULL;
84 }
85
86 if (entry->skb != NULL && entry->seq == seq &&
87 (entry->last_frag + 1 == frag || frag == -1) &&
88 memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
89 memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
90 return entry;
91 }
92
93 return NULL;
94}
95
96/* Called only as a tasklet (software IRQ) */
97static struct sk_buff *
98ieee80211_frag_cache_get(struct ieee80211_device *ieee,
99 struct ieee80211_hdr_4addr *hdr)
100{
101 struct sk_buff *skb = NULL;
102 u16 fc = le16_to_cpu(hdr->frame_ctl);
103 u16 sc = le16_to_cpu(hdr->seq_ctl);
104 unsigned int frag = WLAN_GET_SEQ_FRAG(sc);
105 unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
106 struct ieee80211_frag_entry *entry;
107 struct ieee80211_hdr_3addrqos *hdr_3addrqos;
108 struct ieee80211_hdr_4addrqos *hdr_4addrqos;
109 u8 tid;
110
111 if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
112 hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
113 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
114 tid = UP2AC(tid);
115 tid ++;
116 } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
117 hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
118 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
119 tid = UP2AC(tid);
120 tid ++;
121 } else {
122 tid = 0;
123 }
124
125 if (frag == 0) {
126 /* Reserve enough space to fit maximum frame length */
127 skb = dev_alloc_skb(ieee->dev->mtu +
128 sizeof(struct ieee80211_hdr_4addr) +
129 8 /* LLC */ +
130 2 /* alignment */ +
131 8 /* WEP */ +
132 ETH_ALEN /* WDS */ +
133 (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */);
134 if (skb == NULL)
135 return NULL;
136
137 entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]];
138 ieee->frag_next_idx[tid]++;
139 if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN)
140 ieee->frag_next_idx[tid] = 0;
141
142 if (entry->skb != NULL)
143 dev_kfree_skb_any(entry->skb);
144
145 entry->first_frag_time = jiffies;
146 entry->seq = seq;
147 entry->last_frag = frag;
148 entry->skb = skb;
149 memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
150 memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
151 } else {
152 /* received a fragment of a frame for which the head fragment
153 * should have already been received */
154 entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2,
155 hdr->addr1);
156 if (entry != NULL) {
157 entry->last_frag = frag;
158 skb = entry->skb;
159 }
160 }
161
162 return skb;
163}
164
165
166/* Called only as a tasklet (software IRQ) */
167static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
168 struct ieee80211_hdr_4addr *hdr)
169{
170 u16 fc = le16_to_cpu(hdr->frame_ctl);
171 u16 sc = le16_to_cpu(hdr->seq_ctl);
172 unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
173 struct ieee80211_frag_entry *entry;
174 struct ieee80211_hdr_3addrqos *hdr_3addrqos;
175 struct ieee80211_hdr_4addrqos *hdr_4addrqos;
176 u8 tid;
177
178 if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
179 hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
180 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
181 tid = UP2AC(tid);
182 tid ++;
183 } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
184 hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
185 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
186 tid = UP2AC(tid);
187 tid ++;
188 } else {
189 tid = 0;
190 }
191
192 entry = ieee80211_frag_cache_find(ieee, seq, -1, tid,hdr->addr2,
193 hdr->addr1);
194
195 if (entry == NULL) {
196 IEEE80211_DEBUG_FRAG(
197 "could not invalidate fragment cache "
198 "entry (seq=%u)\n", seq);
199 return -1;
200 }
201
202 entry->skb = NULL;
203 return 0;
204}
205
206
207
208/* ieee80211_rx_frame_mgtmt
209 *
210 * Responsible for handling management control frames
211 *
212 * Called by ieee80211_rx */
213static inline int
214ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
215 struct ieee80211_rx_stats *rx_stats, u16 type,
216 u16 stype)
217{
218 /* On the struct stats definition there is written that
219 * this is not mandatory.... but seems that the probe
220 * response parser uses it
221 */
222 struct ieee80211_hdr_3addr * hdr = (struct ieee80211_hdr_3addr *)skb->data;
223
224 rx_stats->len = skb->len;
225 ieee80211_rx_mgt(ieee,(struct ieee80211_hdr_4addr *)skb->data,rx_stats);
226 if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))//use ADDR1 to perform address matching for Management frames
227 {
228 dev_kfree_skb_any(skb);
229 return 0;
230 }
231
232 ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
233
234 dev_kfree_skb_any(skb);
235
236 return 0;
237
238 #ifdef NOT_YET
239 if (ieee->iw_mode == IW_MODE_MASTER) {
240 printk(KERN_DEBUG "%s: Master mode not yet suppported.\n",
241 ieee->dev->name);
242 return 0;
243 }
244
245 if (ieee->hostapd && type == IEEE80211_TYPE_MGMT) {
246 if (stype == WLAN_FC_STYPE_BEACON &&
247 ieee->iw_mode == IW_MODE_MASTER) {
248 struct sk_buff *skb2;
249 /* Process beacon frames also in kernel driver to
250 * update STA(AP) table statistics */
251 skb2 = skb_clone(skb, GFP_ATOMIC);
252 if (skb2)
253 hostap_rx(skb2->dev, skb2, rx_stats);
254 }
255
256 /* send management frames to the user space daemon for
257 * processing */
258 ieee->apdevstats.rx_packets++;
259 ieee->apdevstats.rx_bytes += skb->len;
260 prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT);
261 return 0;
262 }
263
264 if (ieee->iw_mode == IW_MODE_MASTER) {
265 if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) {
266 printk(KERN_DEBUG "%s: unknown management frame "
267 "(type=0x%02x, stype=0x%02x) dropped\n",
268 skb->dev->name, type, stype);
269 return -1;
270 }
271
272 hostap_rx(skb->dev, skb, rx_stats);
273 return 0;
274 }
275
276 printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame "
277 "received in non-Host AP mode\n", skb->dev->name);
278 return -1;
279 #endif
280}
281
282
283
284/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
285/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
286static unsigned char rfc1042_header[] =
287{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
288/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
289static unsigned char bridge_tunnel_header[] =
290{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
291/* No encapsulation header if EtherType < 0x600 (=length) */
292
293/* Called by ieee80211_rx_frame_decrypt */
294static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
295 struct sk_buff *skb, size_t hdrlen)
296{
297 struct net_device *dev = ieee->dev;
298 u16 fc, ethertype;
299 struct ieee80211_hdr_4addr *hdr;
300 u8 *pos;
301
302 if (skb->len < 24)
303 return 0;
304
305 if (ieee->hwsec_active)
306 {
307 cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
308 tcb_desc->bHwSec = 1;
309
310 if(ieee->need_sw_enc)
311 tcb_desc->bHwSec = 0;
312 }
313
314 hdr = (struct ieee80211_hdr_4addr *) skb->data;
315 fc = le16_to_cpu(hdr->frame_ctl);
316
317 /* check that the frame is unicast frame to us */
318 if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
319 IEEE80211_FCTL_TODS &&
320 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
321 memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
322 /* ToDS frame with own addr BSSID and DA */
323 } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
324 IEEE80211_FCTL_FROMDS &&
325 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
326 /* FromDS frame with own addr as DA */
327 } else
328 return 0;
329
330 if (skb->len < 24 + 8)
331 return 0;
332
333 /* check for port access entity Ethernet type */
334 pos = skb->data + hdrlen;
335 ethertype = (pos[6] << 8) | pos[7];
336 if (ethertype == ETH_P_PAE)
337 return 1;
338
339 return 0;
340}
341
342/* Called only as a tasklet (software IRQ), by ieee80211_rx */
343static inline int
344ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
345 struct ieee80211_crypt_data *crypt)
346{
347 struct ieee80211_hdr_4addr *hdr;
348 int res, hdrlen;
349
350 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
351 return 0;
352
353 if (ieee->hwsec_active)
354 {
355 cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
356 tcb_desc->bHwSec = 1;
357 }
358
359 hdr = (struct ieee80211_hdr_4addr *) skb->data;
360 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
361
362#ifdef CONFIG_IEEE80211_CRYPT_TKIP
363 if (ieee->tkip_countermeasures &&
364 strcmp(crypt->ops->name, "TKIP") == 0) {
365 if (net_ratelimit()) {
366 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
367 "received packet from %pM\n",
368 ieee->dev->name, hdr->addr2);
369 }
370 return -1;
371 }
372#endif
373
374 atomic_inc(&crypt->refcnt);
375 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
376 atomic_dec(&crypt->refcnt);
377 if (res < 0) {
378 IEEE80211_DEBUG_DROP(
379 "decryption failed (SA=%pM"
380 ") res=%d\n", hdr->addr2, res);
381 if (res == -2)
382 IEEE80211_DEBUG_DROP("Decryption failed ICV "
383 "mismatch (key %d)\n",
384 skb->data[hdrlen + 3] >> 6);
385 ieee->ieee_stats.rx_discards_undecryptable++;
386 return -1;
387 }
388
389 return res;
390}
391
392
393/* Called only as a tasklet (software IRQ), by ieee80211_rx */
394static inline int
395ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *skb,
396 int keyidx, struct ieee80211_crypt_data *crypt)
397{
398 struct ieee80211_hdr_4addr *hdr;
399 int res, hdrlen;
400
401 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
402 return 0;
403 if (ieee->hwsec_active)
404 {
405 cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
406 tcb_desc->bHwSec = 1;
407
408 if(ieee->need_sw_enc)
409 tcb_desc->bHwSec = 0;
410
411 }
412
413 hdr = (struct ieee80211_hdr_4addr *) skb->data;
414 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
415
416 atomic_inc(&crypt->refcnt);
417 res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
418 atomic_dec(&crypt->refcnt);
419 if (res < 0) {
420 printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
421 " (SA=%pM keyidx=%d)\n",
422 ieee->dev->name, hdr->addr2, keyidx);
423 return -1;
424 }
425
426 return 0;
427}
428
429
430/* this function is stolen from ipw2200 driver*/
431#define IEEE_PACKET_RETRY_TIME (5*HZ)
432static int is_duplicate_packet(struct ieee80211_device *ieee,
433 struct ieee80211_hdr_4addr *header)
434{
435 u16 fc = le16_to_cpu(header->frame_ctl);
436 u16 sc = le16_to_cpu(header->seq_ctl);
437 u16 seq = WLAN_GET_SEQ_SEQ(sc);
438 u16 frag = WLAN_GET_SEQ_FRAG(sc);
439 u16 *last_seq, *last_frag;
440 unsigned long *last_time;
441 struct ieee80211_hdr_3addrqos *hdr_3addrqos;
442 struct ieee80211_hdr_4addrqos *hdr_4addrqos;
443 u8 tid;
444
445
446 //TO2DS and QoS
447 if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
448 hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header;
449 tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
450 tid = UP2AC(tid);
451 tid ++;
452 } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS
453 hdr_3addrqos = (struct ieee80211_hdr_3addrqos*)header;
454 tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
455 tid = UP2AC(tid);
456 tid ++;
457 } else { // no QoS
458 tid = 0;
459 }
460
461 switch (ieee->iw_mode) {
462 case IW_MODE_ADHOC:
463 {
464 struct list_head *p;
465 struct ieee_ibss_seq *entry = NULL;
466 u8 *mac = header->addr2;
467 int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
468
469 list_for_each(p, &ieee->ibss_mac_hash[index]) {
470 entry = list_entry(p, struct ieee_ibss_seq, list);
471 if (!memcmp(entry->mac, mac, ETH_ALEN))
472 break;
473 }
474
475 if (p == &ieee->ibss_mac_hash[index]) {
476 entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
477 if (!entry) {
478 printk(KERN_WARNING "Cannot malloc new mac entry\n");
479 return 0;
480 }
481 memcpy(entry->mac, mac, ETH_ALEN);
482 entry->seq_num[tid] = seq;
483 entry->frag_num[tid] = frag;
484 entry->packet_time[tid] = jiffies;
485 list_add(&entry->list, &ieee->ibss_mac_hash[index]);
486 return 0;
487 }
488 last_seq = &entry->seq_num[tid];
489 last_frag = &entry->frag_num[tid];
490 last_time = &entry->packet_time[tid];
491 break;
492 }
493
494 case IW_MODE_INFRA:
495 last_seq = &ieee->last_rxseq_num[tid];
496 last_frag = &ieee->last_rxfrag_num[tid];
497 last_time = &ieee->last_packet_time[tid];
498
499 break;
500 default:
501 return 0;
502 }
503
504 if ((*last_seq == seq) &&
505 time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
506 if (*last_frag == frag){
507 goto drop;
508
509 }
510 if (*last_frag + 1 != frag)
511 /* out-of-order fragment */
512 goto drop;
513 } else
514 *last_seq = seq;
515
516 *last_frag = frag;
517 *last_time = jiffies;
518 return 0;
519
520drop:
521 return 1;
522}
523bool
524AddReorderEntry(
525 PRX_TS_RECORD pTS,
526 PRX_REORDER_ENTRY pReorderEntry
527 )
528{
529 struct list_head *pList = &pTS->RxPendingPktList;
530
531 while(pList->next != &pTS->RxPendingPktList)
532 {
533 if( SN_LESS(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) )
534 {
535 pList = pList->next;
536 }
537 else if( SN_EQUAL(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) )
538 {
539 return false;
540 }
541 else
542 {
543 break;
544 }
545 }
546
547 pReorderEntry->List.next = pList->next;
548 pReorderEntry->List.next->prev = &pReorderEntry->List;
549 pReorderEntry->List.prev = pList;
550 pList->next = &pReorderEntry->List;
551
552 return true;
553}
554
555void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8 index)
556{
557 u8 i = 0 , j=0;
558 u16 ethertype;
559
560 for(j = 0; j<index; j++)
561 {
562//added by amy for reorder
563 struct ieee80211_rxb* prxb = prxbIndicateArray[j];
564 for(i = 0; i<prxb->nr_subframes; i++) {
565 struct sk_buff *sub_skb = prxb->subframes[i];
566
567 /* convert hdr + possible LLC headers into Ethernet header */
568 ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
569 if (sub_skb->len >= 8 &&
570 ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
571 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
572 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
573 /* remove RFC1042 or Bridge-Tunnel encapsulation and
574 * replace EtherType */
575 skb_pull(sub_skb, SNAP_SIZE);
576 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
577 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
578 } else {
579 u16 len;
580 /* Leave Ethernet header part of hdr and full payload */
581 len = htons(sub_skb->len);
582 memcpy(skb_push(sub_skb, 2), &len, 2);
583 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
584 memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
585 }
586
587 /* Indicat the packets to upper layer */
588 if (sub_skb) {
589 sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev);
590 memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
591 sub_skb->dev = ieee->dev;
592 sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
593 ieee->last_rx_ps_time = jiffies;
594 netif_rx(sub_skb);
595 }
596 }
597 kfree(prxb);
598 prxb = NULL;
599 }
600}
601
602
603void RxReorderIndicatePacket( struct ieee80211_device *ieee,
604 struct ieee80211_rxb* prxb,
605 PRX_TS_RECORD pTS,
606 u16 SeqNum)
607{
608 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
609 PRX_REORDER_ENTRY pReorderEntry = NULL;
610 struct ieee80211_rxb* prxbIndicateArray[REORDER_WIN_SIZE];
611 u8 WinSize = pHTInfo->RxReorderWinSize;
612 u16 WinEnd = (pTS->RxIndicateSeq + WinSize -1)%4096;
613 u8 index = 0;
614 bool bMatchWinStart = false, bPktInBuf = false;
615 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__FUNCTION__,SeqNum,pTS->RxIndicateSeq,WinSize);
616
617 /* Rx Reorder initialize condition.*/
618 if(pTS->RxIndicateSeq == 0xffff) {
619 pTS->RxIndicateSeq = SeqNum;
620 }
621
622 /* Drop out the packet which SeqNum is smaller than WinStart */
623 if(SN_LESS(SeqNum, pTS->RxIndicateSeq)) {
624 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packet Drop! IndicateSeq: %d, NewSeq: %d\n",
625 pTS->RxIndicateSeq, SeqNum);
626 pHTInfo->RxReorderDropCounter++;
627 {
628 int i;
629 for(i =0; i < prxb->nr_subframes; i++) {
630 dev_kfree_skb(prxb->subframes[i]);
631 }
632 kfree(prxb);
633 prxb = NULL;
634 }
635 return;
636 }
637
638 /*
639 * Sliding window manipulation. Conditions includes:
640 * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
641 * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
642 */
643 if(SN_EQUAL(SeqNum, pTS->RxIndicateSeq)) {
644 pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
645 bMatchWinStart = true;
646 } else if(SN_LESS(WinEnd, SeqNum)) {
647 if(SeqNum >= (WinSize - 1)) {
648 pTS->RxIndicateSeq = SeqNum + 1 -WinSize;
649 } else {
650 pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum +1)) + 1;
651 }
652 IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
653 }
654
655 /*
656 * Indication process.
657 * After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets
658 * with the SeqNum smaller than latest WinStart and buffer other packets.
659 */
660 /* For Rx Reorder condition:
661 * 1. All packets with SeqNum smaller than WinStart => Indicate
662 * 2. All packets with SeqNum larger than or equal to WinStart => Buffer it.
663 */
664 if(bMatchWinStart) {
665 /* Current packet is going to be indicated.*/
666 IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\
667 pTS->RxIndicateSeq, SeqNum);
668 prxbIndicateArray[0] = prxb;
669 index = 1;
670 } else {
671 /* Current packet is going to be inserted into pending list.*/
672 if(!list_empty(&ieee->RxReorder_Unused_List)) {
673 pReorderEntry = (PRX_REORDER_ENTRY)list_entry(ieee->RxReorder_Unused_List.next,RX_REORDER_ENTRY,List);
674 list_del_init(&pReorderEntry->List);
675
676 /* Make a reorder entry and insert into a the packet list.*/
677 pReorderEntry->SeqNum = SeqNum;
678 pReorderEntry->prxb = prxb;
679
680 if(!AddReorderEntry(pTS, pReorderEntry)) {
681 IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n",
682 __FUNCTION__, pTS->RxIndicateSeq, SeqNum);
683 list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List);
684 {
685 int i;
686 for(i =0; i < prxb->nr_subframes; i++) {
687 dev_kfree_skb(prxb->subframes[i]);
688 }
689 kfree(prxb);
690 prxb = NULL;
691 }
692 } else {
693 IEEE80211_DEBUG(IEEE80211_DL_REORDER,
694 "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
695 }
696 }
697 else {
698 /*
699 * Packets are dropped if there is not enough reorder entries.
700 * This part shall be modified!! We can just indicate all the
701 * packets in buffer and get reorder entries.
702 */
703 IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n");
704 {
705 int i;
706 for(i =0; i < prxb->nr_subframes; i++) {
707 dev_kfree_skb(prxb->subframes[i]);
708 }
709 kfree(prxb);
710 prxb = NULL;
711 }
712 }
713 }
714
715 /* Check if there is any packet need indicate.*/
716 while(!list_empty(&pTS->RxPendingPktList)) {
717 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): start RREORDER indicate\n",__FUNCTION__);
718#if 1
719 pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
720 if( SN_LESS(pReorderEntry->SeqNum, pTS->RxIndicateSeq) ||
721 SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
722 {
723 /* This protect buffer from overflow. */
724 if(index >= REORDER_WIN_SIZE) {
725 IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!! \n");
726 bPktInBuf = true;
727 break;
728 }
729
730 list_del_init(&pReorderEntry->List);
731
732 if(SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
733 pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
734
735 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packets indication!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
736 prxbIndicateArray[index] = pReorderEntry->prxb;
737 index++;
738
739 list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List);
740 } else {
741 bPktInBuf = true;
742 break;
743 }
744#endif
745 }
746
747 /* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/
748 if(index>0) {
749 // Cancel previous pending timer.
750 if (timer_pending(&pTS->RxPktPendingTimer))
751 del_timer_sync(&pTS->RxPktPendingTimer);
752 pTS->RxTimeoutIndicateSeq = 0xffff;
753
754 // Indicate packets
755 if(index>REORDER_WIN_SIZE){
756 IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
757 return;
758 }
759 ieee80211_indicate_packets(ieee, prxbIndicateArray, index);
760 bPktInBuf = false;
761 }
762
763 if(bPktInBuf && pTS->RxTimeoutIndicateSeq==0xffff) {
764 // Set new pending timer.
765 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): SET rx timeout timer\n", __FUNCTION__);
766 pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq;
767
768 mod_timer(&pTS->RxPktPendingTimer, jiffies + MSECS(pHTInfo->RxReorderPendingTime));
769 }
770}
771
772u8 parse_subframe(struct ieee80211_device* ieee,struct sk_buff *skb,
773 struct ieee80211_rx_stats *rx_stats,
774 struct ieee80211_rxb *rxb,u8* src,u8* dst)
775{
776 struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr* )skb->data;
777 u16 fc = le16_to_cpu(hdr->frame_ctl);
778
779 u16 LLCOffset= sizeof(struct ieee80211_hdr_3addr);
780 u16 ChkLength;
781 bool bIsAggregateFrame = false;
782 u16 nSubframe_Length;
783 u8 nPadding_Length = 0;
784 u16 SeqNum=0;
785
786 struct sk_buff *sub_skb;
787 u8 *data_ptr;
788 /* just for debug purpose */
789 SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
790
791 if((IEEE80211_QOS_HAS_SEQ(fc))&&\
792 (((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) {
793 bIsAggregateFrame = true;
794 }
795
796 if(IEEE80211_QOS_HAS_SEQ(fc)) {
797 LLCOffset += 2;
798 }
799
800 if(rx_stats->bContainHTC) {
801 LLCOffset += sHTCLng;
802 }
803 // Null packet, don't indicate it to upper layer
804 ChkLength = LLCOffset;/* + (Frame_WEP(frame)!=0 ?Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead:0);*/
805
806 if( skb->len <= ChkLength ) {
807 return 0;
808 }
809
810 skb_pull(skb, LLCOffset);
811 ieee->bIsAggregateFrame = bIsAggregateFrame;//added by amy for Leisure PS
812
813 if(!bIsAggregateFrame) {
814 rxb->nr_subframes = 1;
815#ifdef JOHN_NOCPY
816 rxb->subframes[0] = skb;
817#else
818 rxb->subframes[0] = skb_copy(skb, GFP_ATOMIC);
819#endif
820
821 memcpy(rxb->src,src,ETH_ALEN);
822 memcpy(rxb->dst,dst,ETH_ALEN);
823 //IEEE80211_DEBUG_DATA(IEEE80211_DL_RX,skb->data,skb->len);
824 return 1;
825 } else {
826 rxb->nr_subframes = 0;
827 memcpy(rxb->src,src,ETH_ALEN);
828 memcpy(rxb->dst,dst,ETH_ALEN);
829 while(skb->len > ETHERNET_HEADER_SIZE) {
830 /* Offset 12 denote 2 mac address */
831 nSubframe_Length = *((u16*)(skb->data + 12));
832 //==m==>change the length order
833 nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8);
834
835 if(skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) {
836 printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\
837 __FUNCTION__,rxb->nr_subframes);
838 printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__FUNCTION__, nSubframe_Length);
839 printk("nRemain_Length is %d and nSubframe_Length is : %d\n",skb->len,nSubframe_Length);
840 printk("The Packet SeqNum is %d\n",SeqNum);
841 return 0;
842 }
843
844 /* move the data point to data content */
845 skb_pull(skb, ETHERNET_HEADER_SIZE);
846
847#ifdef JOHN_NOCPY
848 sub_skb = skb_clone(skb, GFP_ATOMIC);
849 sub_skb->len = nSubframe_Length;
850 sub_skb->tail = sub_skb->data + nSubframe_Length;
851#else
852 /* Allocate new skb for releasing to upper layer */
853 sub_skb = dev_alloc_skb(nSubframe_Length + 12);
854 skb_reserve(sub_skb, 12);
855 data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
856 memcpy(data_ptr,skb->data,nSubframe_Length);
857#endif
858 rxb->subframes[rxb->nr_subframes++] = sub_skb;
859 if(rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
860 IEEE80211_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
861 break;
862 }
863 skb_pull(skb,nSubframe_Length);
864
865 if(skb->len != 0) {
866 nPadding_Length = 4 - ((nSubframe_Length + ETHERNET_HEADER_SIZE) % 4);
867 if(nPadding_Length == 4) {
868 nPadding_Length = 0;
869 }
870
871 if(skb->len < nPadding_Length) {
872 return 0;
873 }
874
875 skb_pull(skb,nPadding_Length);
876 }
877 }
878#ifdef JOHN_NOCPY
879 dev_kfree_skb(skb);
880#endif
881 return rxb->nr_subframes;
882 }
883}
884
885/* All received frames are sent to this function. @skb contains the frame in
886 * IEEE 802.11 format, i.e., in the format it was sent over air.
887 * This function is called only as a tasklet (software IRQ). */
888int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
889 struct ieee80211_rx_stats *rx_stats)
890{
891 struct net_device *dev = ieee->dev;
892 struct ieee80211_hdr_4addr *hdr;
893
894 size_t hdrlen;
895 u16 fc, type, stype, sc;
896 struct net_device_stats *stats;
897 unsigned int frag;
898 u8 *payload;
899 u16 ethertype;
900 //added by amy for reorder
901 u8 TID = 0;
902 u16 SeqNum = 0;
903 PRX_TS_RECORD pTS = NULL;
904 bool unicast_packet = false;
905 //added by amy for reorder
906#ifdef NOT_YET
907 struct net_device *wds = NULL;
908 struct sk_buff *skb2 = NULL;
909 struct net_device *wds = NULL;
910 int frame_authorized = 0;
911 int from_assoc_ap = 0;
912 void *sta = NULL;
913#endif
914 u8 dst[ETH_ALEN];
915 u8 src[ETH_ALEN];
916 u8 bssid[ETH_ALEN];
917 struct ieee80211_crypt_data *crypt = NULL;
918 int keyidx = 0;
919
920 int i;
921 struct ieee80211_rxb* rxb = NULL;
922 // cheat the the hdr type
923 hdr = (struct ieee80211_hdr_4addr *)skb->data;
924 stats = &ieee->stats;
925
926 if (skb->len < 10) {
927 printk(KERN_INFO "%s: SKB length < 10\n",
928 dev->name);
929 goto rx_dropped;
930 }
931
932 fc = le16_to_cpu(hdr->frame_ctl);
933 type = WLAN_FC_GET_TYPE(fc);
934 stype = WLAN_FC_GET_STYPE(fc);
935 sc = le16_to_cpu(hdr->seq_ctl);
936
937 frag = WLAN_GET_SEQ_FRAG(sc);
938 hdrlen = ieee80211_get_hdrlen(fc);
939
940 if(HTCCheck(ieee, skb->data))
941 {
942 if(net_ratelimit())
943 printk("find HTCControl\n");
944 hdrlen += 4;
945 rx_stats->bContainHTC = 1;
946 }
947
948#ifdef NOT_YET
949#if WIRELESS_EXT > 15
950 /* Put this code here so that we avoid duplicating it in all
951 * Rx paths. - Jean II */
952#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
953 /* If spy monitoring on */
954 if (iface->spy_data.spy_number > 0) {
955 struct iw_quality wstats;
956 wstats.level = rx_stats->rssi;
957 wstats.noise = rx_stats->noise;
958 wstats.updated = 6; /* No qual value */
959 /* Update spy records */
960 wireless_spy_update(dev, hdr->addr2, &wstats);
961 }
962#endif /* IW_WIRELESS_SPY */
963#endif /* WIRELESS_EXT > 15 */
964 hostap_update_rx_stats(local->ap, hdr, rx_stats);
965#endif
966
967#if WIRELESS_EXT > 15
968 if (ieee->iw_mode == IW_MODE_MONITOR) {
969 ieee80211_monitor_rx(ieee, skb, rx_stats);
970 stats->rx_packets++;
971 stats->rx_bytes += skb->len;
972 return 1;
973 }
974#endif
975 if (ieee->host_decrypt) {
976 int idx = 0;
977 if (skb->len >= hdrlen + 3)
978 idx = skb->data[hdrlen + 3] >> 6;
979 crypt = ieee->crypt[idx];
980#ifdef NOT_YET
981 sta = NULL;
982
983 /* Use station specific key to override default keys if the
984 * receiver address is a unicast address ("individual RA"). If
985 * bcrx_sta_key parameter is set, station specific key is used
986 * even with broad/multicast targets (this is against IEEE
987 * 802.11, but makes it easier to use different keys with
988 * stations that do not support WEP key mapping). */
989
990 if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
991 (void) hostap_handle_sta_crypto(local, hdr, &crypt,
992 &sta);
993#endif
994
995 /* allow NULL decrypt to indicate an station specific override
996 * for default encryption */
997 if (crypt && (crypt->ops == NULL ||
998 crypt->ops->decrypt_mpdu == NULL))
999 crypt = NULL;
1000
1001 if (!crypt && (fc & IEEE80211_FCTL_WEP)) {
1002 /* This seems to be triggered by some (multicast?)
1003 * frames from other than current BSS, so just drop the
1004 * frames silently instead of filling system log with
1005 * these reports. */
1006 IEEE80211_DEBUG_DROP("Decryption failed (not set)"
1007 " (SA=%pM)\n",
1008 hdr->addr2);
1009 ieee->ieee_stats.rx_discards_undecryptable++;
1010 goto rx_dropped;
1011 }
1012 }
1013
1014 if (skb->len < IEEE80211_DATA_HDR3_LEN)
1015 goto rx_dropped;
1016
1017 // if QoS enabled, should check the sequence for each of the AC
1018 if( (ieee->pHTInfo->bCurRxReorderEnable == false) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)){
1019 if (is_duplicate_packet(ieee, hdr))
1020 goto rx_dropped;
1021
1022 }
1023 else
1024 {
1025 PRX_TS_RECORD pRxTS = NULL;
1026
1027 if(GetTs(
1028 ieee,
1029 (PTS_COMMON_INFO*) &pRxTS,
1030 hdr->addr2,
1031 (u8)Frame_QoSTID((u8*)(skb->data)),
1032 RX_DIR,
1033 true))
1034 {
1035
1036 if( (fc & (1<<11)) &&
1037 (frag == pRxTS->RxLastFragNum) &&
1038 (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum) )
1039 {
1040 goto rx_dropped;
1041 }
1042 else
1043 {
1044 pRxTS->RxLastFragNum = frag;
1045 pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc);
1046 }
1047 }
1048 else
1049 {
1050 IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s(): No TS!! Skip the check!!\n",__FUNCTION__);
1051 goto rx_dropped;
1052 }
1053 }
1054
1055 if (type == IEEE80211_FTYPE_MGMT) {
1056
1057 if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
1058 goto rx_dropped;
1059 else
1060 goto rx_exit;
1061 }
1062
1063 /* Data frame - extract src/dst addresses */
1064 switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
1065 case IEEE80211_FCTL_FROMDS:
1066 memcpy(dst, hdr->addr1, ETH_ALEN);
1067 memcpy(src, hdr->addr3, ETH_ALEN);
1068 memcpy(bssid, hdr->addr2, ETH_ALEN);
1069 break;
1070 case IEEE80211_FCTL_TODS:
1071 memcpy(dst, hdr->addr3, ETH_ALEN);
1072 memcpy(src, hdr->addr2, ETH_ALEN);
1073 memcpy(bssid, hdr->addr1, ETH_ALEN);
1074 break;
1075 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
1076 if (skb->len < IEEE80211_DATA_HDR4_LEN)
1077 goto rx_dropped;
1078 memcpy(dst, hdr->addr3, ETH_ALEN);
1079 memcpy(src, hdr->addr4, ETH_ALEN);
1080 memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
1081 break;
1082 case 0:
1083 memcpy(dst, hdr->addr1, ETH_ALEN);
1084 memcpy(src, hdr->addr2, ETH_ALEN);
1085 memcpy(bssid, hdr->addr3, ETH_ALEN);
1086 break;
1087 }
1088
1089#ifdef NOT_YET
1090 if (hostap_rx_frame_wds(ieee, hdr, fc, &wds))
1091 goto rx_dropped;
1092 if (wds) {
1093 skb->dev = dev = wds;
1094 stats = hostap_get_stats(dev);
1095 }
1096
1097 if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
1098 (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS &&
1099 ieee->stadev &&
1100 memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) {
1101 /* Frame from BSSID of the AP for which we are a client */
1102 skb->dev = dev = ieee->stadev;
1103 stats = hostap_get_stats(dev);
1104 from_assoc_ap = 1;
1105 }
1106#endif
1107
1108 dev->last_rx = jiffies;
1109
1110#ifdef NOT_YET
1111 if ((ieee->iw_mode == IW_MODE_MASTER ||
1112 ieee->iw_mode == IW_MODE_REPEAT) &&
1113 !from_assoc_ap) {
1114 switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats,
1115 wds != NULL)) {
1116 case AP_RX_CONTINUE_NOT_AUTHORIZED:
1117 frame_authorized = 0;
1118 break;
1119 case AP_RX_CONTINUE:
1120 frame_authorized = 1;
1121 break;
1122 case AP_RX_DROP:
1123 goto rx_dropped;
1124 case AP_RX_EXIT:
1125 goto rx_exit;
1126 }
1127 }
1128#endif
1129 /* Nullfunc frames may have PS-bit set, so they must be passed to
1130 * hostap_handle_sta_rx() before being dropped here. */
1131 if (stype != IEEE80211_STYPE_DATA &&
1132 stype != IEEE80211_STYPE_DATA_CFACK &&
1133 stype != IEEE80211_STYPE_DATA_CFPOLL &&
1134 stype != IEEE80211_STYPE_DATA_CFACKPOLL&&
1135 stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4
1136 ) {
1137 if (stype != IEEE80211_STYPE_NULLFUNC)
1138 IEEE80211_DEBUG_DROP(
1139 "RX: dropped data frame "
1140 "with no data (type=0x%02x, "
1141 "subtype=0x%02x, len=%d)\n",
1142 type, stype, skb->len);
1143 goto rx_dropped;
1144 }
1145 if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
1146 goto rx_dropped;
1147
1148#ifdef ENABLE_LPS
1149 if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->sta_sleep == 1)
1150 && (ieee->polling)) {
1151 if (WLAN_FC_MORE_DATA(fc)) {
1152 /* more data bit is set, let's request a new frame from the AP */
1153 ieee80211_sta_ps_send_pspoll_frame(ieee);
1154 } else {
1155 ieee->polling = false;
1156 }
1157 }
1158#endif
1159
1160 ieee->need_sw_enc = 0;
1161
1162 if((!rx_stats->Decrypted)){
1163 ieee->need_sw_enc = 1;
1164 }
1165
1166 /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
1167
1168 if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
1169 (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
1170 {
1171 printk("decrypt frame error\n");
1172 goto rx_dropped;
1173 }
1174
1175
1176 hdr = (struct ieee80211_hdr_4addr *) skb->data;
1177
1178 /* skb: hdr + (possibly fragmented) plaintext payload */
1179 // PR: FIXME: hostap has additional conditions in the "if" below:
1180 // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
1181 if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
1182 int flen;
1183 struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
1184 IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
1185
1186 if (!frag_skb) {
1187 IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
1188 "Rx cannot get skb from fragment "
1189 "cache (morefrag=%d seq=%u frag=%u)\n",
1190 (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
1191 WLAN_GET_SEQ_SEQ(sc), frag);
1192 goto rx_dropped;
1193 }
1194 flen = skb->len;
1195 if (frag != 0)
1196 flen -= hdrlen;
1197
1198 if (frag_skb->tail + flen > frag_skb->end) {
1199 printk(KERN_WARNING "%s: host decrypted and "
1200 "reassembled frame did not fit skb\n",
1201 dev->name);
1202 ieee80211_frag_cache_invalidate(ieee, hdr);
1203 goto rx_dropped;
1204 }
1205
1206 if (frag == 0) {
1207 /* copy first fragment (including full headers) into
1208 * beginning of the fragment cache skb */
1209 memcpy(skb_put(frag_skb, flen), skb->data, flen);
1210 } else {
1211 /* append frame payload to the end of the fragment
1212 * cache skb */
1213 memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
1214 flen);
1215 }
1216 dev_kfree_skb_any(skb);
1217 skb = NULL;
1218
1219 if (fc & IEEE80211_FCTL_MOREFRAGS) {
1220 /* more fragments expected - leave the skb in fragment
1221 * cache for now; it will be delivered to upper layers
1222 * after all fragments have been received */
1223 goto rx_exit;
1224 }
1225
1226 /* this was the last fragment and the frame will be
1227 * delivered, so remove skb from fragment cache */
1228 skb = frag_skb;
1229 hdr = (struct ieee80211_hdr_4addr *) skb->data;
1230 ieee80211_frag_cache_invalidate(ieee, hdr);
1231 }
1232
1233 /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
1234 * encrypted/authenticated */
1235 if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
1236 ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
1237 {
1238 printk("==>decrypt msdu error\n");
1239 goto rx_dropped;
1240 }
1241
1242 //added by amy for AP roaming
1243 ieee->LinkDetectInfo.NumRecvDataInPeriod++;
1244 ieee->LinkDetectInfo.NumRxOkInPeriod++;
1245
1246 hdr = (struct ieee80211_hdr_4addr *) skb->data;
1247 if((!is_multicast_ether_addr(hdr->addr1)) && (!is_broadcast_ether_addr(hdr->addr1)))
1248 unicast_packet = true;
1249
1250 if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
1251 if (/*ieee->ieee802_1x &&*/
1252 ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1253
1254#ifdef CONFIG_IEEE80211_DEBUG
1255 /* pass unencrypted EAPOL frames even if encryption is
1256 * configured */
1257 struct eapol *eap = (struct eapol *)(skb->data +
1258 24);
1259 IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1260 eap_get_type(eap->type));
1261#endif
1262 } else {
1263 IEEE80211_DEBUG_DROP(
1264 "encryption configured, but RX "
1265 "frame not encrypted (SA=%pM)\n",
1266 hdr->addr2);
1267 goto rx_dropped;
1268 }
1269 }
1270
1271#ifdef CONFIG_IEEE80211_DEBUG
1272 if (crypt && !(fc & IEEE80211_FCTL_WEP) &&
1273 ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1274 struct eapol *eap = (struct eapol *)(skb->data +
1275 24);
1276 IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1277 eap_get_type(eap->type));
1278 }
1279#endif
1280
1281 if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep &&
1282 !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1283 IEEE80211_DEBUG_DROP(
1284 "dropped unencrypted RX data "
1285 "frame from %pM"
1286 " (drop_unencrypted=1)\n",
1287 hdr->addr2);
1288 goto rx_dropped;
1289 }
1290//added by amy for reorder
1291 if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
1292 && !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1))
1293 {
1294 TID = Frame_QoSTID(skb->data);
1295 SeqNum = WLAN_GET_SEQ_SEQ(sc);
1296 GetTs(ieee,(PTS_COMMON_INFO*) &pTS,hdr->addr2,TID,RX_DIR,true);
1297 if(TID !=0 && TID !=3)
1298 {
1299 ieee->bis_any_nonbepkts = true;
1300 }
1301 }
1302
1303//added by amy for reorder
1304 /* skb: hdr + (possible reassembled) full plaintext payload */
1305 payload = skb->data + hdrlen;
1306
1307 rxb = kmalloc(sizeof(struct ieee80211_rxb), GFP_ATOMIC);
1308 if(rxb == NULL)
1309 {
1310 IEEE80211_DEBUG(IEEE80211_DL_ERR,"%s(): kmalloc rxb error\n",__FUNCTION__);
1311 goto rx_dropped;
1312 }
1313 /* to parse amsdu packets */
1314 /* qos data packets & reserved bit is 1 */
1315 if(parse_subframe(ieee, skb,rx_stats,rxb,src,dst) == 0) {
1316 /* only to free rxb, and not submit the packets to upper layer */
1317 for(i =0; i < rxb->nr_subframes; i++) {
1318 dev_kfree_skb(rxb->subframes[i]);
1319 }
1320 kfree(rxb);
1321 rxb = NULL;
1322 goto rx_dropped;
1323 }
1324
1325#ifdef ENABLE_LPS
1326 if(unicast_packet)
1327 {
1328 if (type == IEEE80211_FTYPE_DATA)
1329 {
1330
1331 if(ieee->bIsAggregateFrame)
1332 ieee->LinkDetectInfo.NumRxUnicastOkInPeriod+=rxb->nr_subframes;
1333 else
1334 ieee->LinkDetectInfo.NumRxUnicastOkInPeriod++;
1335
1336 // 2009.03.03 Leave DC mode immediately when detect high traffic
1337 if((ieee->state == IEEE80211_LINKED) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/)
1338 {
1339 if( ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
1340 (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
1341 {
1342 if(ieee->LeisurePSLeave)
1343 ieee->LeisurePSLeave(ieee);
1344 }
1345 }
1346 }
1347 }
1348#endif
1349
1350 ieee->last_rx_ps_time = jiffies;
1351//added by amy for reorder
1352 if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){
1353//added by amy for reorder
1354 for(i = 0; i<rxb->nr_subframes; i++) {
1355 struct sk_buff *sub_skb = rxb->subframes[i];
1356
1357 if (sub_skb) {
1358 /* convert hdr + possible LLC headers into Ethernet header */
1359 ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
1360 if (sub_skb->len >= 8 &&
1361 ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
1362 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
1363 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
1364 /* remove RFC1042 or Bridge-Tunnel encapsulation and
1365 * replace EtherType */
1366 skb_pull(sub_skb, SNAP_SIZE);
1367 memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
1368 memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
1369 } else {
1370 u16 len;
1371 /* Leave Ethernet header part of hdr and full payload */
1372 len = htons(sub_skb->len);
1373 memcpy(skb_push(sub_skb, 2), &len, 2);
1374 memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
1375 memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
1376 }
1377
1378 stats->rx_packets++;
1379 stats->rx_bytes += sub_skb->len;
1380 if(is_multicast_ether_addr(dst)) {
1381 stats->multicast++;
1382 }
1383
1384 /* Indicat the packets to upper layer */
1385 sub_skb->protocol = eth_type_trans(sub_skb, dev);
1386 memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
1387 sub_skb->dev = dev;
1388 sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
1389 netif_rx(sub_skb);
1390 }
1391 }
1392 kfree(rxb);
1393 rxb = NULL;
1394
1395 }
1396 else
1397 {
1398 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__FUNCTION__);
1399 RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum);
1400 }
1401#ifndef JOHN_NOCPY
1402 dev_kfree_skb(skb);
1403#endif
1404
1405 rx_exit:
1406#ifdef NOT_YET
1407 if (sta)
1408 hostap_handle_sta_release(sta);
1409#endif
1410 return 1;
1411
1412 rx_dropped:
1413 kfree(rxb);
1414 rxb = NULL;
1415 stats->rx_dropped++;
1416
1417 /* Returning 0 indicates to caller that we have not handled the SKB--
1418 * so it is still allocated and can be used again by underlying
1419 * hardware as a DMA target */
1420 return 0;
1421}
1422
1423#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
1424
1425static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
1426
1427/*
1428* Make the structure we read from the beacon packet to have
1429* the right values
1430*/
1431static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
1432 *info_element, int sub_type)
1433{
1434
1435 if (info_element->qui_subtype != sub_type)
1436 return -1;
1437 if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
1438 return -1;
1439 if (info_element->qui_type != QOS_OUI_TYPE)
1440 return -1;
1441 if (info_element->version != QOS_VERSION_1)
1442 return -1;
1443
1444 return 0;
1445}
1446
1447
1448/*
1449 * Parse a QoS parameter element
1450 */
1451static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
1452 *element_param, struct ieee80211_info_element
1453 *info_element)
1454{
1455 int ret = 0;
1456 u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
1457
1458 if ((info_element == NULL) || (element_param == NULL))
1459 return -1;
1460
1461 if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
1462 memcpy(element_param->info_element.qui, info_element->data,
1463 info_element->len);
1464 element_param->info_element.elementID = info_element->id;
1465 element_param->info_element.length = info_element->len;
1466 } else
1467 ret = -1;
1468 if (ret == 0)
1469 ret = ieee80211_verify_qos_info(&element_param->info_element,
1470 QOS_OUI_PARAM_SUB_TYPE);
1471 return ret;
1472}
1473
1474/*
1475 * Parse a QoS information element
1476 */
1477static int ieee80211_read_qos_info_element(struct
1478 ieee80211_qos_information_element
1479 *element_info, struct ieee80211_info_element
1480 *info_element)
1481{
1482 int ret = 0;
1483 u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
1484
1485 if (element_info == NULL)
1486 return -1;
1487 if (info_element == NULL)
1488 return -1;
1489
1490 if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
1491 memcpy(element_info->qui, info_element->data,
1492 info_element->len);
1493 element_info->elementID = info_element->id;
1494 element_info->length = info_element->len;
1495 } else
1496 ret = -1;
1497
1498 if (ret == 0)
1499 ret = ieee80211_verify_qos_info(element_info,
1500 QOS_OUI_INFO_SUB_TYPE);
1501 return ret;
1502}
1503
1504
1505/*
1506 * Write QoS parameters from the ac parameters.
1507 */
1508static int ieee80211_qos_convert_ac_to_parameters(struct
1509 ieee80211_qos_parameter_info
1510 *param_elm, struct
1511 ieee80211_qos_parameters
1512 *qos_param)
1513{
1514 int rc = 0;
1515 int i;
1516 struct ieee80211_qos_ac_parameter *ac_params;
1517 u8 aci;
1518
1519 for (i = 0; i < QOS_QUEUE_NUM; i++) {
1520 ac_params = &(param_elm->ac_params_record[i]);
1521
1522 aci = (ac_params->aci_aifsn & 0x60) >> 5;
1523
1524 if(aci >= QOS_QUEUE_NUM)
1525 continue;
1526 qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f;
1527
1528 /* WMM spec P.11: The minimum value for AIFSN shall be 2 */
1529 qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2:qos_param->aifs[aci];
1530
1531 qos_param->cw_min[aci] = ac_params->ecw_min_max & 0x0F;
1532
1533 qos_param->cw_max[aci] = (ac_params->ecw_min_max & 0xF0) >> 4;
1534
1535 qos_param->flag[aci] =
1536 (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
1537 qos_param->tx_op_limit[aci] = le16_to_cpu(ac_params->tx_op_limit);
1538 }
1539 return rc;
1540}
1541
1542/*
1543 * we have a generic data element which it may contain QoS information or
1544 * parameters element. check the information element length to decide
1545 * which type to read
1546 */
1547static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
1548 *info_element,
1549 struct ieee80211_network *network)
1550{
1551 int rc = 0;
1552 struct ieee80211_qos_parameters *qos_param = NULL;
1553 struct ieee80211_qos_information_element qos_info_element;
1554
1555 rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
1556
1557 if (rc == 0) {
1558 network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
1559 network->flags |= NETWORK_HAS_QOS_INFORMATION;
1560 } else {
1561 struct ieee80211_qos_parameter_info param_element;
1562
1563 rc = ieee80211_read_qos_param_element(&param_element,
1564 info_element);
1565 if (rc == 0) {
1566 qos_param = &(network->qos_data.parameters);
1567 ieee80211_qos_convert_ac_to_parameters(&param_element,
1568 qos_param);
1569 network->flags |= NETWORK_HAS_QOS_PARAMETERS;
1570 network->qos_data.param_count =
1571 param_element.info_element.ac_info & 0x0F;
1572 }
1573 }
1574
1575 if (rc == 0) {
1576 IEEE80211_DEBUG_QOS("QoS is supported\n");
1577 network->qos_data.supported = 1;
1578 }
1579 return rc;
1580}
1581
1582#ifdef CONFIG_IEEE80211_DEBUG
1583#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
1584
1585static const char *get_info_element_string(u16 id)
1586{
1587 switch (id) {
1588 MFIE_STRING(SSID);
1589 MFIE_STRING(RATES);
1590 MFIE_STRING(FH_SET);
1591 MFIE_STRING(DS_SET);
1592 MFIE_STRING(CF_SET);
1593 MFIE_STRING(TIM);
1594 MFIE_STRING(IBSS_SET);
1595 MFIE_STRING(COUNTRY);
1596 MFIE_STRING(HOP_PARAMS);
1597 MFIE_STRING(HOP_TABLE);
1598 MFIE_STRING(REQUEST);
1599 MFIE_STRING(CHALLENGE);
1600 MFIE_STRING(POWER_CONSTRAINT);
1601 MFIE_STRING(POWER_CAPABILITY);
1602 MFIE_STRING(TPC_REQUEST);
1603 MFIE_STRING(TPC_REPORT);
1604 MFIE_STRING(SUPP_CHANNELS);
1605 MFIE_STRING(CSA);
1606 MFIE_STRING(MEASURE_REQUEST);
1607 MFIE_STRING(MEASURE_REPORT);
1608 MFIE_STRING(QUIET);
1609 MFIE_STRING(IBSS_DFS);
1610 // MFIE_STRING(ERP_INFO);
1611 MFIE_STRING(RSN);
1612 MFIE_STRING(RATES_EX);
1613 MFIE_STRING(GENERIC);
1614 MFIE_STRING(QOS_PARAMETER);
1615 default:
1616 return "UNKNOWN";
1617 }
1618}
1619#endif
1620
1621#ifdef ENABLE_DOT11D
1622static inline void ieee80211_extract_country_ie(
1623 struct ieee80211_device *ieee,
1624 struct ieee80211_info_element *info_element,
1625 struct ieee80211_network *network,
1626 u8 * addr2
1627)
1628{
1629 if(IS_DOT11D_ENABLE(ieee))
1630 {
1631 if(info_element->len!= 0)
1632 {
1633 memcpy(network->CountryIeBuf, info_element->data, info_element->len);
1634 network->CountryIeLen = info_element->len;
1635
1636 if(!IS_COUNTRY_IE_VALID(ieee))
1637 {
1638 Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
1639 }
1640 }
1641
1642 //
1643 // 070305, rcnjko: I update country IE watch dog here because
1644 // some AP (e.g. Cisco 1242) don't include country IE in their
1645 // probe response frame.
1646 //
1647 if(IS_EQUAL_CIE_SRC(ieee, addr2) )
1648 {
1649 UPDATE_CIE_WATCHDOG(ieee);
1650 }
1651 }
1652
1653}
1654#endif
1655
1656int ieee80211_parse_info_param(struct ieee80211_device *ieee,
1657 struct ieee80211_info_element *info_element,
1658 u16 length,
1659 struct ieee80211_network *network,
1660 struct ieee80211_rx_stats *stats)
1661{
1662 u8 i;
1663 short offset;
1664 u16 tmp_htcap_len=0;
1665 u16 tmp_htinfo_len=0;
1666 u16 ht_realtek_agg_len=0;
1667 u8 ht_realtek_agg_buf[MAX_IE_LEN];
1668#ifdef CONFIG_IEEE80211_DEBUG
1669 char rates_str[64];
1670 char *p;
1671#endif
1672
1673 while (length >= sizeof(*info_element)) {
1674 if (sizeof(*info_element) + info_element->len > length) {
1675 IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
1676 "info_element->len + 2 > left : "
1677 "info_element->len+2=%zd left=%d, id=%d.\n",
1678 info_element->len +
1679 sizeof(*info_element),
1680 length, info_element->id);
1681 /* We stop processing but don't return an error here
1682 * because some misbehaviour APs break this rule. ie.
1683 * Orinoco AP1000. */
1684 break;
1685 }
1686
1687 switch (info_element->id) {
1688 case MFIE_TYPE_SSID:
1689 if (ieee80211_is_empty_essid(info_element->data,
1690 info_element->len)) {
1691 network->flags |= NETWORK_EMPTY_ESSID;
1692 break;
1693 }
1694
1695 network->ssid_len = min(info_element->len,
1696 (u8) IW_ESSID_MAX_SIZE);
1697 memcpy(network->ssid, info_element->data, network->ssid_len);
1698 if (network->ssid_len < IW_ESSID_MAX_SIZE)
1699 memset(network->ssid + network->ssid_len, 0,
1700 IW_ESSID_MAX_SIZE - network->ssid_len);
1701
1702 IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
1703 network->ssid, network->ssid_len);
1704 break;
1705
1706 case MFIE_TYPE_RATES:
1707#ifdef CONFIG_IEEE80211_DEBUG
1708 p = rates_str;
1709#endif
1710 network->rates_len = min(info_element->len,
1711 MAX_RATES_LENGTH);
1712 for (i = 0; i < network->rates_len; i++) {
1713 network->rates[i] = info_element->data[i];
1714#ifdef CONFIG_IEEE80211_DEBUG
1715 p += snprintf(p, sizeof(rates_str) -
1716 (p - rates_str), "%02X ",
1717 network->rates[i]);
1718#endif
1719 if (ieee80211_is_ofdm_rate
1720 (info_element->data[i])) {
1721 network->flags |= NETWORK_HAS_OFDM;
1722 if (info_element->data[i] &
1723 IEEE80211_BASIC_RATE_MASK)
1724 network->flags &=
1725 ~NETWORK_HAS_CCK;
1726 }
1727 }
1728
1729 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
1730 rates_str, network->rates_len);
1731 break;
1732
1733 case MFIE_TYPE_RATES_EX:
1734#ifdef CONFIG_IEEE80211_DEBUG
1735 p = rates_str;
1736#endif
1737 network->rates_ex_len = min(info_element->len,
1738 MAX_RATES_EX_LENGTH);
1739 for (i = 0; i < network->rates_ex_len; i++) {
1740 network->rates_ex[i] = info_element->data[i];
1741#ifdef CONFIG_IEEE80211_DEBUG
1742 p += snprintf(p, sizeof(rates_str) -
1743 (p - rates_str), "%02X ",
1744 network->rates[i]);
1745#endif
1746 if (ieee80211_is_ofdm_rate
1747 (info_element->data[i])) {
1748 network->flags |= NETWORK_HAS_OFDM;
1749 if (info_element->data[i] &
1750 IEEE80211_BASIC_RATE_MASK)
1751 network->flags &=
1752 ~NETWORK_HAS_CCK;
1753 }
1754 }
1755
1756 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
1757 rates_str, network->rates_ex_len);
1758 break;
1759
1760 case MFIE_TYPE_DS_SET:
1761 IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
1762 info_element->data[0]);
1763 network->channel = info_element->data[0];
1764 break;
1765
1766 case MFIE_TYPE_FH_SET:
1767 IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
1768 break;
1769
1770 case MFIE_TYPE_CF_SET:
1771 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
1772 break;
1773
1774 case MFIE_TYPE_TIM:
1775 if(info_element->len < 4)
1776 break;
1777
1778 network->tim.tim_count = info_element->data[0];
1779 network->tim.tim_period = info_element->data[1];
1780
1781 network->dtim_period = info_element->data[1];
1782 if(ieee->state != IEEE80211_LINKED)
1783 break;
1784 //we use jiffies for legacy Power save
1785 network->last_dtim_sta_time[0] = jiffies;
1786 network->last_dtim_sta_time[1] = stats->mac_time[1];
1787
1788 network->dtim_data = IEEE80211_DTIM_VALID;
1789
1790 if(info_element->data[0] != 0)
1791 break;
1792
1793 if(info_element->data[2] & 1)
1794 network->dtim_data |= IEEE80211_DTIM_MBCAST;
1795
1796 offset = (info_element->data[2] >> 1)*2;
1797
1798 if(ieee->assoc_id < 8*offset ||
1799 ieee->assoc_id > 8*(offset + info_element->len -3))
1800
1801 break;
1802
1803 offset = (ieee->assoc_id / 8) - offset;// + ((aid % 8)? 0 : 1) ;
1804
1805 if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8)))
1806 network->dtim_data |= IEEE80211_DTIM_UCAST;
1807
1808 break;
1809
1810 case MFIE_TYPE_ERP:
1811 network->erp_value = info_element->data[0];
1812 network->flags |= NETWORK_HAS_ERP_VALUE;
1813 IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1814 network->erp_value);
1815 break;
1816 case MFIE_TYPE_IBSS_SET:
1817 network->atim_window = info_element->data[0];
1818 IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
1819 network->atim_window);
1820 break;
1821
1822 case MFIE_TYPE_CHALLENGE:
1823 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
1824 break;
1825
1826 case MFIE_TYPE_GENERIC:
1827 IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
1828 info_element->len);
1829 if (!ieee80211_parse_qos_info_param_IE(info_element,
1830 network))
1831 break;
1832
1833 if (info_element->len >= 4 &&
1834 info_element->data[0] == 0x00 &&
1835 info_element->data[1] == 0x50 &&
1836 info_element->data[2] == 0xf2 &&
1837 info_element->data[3] == 0x01) {
1838 network->wpa_ie_len = min(info_element->len + 2,
1839 MAX_WPA_IE_LEN);
1840 memcpy(network->wpa_ie, info_element,
1841 network->wpa_ie_len);
1842 break;
1843 }
1844
1845#ifdef THOMAS_TURBO
1846 if (info_element->len == 7 &&
1847 info_element->data[0] == 0x00 &&
1848 info_element->data[1] == 0xe0 &&
1849 info_element->data[2] == 0x4c &&
1850 info_element->data[3] == 0x01 &&
1851 info_element->data[4] == 0x02) {
1852 network->Turbo_Enable = 1;
1853 }
1854#endif
1855
1856 //for HTcap and HTinfo parameters
1857 if(tmp_htcap_len == 0){
1858 if(info_element->len >= 4 &&
1859 info_element->data[0] == 0x00 &&
1860 info_element->data[1] == 0x90 &&
1861 info_element->data[2] == 0x4c &&
1862 info_element->data[3] == 0x033){
1863
1864 tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN);
1865 if(tmp_htcap_len != 0){
1866 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
1867 network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\
1868 sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len;
1869 memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen);
1870 }
1871 }
1872 if(tmp_htcap_len != 0)
1873 network->bssht.bdSupportHT = true;
1874 else
1875 network->bssht.bdSupportHT = false;
1876 }
1877
1878
1879 if(tmp_htinfo_len == 0){
1880 if(info_element->len >= 4 &&
1881 info_element->data[0] == 0x00 &&
1882 info_element->data[1] == 0x90 &&
1883 info_element->data[2] == 0x4c &&
1884 info_element->data[3] == 0x034){
1885
1886 tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN);
1887 if(tmp_htinfo_len != 0){
1888 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
1889 if(tmp_htinfo_len){
1890 network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\
1891 sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len;
1892 memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen);
1893 }
1894
1895 }
1896
1897 }
1898 }
1899
1900 if(ieee->aggregation){
1901 if(network->bssht.bdSupportHT){
1902 if(info_element->len >= 4 &&
1903 info_element->data[0] == 0x00 &&
1904 info_element->data[1] == 0xe0 &&
1905 info_element->data[2] == 0x4c &&
1906 info_element->data[3] == 0x02){
1907
1908 ht_realtek_agg_len = min(info_element->len,(u8)MAX_IE_LEN);
1909 memcpy(ht_realtek_agg_buf,info_element->data,info_element->len);
1910
1911 }
1912 if(ht_realtek_agg_len >= 5){
1913 network->bssht.bdRT2RTAggregation = true;
1914
1915 if((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02))
1916 network->bssht.bdRT2RTLongSlotTime = true;
1917 }
1918 }
1919
1920 }
1921
1922 if((info_element->len >= 3 &&
1923 info_element->data[0] == 0x00 &&
1924 info_element->data[1] == 0x05 &&
1925 info_element->data[2] == 0xb5) ||
1926 (info_element->len >= 3 &&
1927 info_element->data[0] == 0x00 &&
1928 info_element->data[1] == 0x0a &&
1929 info_element->data[2] == 0xf7) ||
1930 (info_element->len >= 3 &&
1931 info_element->data[0] == 0x00 &&
1932 info_element->data[1] == 0x10 &&
1933 info_element->data[2] == 0x18)){
1934
1935 network->broadcom_cap_exist = true;
1936
1937 }
1938
1939 if(info_element->len >= 3 &&
1940 info_element->data[0] == 0x00 &&
1941 info_element->data[1] == 0x0c &&
1942 info_element->data[2] == 0x43)
1943 {
1944 network->ralink_cap_exist = true;
1945 }
1946 else
1947 network->ralink_cap_exist = false;
1948 //added by amy for atheros AP
1949 if((info_element->len >= 3 &&
1950 info_element->data[0] == 0x00 &&
1951 info_element->data[1] == 0x03 &&
1952 info_element->data[2] == 0x7f) ||
1953 (info_element->len >= 3 &&
1954 info_element->data[0] == 0x00 &&
1955 info_element->data[1] == 0x13 &&
1956 info_element->data[2] == 0x74))
1957 {
1958 network->atheros_cap_exist = true;
1959 }
1960 else
1961 network->atheros_cap_exist = false;
1962
1963 if ((info_element->len >= 3 &&
1964 info_element->data[0] == 0x00 &&
1965 info_element->data[1] == 0x50 &&
1966 info_element->data[2] == 0x43) )
1967 {
1968 network->marvell_cap_exist = true;
1969 }
1970
1971
1972 if(info_element->len >= 3 &&
1973 info_element->data[0] == 0x00 &&
1974 info_element->data[1] == 0x40 &&
1975 info_element->data[2] == 0x96)
1976 {
1977 network->cisco_cap_exist = true;
1978 }
1979 else
1980 network->cisco_cap_exist = false;
1981 //added by amy for LEAP of cisco
1982 if(info_element->len > 4 &&
1983 info_element->data[0] == 0x00 &&
1984 info_element->data[1] == 0x40 &&
1985 info_element->data[2] == 0x96 &&
1986 info_element->data[3] == 0x01)
1987 {
1988 if(info_element->len == 6)
1989 {
1990 memcpy(network->CcxRmState, &info_element[4], 2);
1991 if(network->CcxRmState[0] != 0)
1992 {
1993 network->bCcxRmEnable = true;
1994 }
1995 else
1996 network->bCcxRmEnable = false;
1997 //
1998 // CCXv4 Table 59-1 MBSSID Masks.
1999 //
2000 network->MBssidMask = network->CcxRmState[1] & 0x07;
2001 if(network->MBssidMask != 0)
2002 {
2003 network->bMBssidValid = true;
2004 network->MBssidMask = 0xff << (network->MBssidMask);
2005 cpMacAddr(network->MBssid, network->bssid);
2006 network->MBssid[5] &= network->MBssidMask;
2007 }
2008 else
2009 {
2010 network->bMBssidValid = false;
2011 }
2012 }
2013 else
2014 {
2015 network->bCcxRmEnable = false;
2016 }
2017 }
2018 if(info_element->len > 4 &&
2019 info_element->data[0] == 0x00 &&
2020 info_element->data[1] == 0x40 &&
2021 info_element->data[2] == 0x96 &&
2022 info_element->data[3] == 0x03)
2023 {
2024 if(info_element->len == 5)
2025 {
2026 network->bWithCcxVerNum = true;
2027 network->BssCcxVerNumber = info_element->data[4];
2028 }
2029 else
2030 {
2031 network->bWithCcxVerNum = false;
2032 network->BssCcxVerNumber = 0;
2033 }
2034 }
2035 break;
2036
2037 case MFIE_TYPE_RSN:
2038 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
2039 info_element->len);
2040 network->rsn_ie_len = min(info_element->len + 2,
2041 MAX_WPA_IE_LEN);
2042 memcpy(network->rsn_ie, info_element,
2043 network->rsn_ie_len);
2044 break;
2045
2046 //HT related element.
2047 case MFIE_TYPE_HT_CAP:
2048 IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n",
2049 info_element->len);
2050 tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN);
2051 if(tmp_htcap_len != 0){
2052 network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
2053 network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\
2054 sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len;
2055 memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen);
2056
2057 //If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT()
2058 // windows driver will update WMM parameters each beacon received once connected
2059 // Linux driver is a bit different.
2060 network->bssht.bdSupportHT = true;
2061 }
2062 else
2063 network->bssht.bdSupportHT = false;
2064 break;
2065
2066
2067 case MFIE_TYPE_HT_INFO:
2068 IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n",
2069 info_element->len);
2070 tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN);
2071 if(tmp_htinfo_len){
2072 network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE;
2073 network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\
2074 sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len;
2075 memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen);
2076 }
2077 break;
2078
2079 case MFIE_TYPE_AIRONET:
2080 IEEE80211_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n",
2081 info_element->len);
2082 if(info_element->len >IE_CISCO_FLAG_POSITION)
2083 {
2084 network->bWithAironetIE = true;
2085
2086 // CCX 1 spec v1.13, A01.1 CKIP Negotiation (page23):
2087 // "A Cisco access point advertises support for CKIP in beacon and probe response packets,
2088 // by adding an Aironet element and setting one or both of the CKIP negotiation bits."
2089 if( (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_MIC) ||
2090 (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_PK) )
2091 {
2092 network->bCkipSupported = true;
2093 }
2094 else
2095 {
2096 network->bCkipSupported = false;
2097 }
2098 }
2099 else
2100 {
2101 network->bWithAironetIE = false;
2102 network->bCkipSupported = false;
2103 }
2104 break;
2105 case MFIE_TYPE_QOS_PARAMETER:
2106 printk(KERN_ERR
2107 "QoS Error need to parse QOS_PARAMETER IE\n");
2108 break;
2109
2110#ifdef ENABLE_DOT11D
2111 case MFIE_TYPE_COUNTRY:
2112 IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
2113 info_element->len);
2114 ieee80211_extract_country_ie(ieee, info_element, network, network->bssid);//addr2 is same as addr3 when from an AP
2115 break;
2116#endif
2117
2118 default:
2119 IEEE80211_DEBUG_MGMT
2120 ("Unsupported info element: %s (%d)\n",
2121 get_info_element_string(info_element->id),
2122 info_element->id);
2123 break;
2124 }
2125
2126 length -= sizeof(*info_element) + info_element->len;
2127 info_element =
2128 (struct ieee80211_info_element *)&info_element->
2129 data[info_element->len];
2130 }
2131
2132 if(!network->atheros_cap_exist && !network->broadcom_cap_exist &&
2133 !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation &&
2134 !network->marvell_cap_exist)
2135 {
2136 network->unknown_cap_exist = true;
2137 }
2138 else
2139 {
2140 network->unknown_cap_exist = false;
2141 }
2142 return 0;
2143}
2144
2145static inline u8 ieee80211_SignalStrengthTranslate(
2146 u8 CurrSS
2147 )
2148{
2149 u8 RetSS;
2150
2151 // Step 1. Scale mapping.
2152 if(CurrSS >= 71 && CurrSS <= 100)
2153 {
2154 RetSS = 90 + ((CurrSS - 70) / 3);
2155 }
2156 else if(CurrSS >= 41 && CurrSS <= 70)
2157 {
2158 RetSS = 78 + ((CurrSS - 40) / 3);
2159 }
2160 else if(CurrSS >= 31 && CurrSS <= 40)
2161 {
2162 RetSS = 66 + (CurrSS - 30);
2163 }
2164 else if(CurrSS >= 21 && CurrSS <= 30)
2165 {
2166 RetSS = 54 + (CurrSS - 20);
2167 }
2168 else if(CurrSS >= 5 && CurrSS <= 20)
2169 {
2170 RetSS = 42 + (((CurrSS - 5) * 2) / 3);
2171 }
2172 else if(CurrSS == 4)
2173 {
2174 RetSS = 36;
2175 }
2176 else if(CurrSS == 3)
2177 {
2178 RetSS = 27;
2179 }
2180 else if(CurrSS == 2)
2181 {
2182 RetSS = 18;
2183 }
2184 else if(CurrSS == 1)
2185 {
2186 RetSS = 9;
2187 }
2188 else
2189 {
2190 RetSS = CurrSS;
2191 }
2192
2193 return RetSS;
2194}
2195
2196long ieee80211_translate_todbm(u8 signal_strength_index )// 0-100 index.
2197{
2198 long signal_power; // in dBm.
2199
2200 // Translate to dBm (x=0.5y-95).
2201 signal_power = (long)((signal_strength_index + 1) >> 1);
2202 signal_power -= 95;
2203
2204 return signal_power;
2205}
2206
2207static inline int ieee80211_network_init(
2208 struct ieee80211_device *ieee,
2209 struct ieee80211_probe_response *beacon,
2210 struct ieee80211_network *network,
2211 struct ieee80211_rx_stats *stats)
2212{
2213 network->qos_data.active = 0;
2214 network->qos_data.supported = 0;
2215 network->qos_data.param_count = 0;
2216 network->qos_data.old_param_count = 0;
2217
2218 /* Pull out fixed field data */
2219 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
2220 network->capability = le16_to_cpu(beacon->capability);
2221 network->last_scanned = jiffies;
2222 network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
2223 network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
2224 network->beacon_interval = le32_to_cpu(beacon->beacon_interval);
2225 /* Where to pull this? beacon->listen_interval;*/
2226 network->listen_interval = 0x0A;
2227 network->rates_len = network->rates_ex_len = 0;
2228 network->last_associate = 0;
2229 network->ssid_len = 0;
2230 network->flags = 0;
2231 network->atim_window = 0;
2232 network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
2233 0x3 : 0x0;
2234 network->berp_info_valid = false;
2235 network->broadcom_cap_exist = false;
2236 network->ralink_cap_exist = false;
2237 network->atheros_cap_exist = false;
2238 network->marvell_cap_exist = false;
2239 network->cisco_cap_exist = false;
2240 network->unknown_cap_exist = false;
2241#ifdef THOMAS_TURBO
2242 network->Turbo_Enable = 0;
2243#endif
2244#ifdef ENABLE_DOT11D
2245 network->CountryIeLen = 0;
2246 memset(network->CountryIeBuf, 0, MAX_IE_LEN);
2247#endif
2248//Initialize HT parameters
2249 HTInitializeBssDesc(&network->bssht);
2250 if (stats->freq == IEEE80211_52GHZ_BAND) {
2251 /* for A band (No DS info) */
2252 network->channel = stats->received_channel;
2253 } else
2254 network->flags |= NETWORK_HAS_CCK;
2255
2256 network->wpa_ie_len = 0;
2257 network->rsn_ie_len = 0;
2258
2259 if (ieee80211_parse_info_param
2260 (ieee,beacon->info_element, stats->len - sizeof(*beacon), network, stats))
2261 return 1;
2262
2263 network->mode = 0;
2264 if (stats->freq == IEEE80211_52GHZ_BAND)
2265 network->mode = IEEE_A;
2266 else {
2267 if (network->flags & NETWORK_HAS_OFDM)
2268 network->mode |= IEEE_G;
2269 if (network->flags & NETWORK_HAS_CCK)
2270 network->mode |= IEEE_B;
2271 }
2272
2273 if (network->mode == 0) {
2274 IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
2275 "network.\n",
2276 escape_essid(network->ssid,
2277 network->ssid_len),
2278 network->bssid);
2279 return 1;
2280 }
2281
2282 if(network->bssht.bdSupportHT){
2283 if(network->mode == IEEE_A)
2284 network->mode = IEEE_N_5G;
2285 else if(network->mode & (IEEE_G | IEEE_B))
2286 network->mode = IEEE_N_24G;
2287 }
2288 if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
2289 network->flags |= NETWORK_EMPTY_ESSID;
2290
2291 stats->signal = 30 + (stats->SignalStrength * 70) / 100;
2292 stats->noise = ieee80211_translate_todbm((u8)(100-stats->signal)) -25;
2293
2294 memcpy(&network->stats, stats, sizeof(network->stats));
2295
2296 return 0;
2297}
2298
2299static inline int is_same_network(struct ieee80211_network *src,
2300 struct ieee80211_network *dst, struct ieee80211_device* ieee)
2301{
2302 /* A network is only a duplicate if the channel, BSSID, ESSID
2303 * and the capability field (in particular IBSS and BSS) all match.
2304 * We treat all <hidden> with the same BSSID and channel
2305 * as one network */
2306 return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&
2307 (src->channel == dst->channel) &&
2308 !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
2309 (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&
2310 ((src->capability & WLAN_CAPABILITY_IBSS) ==
2311 (dst->capability & WLAN_CAPABILITY_IBSS)) &&
2312 ((src->capability & WLAN_CAPABILITY_BSS) ==
2313 (dst->capability & WLAN_CAPABILITY_BSS)));
2314}
2315
2316static inline void update_network(struct ieee80211_network *dst,
2317 struct ieee80211_network *src)
2318{
2319 int qos_active;
2320 u8 old_param;
2321
2322 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
2323 dst->capability = src->capability;
2324 memcpy(dst->rates, src->rates, src->rates_len);
2325 dst->rates_len = src->rates_len;
2326 memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
2327 dst->rates_ex_len = src->rates_ex_len;
2328 if(src->ssid_len > 0)
2329 {
2330 memset(dst->ssid, 0, dst->ssid_len);
2331 dst->ssid_len = src->ssid_len;
2332 memcpy(dst->ssid, src->ssid, src->ssid_len);
2333 }
2334 dst->mode = src->mode;
2335 dst->flags = src->flags;
2336 dst->time_stamp[0] = src->time_stamp[0];
2337 dst->time_stamp[1] = src->time_stamp[1];
2338 if (src->flags & NETWORK_HAS_ERP_VALUE)
2339 {
2340 dst->erp_value = src->erp_value;
2341 dst->berp_info_valid = src->berp_info_valid = true;
2342 }
2343 dst->beacon_interval = src->beacon_interval;
2344 dst->listen_interval = src->listen_interval;
2345 dst->atim_window = src->atim_window;
2346 dst->dtim_period = src->dtim_period;
2347 dst->dtim_data = src->dtim_data;
2348 dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0];
2349 dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1];
2350 memcpy(&dst->tim, &src->tim, sizeof(struct ieee80211_tim_parameters));
2351
2352 dst->bssht.bdSupportHT = src->bssht.bdSupportHT;
2353 dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation;
2354 dst->bssht.bdHTCapLen= src->bssht.bdHTCapLen;
2355 memcpy(dst->bssht.bdHTCapBuf,src->bssht.bdHTCapBuf,src->bssht.bdHTCapLen);
2356 dst->bssht.bdHTInfoLen= src->bssht.bdHTInfoLen;
2357 memcpy(dst->bssht.bdHTInfoBuf,src->bssht.bdHTInfoBuf,src->bssht.bdHTInfoLen);
2358 dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer;
2359 dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime;
2360 dst->broadcom_cap_exist = src->broadcom_cap_exist;
2361 dst->ralink_cap_exist = src->ralink_cap_exist;
2362 dst->atheros_cap_exist = src->atheros_cap_exist;
2363 dst->marvell_cap_exist = src->marvell_cap_exist;
2364 dst->cisco_cap_exist = src->cisco_cap_exist;
2365 dst->unknown_cap_exist = src->unknown_cap_exist;
2366 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
2367 dst->wpa_ie_len = src->wpa_ie_len;
2368 memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
2369 dst->rsn_ie_len = src->rsn_ie_len;
2370
2371 dst->last_scanned = jiffies;
2372 /* qos related parameters */
2373 qos_active = dst->qos_data.active;
2374 old_param = dst->qos_data.param_count;
2375 if(dst->flags & NETWORK_HAS_QOS_MASK){
2376 //not update QOS paramter in beacon, as most AP will set all these parameter to 0.//WB
2377 }
2378 else {
2379 dst->qos_data.supported = src->qos_data.supported;
2380 dst->qos_data.param_count = src->qos_data.param_count;
2381 }
2382
2383 if(dst->qos_data.supported == 1) {
2384 dst->QoS_Enable = 1;
2385 if(dst->ssid_len)
2386 IEEE80211_DEBUG_QOS
2387 ("QoS the network %s is QoS supported\n",
2388 dst->ssid);
2389 else
2390 IEEE80211_DEBUG_QOS
2391 ("QoS the network is QoS supported\n");
2392 }
2393 dst->qos_data.active = qos_active;
2394 dst->qos_data.old_param_count = old_param;
2395
2396 /* dst->last_associate is not overwritten */
2397 dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame.
2398 if(src->wmm_param[0].ac_aci_acm_aifsn|| \
2399 src->wmm_param[1].ac_aci_acm_aifsn|| \
2400 src->wmm_param[2].ac_aci_acm_aifsn|| \
2401 src->wmm_param[3].ac_aci_acm_aifsn) {
2402 memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
2403 }
2404#ifdef THOMAS_TURBO
2405 dst->Turbo_Enable = src->Turbo_Enable;
2406#endif
2407
2408#ifdef ENABLE_DOT11D
2409 dst->CountryIeLen = src->CountryIeLen;
2410 memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
2411#endif
2412
2413 //added by amy for LEAP
2414 dst->bWithAironetIE = src->bWithAironetIE;
2415 dst->bCkipSupported = src->bCkipSupported;
2416 memcpy(dst->CcxRmState,src->CcxRmState,2);
2417 dst->bCcxRmEnable = src->bCcxRmEnable;
2418 dst->MBssidMask = src->MBssidMask;
2419 dst->bMBssidValid = src->bMBssidValid;
2420 memcpy(dst->MBssid,src->MBssid,6);
2421 dst->bWithCcxVerNum = src->bWithCcxVerNum;
2422 dst->BssCcxVerNumber = src->BssCcxVerNumber;
2423
2424}
2425
2426static inline int is_beacon(__le16 fc)
2427{
2428 return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
2429}
2430
2431static inline void ieee80211_process_probe_response(
2432 struct ieee80211_device *ieee,
2433 struct ieee80211_probe_response *beacon,
2434 struct ieee80211_rx_stats *stats)
2435{
2436 struct ieee80211_network network;
2437 struct ieee80211_network *target;
2438 struct ieee80211_network *oldest = NULL;
2439#ifdef CONFIG_IEEE80211_DEBUG
2440 struct ieee80211_info_element *info_element = &beacon->info_element[0];
2441#endif
2442 unsigned long flags;
2443 short renew;
2444
2445 memset(&network, 0, sizeof(struct ieee80211_network));
2446 IEEE80211_DEBUG_SCAN(
2447 "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
2448 escape_essid(info_element->data, info_element->len),
2449 beacon->header.addr3,
2450 (beacon->capability & (1<<0xf)) ? '1' : '0',
2451 (beacon->capability & (1<<0xe)) ? '1' : '0',
2452 (beacon->capability & (1<<0xd)) ? '1' : '0',
2453 (beacon->capability & (1<<0xc)) ? '1' : '0',
2454 (beacon->capability & (1<<0xb)) ? '1' : '0',
2455 (beacon->capability & (1<<0xa)) ? '1' : '0',
2456 (beacon->capability & (1<<0x9)) ? '1' : '0',
2457 (beacon->capability & (1<<0x8)) ? '1' : '0',
2458 (beacon->capability & (1<<0x7)) ? '1' : '0',
2459 (beacon->capability & (1<<0x6)) ? '1' : '0',
2460 (beacon->capability & (1<<0x5)) ? '1' : '0',
2461 (beacon->capability & (1<<0x4)) ? '1' : '0',
2462 (beacon->capability & (1<<0x3)) ? '1' : '0',
2463 (beacon->capability & (1<<0x2)) ? '1' : '0',
2464 (beacon->capability & (1<<0x1)) ? '1' : '0',
2465 (beacon->capability & (1<<0x0)) ? '1' : '0');
2466
2467 if (ieee80211_network_init(ieee, beacon, &network, stats)) {
2468 IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
2469 escape_essid(info_element->data,
2470 info_element->len),
2471 beacon->header.addr3,
2472 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
2473 IEEE80211_STYPE_PROBE_RESP ?
2474 "PROBE RESPONSE" : "BEACON");
2475 return;
2476 }
2477
2478#ifdef ENABLE_DOT11D
2479 // For Asus EeePc request,
2480 // (1) if wireless adapter receive get any 802.11d country code in AP beacon,
2481 // wireless adapter should follow the country code.
2482 // (2) If there is no any country code in beacon,
2483 // then wireless adapter should do active scan from ch1~11 and
2484 // passive scan from ch12~14
2485
2486 if( !IsLegalChannel(ieee, network.channel) )
2487 return;
2488 if(ieee->bGlobalDomain)
2489 {
2490 if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP)
2491 {
2492 // Case 1: Country code
2493 if(IS_COUNTRY_IE_VALID(ieee) )
2494 {
2495 if( !IsLegalChannel(ieee, network.channel) )
2496 {
2497 printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel);
2498 return;
2499 }
2500 }
2501 // Case 2: No any country code.
2502 else
2503 {
2504 // Filter over channel ch12~14
2505 if(network.channel > 11)
2506 {
2507 printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel);
2508 return;
2509 }
2510 }
2511 }
2512 else
2513 {
2514 // Case 1: Country code
2515 if(IS_COUNTRY_IE_VALID(ieee) )
2516 {
2517 if( !IsLegalChannel(ieee, network.channel) )
2518 {
2519 printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network.channel);
2520 return;
2521 }
2522 }
2523 // Case 2: No any country code.
2524 else
2525 {
2526 // Filter over channel ch12~14
2527 if(network.channel > 14)
2528 {
2529 printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel);
2530 return;
2531 }
2532 }
2533 }
2534 }
2535#endif
2536
2537 /* The network parsed correctly -- so now we scan our known networks
2538 * to see if we can find it in our list.
2539 *
2540 * NOTE: This search is definitely not optimized. Once its doing
2541 * the "right thing" we'll optimize it for efficiency if
2542 * necessary */
2543
2544 /* Search for this entry in the list and update it if it is
2545 * already there. */
2546
2547 spin_lock_irqsave(&ieee->lock, flags);
2548
2549 if(is_same_network(&ieee->current_network, &network, ieee)) {
2550 update_network(&ieee->current_network, &network);
2551 if((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G)
2552 && ieee->current_network.berp_info_valid){
2553 if(ieee->current_network.erp_value& ERP_UseProtection)
2554 ieee->current_network.buseprotection = true;
2555 else
2556 ieee->current_network.buseprotection = false;
2557 }
2558 if(is_beacon(beacon->header.frame_ctl))
2559 {
2560 if(ieee->state == IEEE80211_LINKED)
2561 ieee->LinkDetectInfo.NumRecvBcnInPeriod++;
2562 }
2563 else //hidden AP
2564 network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags);
2565 }
2566
2567 list_for_each_entry(target, &ieee->network_list, list) {
2568 if (is_same_network(target, &network, ieee))
2569 break;
2570 if ((oldest == NULL) ||
2571 (target->last_scanned < oldest->last_scanned))
2572 oldest = target;
2573 }
2574
2575 /* If we didn't find a match, then get a new network slot to initialize
2576 * with this beacon's information */
2577 if (&target->list == &ieee->network_list) {
2578 if (list_empty(&ieee->network_free_list)) {
2579 /* If there are no more slots, expire the oldest */
2580 list_del(&oldest->list);
2581 target = oldest;
2582 IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
2583 "network list.\n",
2584 escape_essid(target->ssid,
2585 target->ssid_len),
2586 target->bssid);
2587 } else {
2588 /* Otherwise just pull from the free list */
2589 target = list_entry(ieee->network_free_list.next,
2590 struct ieee80211_network, list);
2591 list_del(ieee->network_free_list.next);
2592 }
2593
2594
2595#ifdef CONFIG_IEEE80211_DEBUG
2596 IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
2597 escape_essid(network.ssid,
2598 network.ssid_len),
2599 network.bssid,
2600 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
2601 IEEE80211_STYPE_PROBE_RESP ?
2602 "PROBE RESPONSE" : "BEACON");
2603#endif
2604 memcpy(target, &network, sizeof(*target));
2605 list_add_tail(&target->list, &ieee->network_list);
2606 } else {
2607 IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
2608 escape_essid(target->ssid,
2609 target->ssid_len),
2610 target->bssid,
2611 WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
2612 IEEE80211_STYPE_PROBE_RESP ?
2613 "PROBE RESPONSE" : "BEACON");
2614
2615 /* we have an entry and we are going to update it. But this entry may
2616 * be already expired. In this case we do the same as we found a new
2617 * net and call the new_net handler
2618 */
2619 renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
2620 //YJ,add,080819,for hidden ap
2621 if(is_beacon(beacon->header.frame_ctl) == 0)
2622 network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
2623 if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
2624 && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
2625 ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK))))
2626 renew = 1;
2627 //YJ,add,080819,for hidden ap,end
2628
2629 update_network(target, &network);
2630 }
2631
2632 spin_unlock_irqrestore(&ieee->lock, flags);
2633 if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\
2634 (ieee->state == IEEE80211_LINKED)) {
2635 if(ieee->handle_beacon != NULL) {
2636 ieee->handle_beacon(ieee, beacon, &ieee->current_network);
2637 }
2638 }
2639}
2640
2641void ieee80211_rx_mgt(struct ieee80211_device *ieee,
2642 struct ieee80211_hdr_4addr *header,
2643 struct ieee80211_rx_stats *stats)
2644{
2645 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2646 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2647 ieee->last_rx_ps_time = jiffies;
2648
2649 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2650
2651 case IEEE80211_STYPE_BEACON:
2652 IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
2653 WLAN_FC_GET_STYPE(header->frame_ctl));
2654 IEEE80211_DEBUG_SCAN("Beacon\n");
2655 ieee80211_process_probe_response(
2656 ieee, (struct ieee80211_probe_response *)header, stats);
2657
2658 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2659 ieee->iw_mode == IW_MODE_INFRA &&
2660 ieee->state == IEEE80211_LINKED))
2661 {
2662 tasklet_schedule(&ieee->ps_task);
2663 }
2664
2665 break;
2666
2667 case IEEE80211_STYPE_PROBE_RESP:
2668 IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
2669 WLAN_FC_GET_STYPE(header->frame_ctl));
2670 IEEE80211_DEBUG_SCAN("Probe response\n");
2671 ieee80211_process_probe_response(
2672 ieee, (struct ieee80211_probe_response *)header, stats);
2673 break;
2674
2675 }
2676}
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
new file mode 100644
index 00000000000..60e9a09d933
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
@@ -0,0 +1,3278 @@
1/* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
3 *
4 * Mostly extracted from the rtl8180-sa2400 driver for the
5 * in-kernel generic ieee802.11 stack.
6 *
7 * Few lines might be stolen from other part of the ieee80211
8 * stack. Copyright who own it's copyright
9 *
10 * WPA code stolen from the ipw2200 driver.
11 * Copyright who own it's copyright.
12 *
13 * released under the GPL
14 */
15
16
17#include "ieee80211.h"
18
19#include <linux/random.h>
20#include <linux/delay.h>
21#include <linux/slab.h>
22#include <asm/uaccess.h>
23#ifdef ENABLE_DOT11D
24#include "dot11d.h"
25#endif
26
27u8 rsn_authen_cipher_suite[16][4] = {
28 {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved
29 {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default
30 {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default}
31 {0x00,0x0F,0xAC,0x03}, //WRAP-historical
32 {0x00,0x0F,0xAC,0x04}, //CCMP
33 {0x00,0x0F,0xAC,0x05}, //WEP-104
34};
35
36short ieee80211_is_54g(struct ieee80211_network net)
37{
38 return ((net.rates_ex_len > 0) || (net.rates_len > 4));
39}
40
41short ieee80211_is_shortslot(struct ieee80211_network net)
42{
43 return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
44}
45
46/* returns the total length needed for pleacing the RATE MFIE
47 * tag and the EXTENDED RATE MFIE tag if needed.
48 * It encludes two bytes per tag for the tag itself and its len
49 */
50unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
51{
52 unsigned int rate_len = 0;
53
54 if (ieee->modulation & IEEE80211_CCK_MODULATION)
55 rate_len = IEEE80211_CCK_RATE_LEN + 2;
56
57 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
58
59 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
60
61 return rate_len;
62}
63
64/* pleace the MFIE rate, tag to the memory (double) poined.
65 * Then it updates the pointer so that
66 * it points after the new MFIE tag added.
67 */
68void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
69{
70 u8 *tag = *tag_p;
71
72 if (ieee->modulation & IEEE80211_CCK_MODULATION){
73 *tag++ = MFIE_TYPE_RATES;
74 *tag++ = 4;
75 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
76 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
77 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
78 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
79 }
80
81 /* We may add an option for custom rates that specific HW might support */
82 *tag_p = tag;
83}
84
85void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
86{
87 u8 *tag = *tag_p;
88
89 if (ieee->modulation & IEEE80211_OFDM_MODULATION){
90
91 *tag++ = MFIE_TYPE_RATES_EX;
92 *tag++ = 8;
93 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
94 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
95 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
96 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
97 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
98 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
99 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
100 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
101
102 }
103
104 /* We may add an option for custom rates that specific HW might support */
105 *tag_p = tag;
106}
107
108
109void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
110 u8 *tag = *tag_p;
111
112 *tag++ = MFIE_TYPE_GENERIC; //0
113 *tag++ = 7;
114 *tag++ = 0x00;
115 *tag++ = 0x50;
116 *tag++ = 0xf2;
117 *tag++ = 0x02;//5
118 *tag++ = 0x00;
119 *tag++ = 0x01;
120#ifdef SUPPORT_USPD
121 if(ieee->current_network.wmm_info & 0x80) {
122 *tag++ = 0x0f|MAX_SP_Len;
123 } else {
124 *tag++ = MAX_SP_Len;
125 }
126#else
127 *tag++ = MAX_SP_Len;
128#endif
129 *tag_p = tag;
130}
131
132#ifdef THOMAS_TURBO
133void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
134 u8 *tag = *tag_p;
135
136 *tag++ = MFIE_TYPE_GENERIC; //0
137 *tag++ = 7;
138 *tag++ = 0x00;
139 *tag++ = 0xe0;
140 *tag++ = 0x4c;
141 *tag++ = 0x01;//5
142 *tag++ = 0x02;
143 *tag++ = 0x11;
144 *tag++ = 0x00;
145
146 *tag_p = tag;
147 printk(KERN_ALERT "This is enable turbo mode IE process\n");
148}
149#endif
150
151void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
152{
153 int nh;
154 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
155
156/*
157 * if the queue is full but we have newer frames then
158 * just overwrites the oldest.
159 *
160 * if (nh == ieee->mgmt_queue_tail)
161 * return -1;
162 */
163 ieee->mgmt_queue_head = nh;
164 ieee->mgmt_queue_ring[nh] = skb;
165}
166
167struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
168{
169 struct sk_buff *ret;
170
171 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
172 return NULL;
173
174 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
175
176 ieee->mgmt_queue_tail =
177 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
178
179 return ret;
180}
181
182void init_mgmt_queue(struct ieee80211_device *ieee)
183{
184 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
185}
186
187u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
188{
189 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
190 u8 rate;
191
192 // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
193 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
194 rate = 0x0c;
195 else
196 rate = ieee->basic_rate & 0x7f;
197
198 if(rate == 0){
199 // 2005.01.26, by rcnjko.
200 if(ieee->mode == IEEE_A||
201 ieee->mode== IEEE_N_5G||
202 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
203 rate = 0x0c;
204 else
205 rate = 0x02;
206 }
207
208 return rate;
209}
210
211
212void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
213
214inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
215{
216 unsigned long flags;
217 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
218 struct ieee80211_hdr_3addr *header=
219 (struct ieee80211_hdr_3addr *) skb->data;
220
221 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
222 spin_lock_irqsave(&ieee->lock, flags);
223
224 /* called with 2nd param 0, no mgmt lock required */
225 ieee80211_sta_wakeup(ieee,0);
226
227 tcb_desc->queue_index = MGNT_QUEUE;
228 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
229 tcb_desc->RATRIndex = 7;
230 tcb_desc->bTxDisableRateFallBack = 1;
231 tcb_desc->bTxUseDriverAssingedRate = 1;
232
233 if(single){
234 if(ieee->queue_stop){
235 enqueue_mgmt(ieee,skb);
236 }else{
237 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
238
239 if (ieee->seq_ctrl[0] == 0xFFF)
240 ieee->seq_ctrl[0] = 0;
241 else
242 ieee->seq_ctrl[0]++;
243
244 /* avoid watchdog triggers */
245 ieee->softmac_data_hard_start_xmit(skb, ieee, ieee->basic_rate);
246 }
247
248 spin_unlock_irqrestore(&ieee->lock, flags);
249 }else{
250 spin_unlock_irqrestore(&ieee->lock, flags);
251 spin_lock(&ieee->mgmt_tx_lock);
252
253 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
254
255 if (ieee->seq_ctrl[0] == 0xFFF)
256 ieee->seq_ctrl[0] = 0;
257 else
258 ieee->seq_ctrl[0]++;
259
260 /* check wether the managed packet queued greater than 5 */
261 if(!ieee->check_nic_enough_desc(ieee, tcb_desc->queue_index)||
262 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||
263 (ieee->queue_stop) ) {
264 /* insert the skb packet to the management queue */
265 /* as for the completion function, it does not need
266 * to check it any more.
267 * */
268 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
269 } else {
270 ieee->softmac_hard_start_xmit(skb, ieee);
271 }
272 spin_unlock(&ieee->mgmt_tx_lock);
273 }
274}
275
276inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
277{
278
279 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
280 struct ieee80211_hdr_3addr *header =
281 (struct ieee80211_hdr_3addr *) skb->data;
282 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
283
284 tcb_desc->queue_index = MGNT_QUEUE;
285 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
286 tcb_desc->RATRIndex = 7;
287 tcb_desc->bTxDisableRateFallBack = 1;
288 tcb_desc->bTxUseDriverAssingedRate = 1;
289 if(single){
290
291 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
292
293 if (ieee->seq_ctrl[0] == 0xFFF)
294 ieee->seq_ctrl[0] = 0;
295 else
296 ieee->seq_ctrl[0]++;
297
298 /* avoid watchdog triggers */
299 ieee->softmac_data_hard_start_xmit(skb, ieee, ieee->basic_rate);
300
301 }else{
302
303 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
304
305 if (ieee->seq_ctrl[0] == 0xFFF)
306 ieee->seq_ctrl[0] = 0;
307 else
308 ieee->seq_ctrl[0]++;
309
310 ieee->softmac_hard_start_xmit(skb, ieee);
311
312 }
313}
314
315inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
316{
317 unsigned int len,rate_len;
318 u8 *tag;
319 struct sk_buff *skb;
320 struct ieee80211_probe_request *req;
321
322 len = ieee->current_network.ssid_len;
323
324 rate_len = ieee80211_MFIE_rate_len(ieee);
325
326 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
327 2 + len + rate_len + ieee->tx_headroom);
328 if (!skb)
329 return NULL;
330
331 skb_reserve(skb, ieee->tx_headroom);
332
333 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
334 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
335 req->header.duration_id = 0; //FIXME: is this OK ?
336
337 memset(req->header.addr1, 0xff, ETH_ALEN);
338 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
339 memset(req->header.addr3, 0xff, ETH_ALEN);
340
341 tag = (u8 *) skb_put(skb,len+2+rate_len);
342
343 *tag++ = MFIE_TYPE_SSID;
344 *tag++ = len;
345 memcpy(tag, ieee->current_network.ssid, len);
346 tag += len;
347
348 ieee80211_MFIE_Brate(ieee,&tag);
349 ieee80211_MFIE_Grate(ieee,&tag);
350 return skb;
351}
352
353struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
354void ieee80211_send_beacon(struct ieee80211_device *ieee)
355{
356 struct sk_buff *skb;
357 if(!ieee->ieee_up)
358 return;
359
360 skb = ieee80211_get_beacon_(ieee);
361
362 if (skb){
363 softmac_mgmt_xmit(skb, ieee);
364 ieee->softmac_stats.tx_beacons++;
365 }
366
367 if(ieee->beacon_txing && ieee->ieee_up){
368 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
369 }
370}
371
372
373void ieee80211_send_beacon_cb(unsigned long _ieee)
374{
375 struct ieee80211_device *ieee =
376 (struct ieee80211_device *) _ieee;
377 unsigned long flags;
378
379 spin_lock_irqsave(&ieee->beacon_lock, flags);
380 ieee80211_send_beacon(ieee);
381 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
382}
383
384
385void ieee80211_send_probe(struct ieee80211_device *ieee)
386{
387 struct sk_buff *skb;
388
389 skb = ieee80211_probe_req(ieee);
390 if (skb){
391 softmac_mgmt_xmit(skb, ieee);
392 ieee->softmac_stats.tx_probe_rq++;
393 }
394}
395
396void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
397{
398 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
399 ieee80211_send_probe(ieee);
400 ieee80211_send_probe(ieee);
401 }
402}
403
404/* this performs syncro scan blocking the caller until all channels
405 * in the allowed channel map has been checked.
406 */
407void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
408{
409 short ch = 0;
410#ifdef ENABLE_DOT11D
411 u8 channel_map[MAX_CHANNEL_NUMBER+1];
412 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
413#endif
414 down(&ieee->scan_sem);
415
416 while(1)
417 {
418
419 do{
420 ch++;
421 if (ch > MAX_CHANNEL_NUMBER)
422 goto out; /* scan completed */
423#ifdef ENABLE_DOT11D
424 }while(!channel_map[ch]);
425#else
426 }while(!ieee->channel_map[ch]);
427#endif
428
429 /* this function can be called in two situations
430 * 1- We have switched to ad-hoc mode and we are
431 * performing a complete syncro scan before conclude
432 * there are no interesting cell and to create a
433 * new one. In this case the link state is
434 * IEEE80211_NOLINK until we found an interesting cell.
435 * If so the ieee8021_new_net, called by the RX path
436 * will set the state to IEEE80211_LINKED, so we stop
437 * scanning
438 * 2- We are linked and the root uses run iwlist scan.
439 * So we switch to IEEE80211_LINKED_SCANNING to remember
440 * that we are still logically linked (not interested in
441 * new network events, despite for updating the net list,
442 * but we are temporarly 'unlinked' as the driver shall
443 * not filter RX frames and the channel is changing.
444 * So the only situation in witch are interested is to check
445 * if the state become LINKED because of the #1 situation
446 */
447
448 if (ieee->state == IEEE80211_LINKED)
449 goto out;
450 ieee->set_chan(ieee, ch);
451#ifdef ENABLE_DOT11D
452 if(channel_map[ch] == 1)
453#endif
454 ieee80211_send_probe_requests(ieee);
455
456 /* this prevent excessive time wait when we
457 * need to wait for a syncro scan to end..
458 */
459 if(ieee->state < IEEE80211_LINKED)
460 ;
461 else
462 if (ieee->sync_scan_hurryup)
463 goto out;
464
465
466 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
467
468 }
469out:
470 if(ieee->state < IEEE80211_LINKED){
471 ieee->actscanning = false;
472 up(&ieee->scan_sem);
473 }
474 else{
475 ieee->sync_scan_hurryup = 0;
476#ifdef ENABLE_DOT11D
477 if(IS_DOT11D_ENABLE(ieee))
478 DOT11D_ScanComplete(ieee);
479#endif
480 up(&ieee->scan_sem);
481}
482}
483
484
485void ieee80211_softmac_scan_wq(struct work_struct *work)
486{
487 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
488 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
489 static short watchdog = 0;
490 u8 last_channel = ieee->current_network.channel;
491#ifdef ENABLE_DOT11D
492 u8 channel_map[MAX_CHANNEL_NUMBER+1];
493 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
494#endif
495 if(!ieee->ieee_up)
496 return;
497 down(&ieee->scan_sem);
498 do{
499 ieee->current_network.channel =
500 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
501 if (watchdog++ > MAX_CHANNEL_NUMBER) {
502 /* if current channel is not in channel map, set to default channel. */
503#ifdef ENABLE_DOT11D
504 if (!channel_map[ieee->current_network.channel]) {
505#else
506 if (!ieee->channel_map[ieee->current_network.channel]) {
507#endif
508 ieee->current_network.channel = 6;
509 goto out; /* no good chans */
510 }
511 }
512#ifdef ENABLE_DOT11D
513 }while(!channel_map[ieee->current_network.channel]);
514#else
515 }while(!ieee->channel_map[ieee->current_network.channel]);
516#endif
517 if (ieee->scanning == 0 )
518 goto out;
519 ieee->set_chan(ieee, ieee->current_network.channel);
520#ifdef ENABLE_DOT11D
521 if(channel_map[ieee->current_network.channel] == 1)
522#endif
523 ieee80211_send_probe_requests(ieee);
524
525
526 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
527
528 up(&ieee->scan_sem);
529 return;
530out:
531#ifdef ENABLE_DOT11D
532 if(IS_DOT11D_ENABLE(ieee))
533 DOT11D_ScanComplete(ieee);
534#endif
535 ieee->current_network.channel = last_channel;
536 ieee->actscanning = false;
537 watchdog = 0;
538 ieee->scanning = 0;
539 up(&ieee->scan_sem);
540}
541
542void ieee80211_beacons_start(struct ieee80211_device *ieee)
543{
544 unsigned long flags;
545 spin_lock_irqsave(&ieee->beacon_lock,flags);
546
547 ieee->beacon_txing = 1;
548 ieee80211_send_beacon(ieee);
549
550 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
551}
552
553void ieee80211_beacons_stop(struct ieee80211_device *ieee)
554{
555 unsigned long flags;
556
557 spin_lock_irqsave(&ieee->beacon_lock,flags);
558
559 ieee->beacon_txing = 0;
560 del_timer_sync(&ieee->beacon_timer);
561
562 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
563
564}
565
566
567void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
568{
569 if(ieee->stop_send_beacons)
570 ieee->stop_send_beacons(ieee);
571 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
572 ieee80211_beacons_stop(ieee);
573}
574
575
576void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
577{
578 if(ieee->start_send_beacons)
579 ieee->start_send_beacons(ieee);
580 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
581 ieee80211_beacons_start(ieee);
582}
583
584
585void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
586{
587 down(&ieee->scan_sem);
588
589 if (ieee->scanning == 1){
590 ieee->scanning = 0;
591
592 cancel_delayed_work(&ieee->softmac_scan_wq);
593 }
594
595 up(&ieee->scan_sem);
596}
597
598void ieee80211_stop_scan(struct ieee80211_device *ieee)
599{
600 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
601 ieee80211_softmac_stop_scan(ieee);
602 else
603 ieee->stop_scan(ieee);
604}
605
606/* called with ieee->lock held */
607void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
608{
609#ifdef ENABLE_IPS
610 if(ieee->ieee80211_ips_leave_wq != NULL)
611 ieee->ieee80211_ips_leave_wq(ieee);
612#endif
613
614#ifdef ENABLE_DOT11D
615 if(IS_DOT11D_ENABLE(ieee) )
616 {
617 if(IS_COUNTRY_IE_VALID(ieee))
618 {
619 RESET_CIE_WATCHDOG(ieee);
620 }
621 }
622#endif
623 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
624 if (ieee->scanning == 0){
625 ieee->scanning = 1;
626 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
627 }
628 }else
629 ieee->start_scan(ieee);
630
631}
632
633/* called with wx_sem held */
634void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
635{
636#ifdef ENABLE_DOT11D
637 if(IS_DOT11D_ENABLE(ieee) )
638 {
639 if(IS_COUNTRY_IE_VALID(ieee))
640 {
641 RESET_CIE_WATCHDOG(ieee);
642 }
643 }
644#endif
645 ieee->sync_scan_hurryup = 0;
646 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
647 ieee80211_softmac_scan_syncro(ieee);
648 else
649 ieee->scan_syncro(ieee);
650
651}
652
653inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
654 struct ieee80211_device *ieee, int challengelen)
655{
656 struct sk_buff *skb;
657 struct ieee80211_authentication *auth;
658 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
659
660
661 skb = dev_alloc_skb(len);
662 if (!skb) return NULL;
663
664 skb_reserve(skb, ieee->tx_headroom);
665 auth = (struct ieee80211_authentication *)
666 skb_put(skb, sizeof(struct ieee80211_authentication));
667
668 auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
669 if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
670
671 auth->header.duration_id = 0x013a; //FIXME
672
673 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
674 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
675 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
676
677 if(ieee->auth_mode == 0)
678 auth->algorithm = WLAN_AUTH_OPEN;
679 else if(ieee->auth_mode == 1)
680 auth->algorithm = WLAN_AUTH_SHARED_KEY;
681 else if(ieee->auth_mode == 2)
682 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
683 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
684 auth->transaction = cpu_to_le16(ieee->associate_seq);
685 ieee->associate_seq++;
686
687 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
688
689 return skb;
690
691}
692
693
694static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
695{
696 u8 *tag;
697 int beacon_size;
698 struct ieee80211_probe_response *beacon_buf;
699 struct sk_buff *skb = NULL;
700 int encrypt;
701 int atim_len,erp_len;
702 struct ieee80211_crypt_data* crypt;
703
704 char *ssid = ieee->current_network.ssid;
705 int ssid_len = ieee->current_network.ssid_len;
706 int rate_len = ieee->current_network.rates_len+2;
707 int rate_ex_len = ieee->current_network.rates_ex_len;
708 int wpa_ie_len = ieee->wpa_ie_len;
709 u8 erpinfo_content = 0;
710
711 u8* tmp_ht_cap_buf;
712 u8 tmp_ht_cap_len=0;
713 u8* tmp_ht_info_buf;
714 u8 tmp_ht_info_len=0;
715 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
716 u8* tmp_generic_ie_buf=NULL;
717 u8 tmp_generic_ie_len=0;
718
719 if(rate_ex_len > 0) rate_ex_len+=2;
720
721 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
722 atim_len = 4;
723 else
724 atim_len = 0;
725
726 if(ieee80211_is_54g(ieee->current_network))
727 erp_len = 3;
728 else
729 erp_len = 0;
730
731 crypt = ieee->crypt[ieee->tx_keyidx];
732
733
734 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
735 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
736 //HT ralated element
737
738 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
739 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
740 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
741 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
742 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
743 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
744
745
746 if(pHTInfo->bRegRT2RTAggregation)
747 {
748 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
749 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
750 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
751 }
752
753 beacon_size = sizeof(struct ieee80211_probe_response)+2+
754 ssid_len
755 +3 //channel
756 +rate_len
757 +rate_ex_len
758 +atim_len
759 +erp_len
760 +wpa_ie_len
761 +ieee->tx_headroom;
762 skb = dev_alloc_skb(beacon_size);
763 if (!skb)
764 return NULL;
765 skb_reserve(skb, ieee->tx_headroom);
766 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
767 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
768 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
769 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
770
771 beacon_buf->header.duration_id = 0; //FIXME
772 beacon_buf->beacon_interval =
773 cpu_to_le16(ieee->current_network.beacon_interval);
774 beacon_buf->capability =
775 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
776 beacon_buf->capability |=
777 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
778
779 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
780 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
781
782 crypt = ieee->crypt[ieee->tx_keyidx];
783 if (encrypt)
784 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
785
786
787 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
788 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
789 beacon_buf->info_element[0].len = ssid_len;
790
791 tag = (u8*) beacon_buf->info_element[0].data;
792
793 memcpy(tag, ssid, ssid_len);
794
795 tag += ssid_len;
796
797 *(tag++) = MFIE_TYPE_RATES;
798 *(tag++) = rate_len-2;
799 memcpy(tag,ieee->current_network.rates,rate_len-2);
800 tag+=rate_len-2;
801
802 *(tag++) = MFIE_TYPE_DS_SET;
803 *(tag++) = 1;
804 *(tag++) = ieee->current_network.channel;
805
806 if(atim_len){
807 u16 val16;
808 *(tag++) = MFIE_TYPE_IBSS_SET;
809 *(tag++) = 2;
810 val16 = cpu_to_le16(ieee->current_network.atim_window);
811 memcpy((u8 *)tag, (u8 *)&val16, 2);
812 tag+=2;
813 }
814
815 if(erp_len){
816 *(tag++) = MFIE_TYPE_ERP;
817 *(tag++) = 1;
818 *(tag++) = erpinfo_content;
819 }
820 if(rate_ex_len){
821 *(tag++) = MFIE_TYPE_RATES_EX;
822 *(tag++) = rate_ex_len-2;
823 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
824 tag+=rate_ex_len-2;
825 }
826
827 if (wpa_ie_len)
828 {
829 if (ieee->iw_mode == IW_MODE_ADHOC)
830 {//as Windows will set pairwise key same as the group key which is not allowed in Linux, so set this for IOT issue. WB 2008.07.07
831 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
832 }
833 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
834 tag += wpa_ie_len;
835 }
836
837 return skb;
838}
839
840
841struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
842{
843 struct sk_buff *skb;
844 u8* tag;
845
846 struct ieee80211_crypt_data* crypt;
847 struct ieee80211_assoc_response_frame *assoc;
848 short encrypt;
849
850 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
851 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
852
853 skb = dev_alloc_skb(len);
854
855 if (!skb)
856 return NULL;
857
858 skb_reserve(skb, ieee->tx_headroom);
859
860 assoc = (struct ieee80211_assoc_response_frame *)
861 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
862
863 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
864 memcpy(assoc->header.addr1, dest,ETH_ALEN);
865 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
866 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
867 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
868 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
869
870
871 if(ieee->short_slot)
872 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
873
874 if (ieee->host_encrypt)
875 crypt = ieee->crypt[ieee->tx_keyidx];
876 else crypt = NULL;
877
878 encrypt = ( crypt && crypt->ops);
879
880 if (encrypt)
881 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
882
883 assoc->status = 0;
884 assoc->aid = cpu_to_le16(ieee->assoc_id);
885 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
886 else ieee->assoc_id++;
887
888 tag = (u8*) skb_put(skb, rate_len);
889
890 ieee80211_MFIE_Brate(ieee, &tag);
891 ieee80211_MFIE_Grate(ieee, &tag);
892
893 return skb;
894}
895
896struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
897{
898 struct sk_buff *skb;
899 struct ieee80211_authentication *auth;
900 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
901
902 skb = dev_alloc_skb(len);
903
904 if (!skb)
905 return NULL;
906
907 skb->len = sizeof(struct ieee80211_authentication);
908
909 auth = (struct ieee80211_authentication *)skb->data;
910
911 auth->status = cpu_to_le16(status);
912 auth->transaction = cpu_to_le16(2);
913 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
914
915 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
916 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
917 memcpy(auth->header.addr1, dest, ETH_ALEN);
918 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
919 return skb;
920
921
922}
923
924struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
925{
926 struct sk_buff *skb;
927 struct ieee80211_hdr_3addr* hdr;
928
929 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
930
931 if (!skb)
932 return NULL;
933
934 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
935
936 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
937 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
938 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
939
940 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
941 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
942 (pwr ? IEEE80211_FCTL_PM:0));
943
944 return skb;
945
946
947}
948
949struct sk_buff* ieee80211_pspoll_func(struct ieee80211_device *ieee)
950{
951 struct sk_buff *skb;
952 struct ieee80211_pspoll_hdr* hdr;
953
954#ifdef USB_USE_ALIGNMENT
955 u32 Tmpaddr=0;
956 int alignment=0;
957 skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
958#else
959 skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr)+ieee->tx_headroom);
960#endif
961 if (!skb)
962 return NULL;
963
964#ifdef USB_USE_ALIGNMENT
965 Tmpaddr = (u32)skb->data;
966 alignment = Tmpaddr & 0x1ff;
967 skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
968#endif
969 skb_reserve(skb, ieee->tx_headroom);
970
971 hdr = (struct ieee80211_pspoll_hdr*)skb_put(skb,sizeof(struct ieee80211_pspoll_hdr));
972
973 memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN);
974 memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN);
975
976 hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000);
977 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_CTL |IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM);
978
979 return skb;
980
981}
982
983
984void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
985{
986 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
987
988 if (buf)
989 softmac_mgmt_xmit(buf, ieee);
990}
991
992
993void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
994{
995 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
996
997 if (buf)
998 softmac_mgmt_xmit(buf, ieee);
999}
1000
1001
1002void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
1003{
1004
1005
1006 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
1007 if (buf)
1008 softmac_mgmt_xmit(buf, ieee);
1009}
1010
1011
1012inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1013{
1014 struct sk_buff *skb;
1015 struct ieee80211_assoc_request_frame *hdr;
1016 u8 *tag;
1017 u8* ht_cap_buf = NULL;
1018 u8 ht_cap_len=0;
1019 u8* realtek_ie_buf=NULL;
1020 u8 realtek_ie_len=0;
1021 int wpa_ie_len= ieee->wpa_ie_len;
1022 unsigned int ckip_ie_len=0;
1023 unsigned int ccxrm_ie_len=0;
1024 unsigned int cxvernum_ie_len=0;
1025 struct ieee80211_crypt_data* crypt;
1026 int encrypt;
1027
1028 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1029 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1030#ifdef THOMAS_TURBO
1031 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1032#endif
1033
1034 int len = 0;
1035
1036 crypt = ieee->crypt[ieee->tx_keyidx];
1037 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1038
1039 //Include High Throuput capability && Realtek proprietary
1040 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1041 {
1042 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1043 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1044 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1045 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1046 {
1047 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1048 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1049 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1050
1051 }
1052 }
1053 if(ieee->qos_support){
1054 wmm_info_len = beacon->qos_data.supported?9:0;
1055 }
1056
1057
1058 if(beacon->bCkipSupported)
1059 {
1060 ckip_ie_len = 30+2;
1061 }
1062 if(beacon->bCcxRmEnable)
1063 {
1064 ccxrm_ie_len = 6+2;
1065 }
1066 if( beacon->BssCcxVerNumber >= 2 )
1067 {
1068 cxvernum_ie_len = 5+2;
1069 }
1070#ifdef THOMAS_TURBO
1071 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1072 + beacon->ssid_len//essid tagged val
1073 + rate_len//rates tagged val
1074 + wpa_ie_len
1075 + wmm_info_len
1076 + turbo_info_len
1077 + ht_cap_len
1078 + realtek_ie_len
1079 + ckip_ie_len
1080 + ccxrm_ie_len
1081 + cxvernum_ie_len
1082 + ieee->tx_headroom;
1083#else
1084 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1085 + beacon->ssid_len//essid tagged val
1086 + rate_len//rates tagged val
1087 + wpa_ie_len
1088 + wmm_info_len
1089 + ht_cap_len
1090 + realtek_ie_len
1091 + ckip_ie_len
1092 + ccxrm_ie_len
1093 + cxvernum_ie_len
1094 + ieee->tx_headroom;
1095#endif
1096
1097 skb = dev_alloc_skb(len);
1098
1099 if (!skb)
1100 return NULL;
1101
1102 skb_reserve(skb, ieee->tx_headroom);
1103
1104 hdr = (struct ieee80211_assoc_request_frame *)
1105 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1106
1107
1108 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1109 hdr->header.duration_id= 37; //FIXME
1110 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1111 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1112 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1113
1114 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1115
1116 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1117 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1118 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1119
1120 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1121 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1122
1123 if(ieee->short_slot)
1124 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1125 if (wmm_info_len) //QOS
1126 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1127
1128 hdr->listen_interval = 0xa; //FIXME
1129
1130 hdr->info_element[0].id = MFIE_TYPE_SSID;
1131
1132 hdr->info_element[0].len = beacon->ssid_len;
1133 tag = skb_put(skb, beacon->ssid_len);
1134 memcpy(tag, beacon->ssid, beacon->ssid_len);
1135
1136 tag = skb_put(skb, rate_len);
1137
1138 ieee80211_MFIE_Brate(ieee, &tag);
1139 ieee80211_MFIE_Grate(ieee, &tag);
1140 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1141 if( beacon->bCkipSupported )
1142 {
1143 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1144 u8 CcxAironetBuf[30];
1145 OCTET_STRING osCcxAironetIE;
1146
1147 memset(CcxAironetBuf, 0,30);
1148 osCcxAironetIE.Octet = CcxAironetBuf;
1149 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1150 //
1151 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1152 // We want to make the device type as "4500-client". 060926, by CCW.
1153 //
1154 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1155
1156 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1157 // "The CKIP negotiation is started with the associate request from the client to the access point,
1158 // containing an Aironet element with both the MIC and KP bits set."
1159 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1160 tag = skb_put(skb, ckip_ie_len);
1161 *tag++ = MFIE_TYPE_AIRONET;
1162 *tag++ = osCcxAironetIE.Length;
1163 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1164 tag += osCcxAironetIE.Length;
1165 }
1166
1167 if(beacon->bCcxRmEnable)
1168 {
1169 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1170 OCTET_STRING osCcxRmCap;
1171
1172 osCcxRmCap.Octet = CcxRmCapBuf;
1173 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1174 tag = skb_put(skb,ccxrm_ie_len);
1175 *tag++ = MFIE_TYPE_GENERIC;
1176 *tag++ = osCcxRmCap.Length;
1177 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1178 tag += osCcxRmCap.Length;
1179 }
1180
1181 if( beacon->BssCcxVerNumber >= 2 )
1182 {
1183 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1184 OCTET_STRING osCcxVerNum;
1185 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1186 osCcxVerNum.Octet = CcxVerNumBuf;
1187 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1188 tag = skb_put(skb,cxvernum_ie_len);
1189 *tag++ = MFIE_TYPE_GENERIC;
1190 *tag++ = osCcxVerNum.Length;
1191 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1192 tag += osCcxVerNum.Length;
1193 }
1194 //HT cap element
1195 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1196 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1197 {
1198 tag = skb_put(skb, ht_cap_len);
1199 *tag++ = MFIE_TYPE_HT_CAP;
1200 *tag++ = ht_cap_len - 2;
1201 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1202 tag += ht_cap_len -2;
1203 }
1204 }
1205
1206
1207 //choose what wpa_supplicant gives to associate.
1208 tag = skb_put(skb, wpa_ie_len);
1209 if (wpa_ie_len){
1210 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1211 }
1212
1213 tag = skb_put(skb,wmm_info_len);
1214 if(wmm_info_len) {
1215 ieee80211_WMM_Info(ieee, &tag);
1216 }
1217#ifdef THOMAS_TURBO
1218 tag = skb_put(skb,turbo_info_len);
1219 if(turbo_info_len) {
1220 ieee80211_TURBO_Info(ieee, &tag);
1221 }
1222#endif
1223
1224 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1225 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1226 {
1227 tag = skb_put(skb, ht_cap_len);
1228 *tag++ = MFIE_TYPE_GENERIC;
1229 *tag++ = ht_cap_len - 2;
1230 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1231 tag += ht_cap_len -2;
1232 }
1233
1234 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1235 tag = skb_put(skb, realtek_ie_len);
1236 *tag++ = MFIE_TYPE_GENERIC;
1237 *tag++ = realtek_ie_len - 2;
1238 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1239 }
1240 }
1241 return skb;
1242}
1243
1244void ieee80211_associate_abort(struct ieee80211_device *ieee)
1245{
1246
1247 unsigned long flags;
1248 spin_lock_irqsave(&ieee->lock, flags);
1249
1250 ieee->associate_seq++;
1251
1252 /* don't scan, and avoid to have the RX path possibily
1253 * try again to associate. Even do not react to AUTH or
1254 * ASSOC response. Just wait for the retry wq to be scheduled.
1255 * Here we will check if there are good nets to associate
1256 * with, so we retry or just get back to NO_LINK and scanning
1257 */
1258 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1259 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1260 ieee->softmac_stats.no_auth_rs++;
1261 }else{
1262 IEEE80211_DEBUG_MGMT("Association failed\n");
1263 ieee->softmac_stats.no_ass_rs++;
1264 }
1265
1266 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1267
1268 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1269 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1270 spin_unlock_irqrestore(&ieee->lock, flags);
1271}
1272
1273void ieee80211_associate_abort_cb(unsigned long dev)
1274{
1275 ieee80211_associate_abort((struct ieee80211_device *) dev);
1276}
1277
1278
1279void ieee80211_associate_step1(struct ieee80211_device *ieee)
1280{
1281 struct ieee80211_network *beacon = &ieee->current_network;
1282 struct sk_buff *skb;
1283
1284 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1285
1286 ieee->softmac_stats.tx_auth_rq++;
1287 skb=ieee80211_authentication_req(beacon, ieee, 0);
1288
1289 if (!skb)
1290 ieee80211_associate_abort(ieee);
1291 else{
1292 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1293 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1294 softmac_mgmt_xmit(skb, ieee);
1295 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1296 if(!timer_pending(&ieee->associate_timer)){
1297 ieee->associate_timer.expires = jiffies + (HZ / 2);
1298 add_timer(&ieee->associate_timer);
1299 }
1300 }
1301}
1302
1303void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1304{
1305 u8 *c;
1306 struct sk_buff *skb;
1307 struct ieee80211_network *beacon = &ieee->current_network;
1308
1309 ieee->associate_seq++;
1310 ieee->softmac_stats.tx_auth_rq++;
1311
1312 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1313 if (!skb)
1314 ieee80211_associate_abort(ieee);
1315 else{
1316 c = skb_put(skb, chlen+2);
1317 *(c++) = MFIE_TYPE_CHALLENGE;
1318 *(c++) = chlen;
1319 memcpy(c, challenge, chlen);
1320
1321 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1322
1323 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1324
1325 softmac_mgmt_xmit(skb, ieee);
1326 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1327 }
1328 kfree(challenge);
1329}
1330
1331void ieee80211_associate_step2(struct ieee80211_device *ieee)
1332{
1333 struct sk_buff* skb;
1334 struct ieee80211_network *beacon = &ieee->current_network;
1335
1336 del_timer_sync(&ieee->associate_timer);
1337
1338 IEEE80211_DEBUG_MGMT("Sending association request\n");
1339
1340 ieee->softmac_stats.tx_ass_rq++;
1341 skb=ieee80211_association_req(beacon, ieee);
1342 if (!skb)
1343 ieee80211_associate_abort(ieee);
1344 else{
1345 softmac_mgmt_xmit(skb, ieee);
1346 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1347 }
1348}
1349void ieee80211_associate_complete_wq(struct work_struct *work)
1350{
1351 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1352 printk(KERN_INFO "Associated successfully\n");
1353 ieee->is_roaming = false;
1354 if(ieee80211_is_54g(ieee->current_network) &&
1355 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1356
1357 ieee->rate = 108;
1358 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1359 }else{
1360 ieee->rate = 22;
1361 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1362 }
1363 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1364 {
1365 printk("Successfully associated, ht enabled\n");
1366 HTOnAssocRsp(ieee);
1367 }
1368 else
1369 {
1370 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1371 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1372 }
1373 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1374 // To prevent the immediately calling watch_dog after association.
1375 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1376 {
1377 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1378 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1379 }
1380 ieee->link_change(ieee);
1381 if(ieee->is_silent_reset == 0){
1382 printk("============>normal associate\n");
1383 notify_wx_assoc_event(ieee);
1384 }
1385 else if(ieee->is_silent_reset == 1)
1386 {
1387 printk("==================>silent reset associate\n");
1388 ieee->is_silent_reset = 0;
1389 }
1390
1391 if (ieee->data_hard_resume)
1392 ieee->data_hard_resume(ieee);
1393 netif_carrier_on(ieee->dev);
1394}
1395
1396void ieee80211_associate_complete(struct ieee80211_device *ieee)
1397{
1398 del_timer_sync(&ieee->associate_timer);
1399
1400 ieee->state = IEEE80211_LINKED;
1401 queue_work(ieee->wq, &ieee->associate_complete_wq);
1402}
1403
1404void ieee80211_associate_procedure_wq(struct work_struct *work)
1405{
1406 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1407 ieee->sync_scan_hurryup = 1;
1408#ifdef ENABLE_IPS
1409 if(ieee->ieee80211_ips_leave != NULL)
1410 ieee->ieee80211_ips_leave(ieee);
1411#endif
1412
1413 down(&ieee->wx_sem);
1414
1415 if (ieee->data_hard_stop)
1416 ieee->data_hard_stop(ieee);
1417
1418 ieee80211_stop_scan(ieee);
1419 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1420 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1421
1422 ieee->associate_seq = 1;
1423 ieee80211_associate_step1(ieee);
1424
1425 up(&ieee->wx_sem);
1426}
1427
1428inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1429{
1430 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1431 int tmp_ssid_len = 0;
1432
1433 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1434
1435 /* we are interested in new new only if we are not associated
1436 * and we are not associating / authenticating
1437 */
1438 if (ieee->state != IEEE80211_NOLINK)
1439 return;
1440
1441 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1442 return;
1443
1444 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1445 return;
1446
1447
1448 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1449 /* if the user specified the AP MAC, we need also the essid
1450 * This could be obtained by beacons or, if the network does not
1451 * broadcast it, it can be put manually.
1452 */
1453 apset = ieee->wap_set;
1454 ssidset = ieee->ssid_set;
1455 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1456 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1457 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1458 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1459
1460
1461 if ( /* if the user set the AP check if match.
1462 * if the network does not broadcast essid we check the user supplyed ANY essid
1463 * if the network does broadcast and the user does not set essid it is OK
1464 * if the network does broadcast and the user did set essid chech if essid match
1465 */
1466 ( apset && apmatch &&
1467 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1468 /* if the ap is not set, check that the user set the bssid
1469 * and the network does bradcast and that those two bssid matches
1470 */
1471 (!apset && ssidset && ssidbroad && ssidmatch)
1472 ){
1473 /* if the essid is hidden replace it with the
1474 * essid provided by the user.
1475 */
1476 if (!ssidbroad){
1477 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1478 tmp_ssid_len = ieee->current_network.ssid_len;
1479 }
1480 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1481
1482 if (!ssidbroad){
1483 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1484 ieee->current_network.ssid_len = tmp_ssid_len;
1485 }
1486 printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT);
1487
1488 HTResetIOTSetting(ieee->pHTInfo);
1489 if (ieee->iw_mode == IW_MODE_INFRA){
1490 /* Join the network for the first time */
1491 ieee->AsocRetryCount = 0;
1492 //for HT by amy 080514
1493 if((ieee->current_network.qos_data.supported == 1) &&
1494 ieee->current_network.bssht.bdSupportHT)
1495/*WB, 2008.09.09:bCurrentHTSupport and bEnableHT two flags are going to put together to check whether we are in HT now, so needn't to check bEnableHT flags here. That's is to say we will set to HT support whenever joined AP has the ability to support HT. And whether we are in HT or not, please check bCurrentHTSupport&&bEnableHT now please.*/
1496 {
1497 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1498 }
1499 else
1500 {
1501 ieee->pHTInfo->bCurrentHTSupport = false;
1502 }
1503
1504 ieee->state = IEEE80211_ASSOCIATING;
1505 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1506 }else{
1507 if(ieee80211_is_54g(ieee->current_network) &&
1508 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1509 ieee->rate = 108;
1510 ieee->SetWirelessMode(ieee, IEEE_G);
1511 printk(KERN_INFO"Using G rates\n");
1512 }else{
1513 ieee->rate = 22;
1514 ieee->SetWirelessMode(ieee, IEEE_B);
1515 printk(KERN_INFO"Using B rates\n");
1516 }
1517 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1518 ieee->state = IEEE80211_LINKED;
1519 }
1520
1521 }
1522 }
1523
1524}
1525
1526void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1527{
1528 unsigned long flags;
1529 struct ieee80211_network *target;
1530
1531 spin_lock_irqsave(&ieee->lock, flags);
1532
1533 list_for_each_entry(target, &ieee->network_list, list) {
1534
1535 /* if the state become different that NOLINK means
1536 * we had found what we are searching for
1537 */
1538
1539 if (ieee->state != IEEE80211_NOLINK)
1540 break;
1541
1542 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1543 ieee80211_softmac_new_net(ieee, target);
1544 }
1545
1546 spin_unlock_irqrestore(&ieee->lock, flags);
1547
1548}
1549
1550
1551static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1552{
1553 struct ieee80211_authentication *a;
1554 u8 *t;
1555 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1556 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1557 return 0xcafe;
1558 }
1559 *challenge = NULL;
1560 a = (struct ieee80211_authentication*) skb->data;
1561 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1562 t = skb->data + sizeof(struct ieee80211_authentication);
1563
1564 if(*(t++) == MFIE_TYPE_CHALLENGE){
1565 *chlen = *(t++);
1566 *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
1567 if (!*challenge)
1568 return -ENOMEM;
1569 }
1570 }
1571
1572 return cpu_to_le16(a->status);
1573
1574}
1575
1576
1577int auth_rq_parse(struct sk_buff *skb,u8* dest)
1578{
1579 struct ieee80211_authentication *a;
1580
1581 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1582 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1583 return -1;
1584 }
1585 a = (struct ieee80211_authentication*) skb->data;
1586
1587 memcpy(dest,a->header.addr2, ETH_ALEN);
1588
1589 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1590 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1591
1592 return WLAN_STATUS_SUCCESS;
1593}
1594
1595static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1596{
1597 u8 *tag;
1598 u8 *skbend;
1599 u8 *ssid=NULL;
1600 u8 ssidlen = 0;
1601
1602 struct ieee80211_hdr_3addr *header =
1603 (struct ieee80211_hdr_3addr *) skb->data;
1604
1605 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1606 return -1; /* corrupted */
1607
1608 memcpy(src,header->addr2, ETH_ALEN);
1609
1610 skbend = (u8*)skb->data + skb->len;
1611
1612 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1613
1614 while (tag+1 < skbend){
1615 if (*tag == 0){
1616 ssid = tag+2;
1617 ssidlen = *(tag+1);
1618 break;
1619 }
1620 tag++; /* point to the len field */
1621 tag = tag + *(tag); /* point to the last data byte of the tag */
1622 tag++; /* point to the next tag */
1623 }
1624
1625 if (ssidlen == 0) return 1;
1626
1627 if (!ssid) return 1; /* ssid not found in tagged param */
1628 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1629
1630}
1631
1632int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1633{
1634 struct ieee80211_assoc_request_frame *a;
1635
1636 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1637 sizeof(struct ieee80211_info_element))) {
1638
1639 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1640 return -1;
1641 }
1642
1643 a = (struct ieee80211_assoc_request_frame*) skb->data;
1644
1645 memcpy(dest,a->header.addr2,ETH_ALEN);
1646
1647 return 0;
1648}
1649
1650static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1651{
1652 struct ieee80211_assoc_response_frame *response_head;
1653 u16 status_code;
1654
1655 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1656 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1657 return 0xcafe;
1658 }
1659
1660 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1661 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1662
1663 status_code = le16_to_cpu(response_head->status);
1664 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1665 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1666 ((ieee->mode == IEEE_G) &&
1667 (ieee->current_network.mode == IEEE_N_24G) &&
1668 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1669 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1670 }else {
1671 ieee->AsocRetryCount = 0;
1672 }
1673
1674 return le16_to_cpu(response_head->status);
1675}
1676
1677static inline void
1678ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1679{
1680 u8 dest[ETH_ALEN];
1681
1682 ieee->softmac_stats.rx_probe_rq++;
1683 if (probe_rq_parse(ieee, skb, dest)){
1684 ieee->softmac_stats.tx_probe_rs++;
1685 ieee80211_resp_to_probe(ieee, dest);
1686 }
1687}
1688
1689static inline void
1690ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1691{
1692 u8 dest[ETH_ALEN];
1693 int status;
1694 ieee->softmac_stats.rx_auth_rq++;
1695
1696 status = auth_rq_parse(skb, dest);
1697 if (status != -1) {
1698 ieee80211_resp_to_auth(ieee, status, dest);
1699 }
1700}
1701
1702static inline void
1703ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1704{
1705 u8 dest[ETH_ALEN];
1706
1707 ieee->softmac_stats.rx_ass_rq++;
1708 if (assoc_rq_parse(skb,dest) != -1){
1709 ieee80211_resp_to_assoc_rq(ieee, dest);
1710 }
1711
1712 printk(KERN_INFO"New client associated: %pM\n", dest);
1713}
1714
1715
1716
1717void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1718{
1719
1720 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1721
1722 if (buf)
1723 softmac_ps_mgmt_xmit(buf, ieee);
1724
1725}
1726
1727void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
1728{
1729
1730 struct sk_buff *buf = ieee80211_pspoll_func(ieee);
1731
1732 if (buf)
1733 softmac_ps_mgmt_xmit(buf, ieee);
1734
1735}
1736
1737short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1738{
1739 int timeout = ieee->ps_timeout;
1740 u8 dtim;
1741
1742 if(ieee->LPSDelayCnt)
1743 {
1744 ieee->LPSDelayCnt --;
1745 return 0;
1746 }
1747
1748 dtim = ieee->current_network.dtim_data;
1749 if(!(dtim & IEEE80211_DTIM_VALID))
1750 return 0;
1751 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1752 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1753 /* there's no need to nofity AP that I find you buffered with broadcast packet */
1754 if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
1755 return 2;
1756
1757 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
1758 return 0;
1759 }
1760 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
1761 return 0;
1762 }
1763 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1764 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1765 return 0;
1766
1767 if(time_l){
1768 if(ieee->bAwakePktSent == true) {
1769 ieee->LPSAwakeIntvl = 1;//tx wake one beacon
1770 } else {
1771 u8 MaxPeriod = 1;
1772
1773 if(ieee->LPSAwakeIntvl == 0)
1774 ieee->LPSAwakeIntvl = 1;
1775 if(ieee->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
1776 MaxPeriod = 1; // 1 Beacon interval
1777 else if(ieee->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
1778 MaxPeriod = ieee->current_network.dtim_period;
1779 else
1780 MaxPeriod = ieee->RegMaxLPSAwakeIntvl;
1781 ieee->LPSAwakeIntvl = (ieee->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (ieee->LPSAwakeIntvl + 1);
1782 }
1783 {
1784 u8 LPSAwakeIntvl_tmp = 0;
1785 u8 period = ieee->current_network.dtim_period;
1786 u8 count = ieee->current_network.tim.tim_count;
1787 if(count == 0 ) {
1788 if(ieee->LPSAwakeIntvl > period)
1789 LPSAwakeIntvl_tmp = period + (ieee->LPSAwakeIntvl - period) -((ieee->LPSAwakeIntvl-period)%period);
1790 else
1791 LPSAwakeIntvl_tmp = ieee->LPSAwakeIntvl;
1792
1793 } else {
1794 if(ieee->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
1795 LPSAwakeIntvl_tmp = count + (ieee->LPSAwakeIntvl - count) -((ieee->LPSAwakeIntvl-count)%period);
1796 else
1797 LPSAwakeIntvl_tmp = ieee->LPSAwakeIntvl;
1798 }
1799
1800 *time_l = ieee->current_network.last_dtim_sta_time[0]
1801 + MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
1802 }
1803 }
1804
1805 if(time_h){
1806 *time_h = ieee->current_network.last_dtim_sta_time[1];
1807 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1808 *time_h += 1;
1809 }
1810
1811 return 1;
1812
1813
1814}
1815
1816inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1817{
1818
1819 u32 th,tl;
1820 short sleep;
1821 unsigned long flags;
1822
1823 spin_lock_irqsave(&ieee->lock, flags);
1824
1825 if((ieee->ps == IEEE80211_PS_DISABLED ||
1826 ieee->iw_mode != IW_MODE_INFRA ||
1827 ieee->state != IEEE80211_LINKED)){
1828
1829 // #warning CHECK_LOCK_HERE
1830 printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
1831 __FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
1832 spin_lock(&ieee->mgmt_tx_lock);
1833
1834 ieee80211_sta_wakeup(ieee, 1);
1835
1836 spin_unlock(&ieee->mgmt_tx_lock);
1837 }
1838
1839 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1840 /* 2 wake, 1 sleep, 0 do nothing */
1841 if(sleep == 0)//it is not time out or dtim is not valid
1842 {
1843 goto out;
1844 }
1845 if(sleep == 1){
1846 if(ieee->sta_sleep == 1){
1847 ieee->enter_sleep_state(ieee, th, tl);
1848 }
1849
1850 else if(ieee->sta_sleep == 0){
1851 spin_lock(&ieee->mgmt_tx_lock);
1852
1853 if (ieee->ps_is_queue_empty(ieee)) {
1854 ieee->sta_sleep = 2;
1855 ieee->ack_tx_to_ieee = 1;
1856 ieee80211_sta_ps_send_null_frame(ieee,1);
1857 ieee->ps_th = th;
1858 ieee->ps_tl = tl;
1859 }
1860 spin_unlock(&ieee->mgmt_tx_lock);
1861
1862 }
1863
1864 ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
1865
1866 }else if(sleep == 2){
1867 spin_lock(&ieee->mgmt_tx_lock);
1868
1869 ieee80211_sta_wakeup(ieee,1);
1870
1871 spin_unlock(&ieee->mgmt_tx_lock);
1872 }
1873
1874out:
1875 spin_unlock_irqrestore(&ieee->lock, flags);
1876
1877}
1878
1879void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1880{
1881 if(ieee->sta_sleep == 0){
1882 if(nl){
1883 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
1884 {
1885 ieee->ack_tx_to_ieee = 1;
1886 ieee80211_sta_ps_send_null_frame(ieee, 0);
1887 }
1888 else
1889 {
1890 ieee->ack_tx_to_ieee = 1;
1891 ieee80211_sta_ps_send_pspoll_frame(ieee);
1892 }
1893 }
1894 return;
1895
1896 }
1897
1898 if(ieee->sta_sleep == 1)
1899 ieee->sta_wake_up(ieee);
1900 if(nl){
1901
1902 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
1903 {
1904 ieee->ack_tx_to_ieee = 1;
1905 ieee80211_sta_ps_send_null_frame(ieee, 0);
1906 }
1907 else
1908 {
1909 ieee->ack_tx_to_ieee = 1;
1910 ieee->polling = true;
1911 //ieee80211_sta_ps_send_null_frame(ieee, 0);
1912 ieee80211_sta_ps_send_pspoll_frame(ieee);
1913 }
1914
1915 } else {
1916 ieee->sta_sleep = 0;
1917 ieee->polling = false;
1918 }
1919}
1920
1921void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1922{
1923 unsigned long flags;
1924
1925 spin_lock_irqsave(&ieee->lock, flags);
1926
1927 if(ieee->sta_sleep == 2){
1928 /* Null frame with PS bit set */
1929 if(success){
1930 ieee->sta_sleep = 1;
1931 ieee->enter_sleep_state(ieee, ieee->ps_th, ieee->ps_tl);
1932 }
1933 } else {/* 21112005 - tx again null without PS bit if lost */
1934
1935 if((ieee->sta_sleep == 0) && !success){
1936 spin_lock(&ieee->mgmt_tx_lock);
1937 //ieee80211_sta_ps_send_null_frame(ieee, 0);
1938 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
1939 {
1940 ieee80211_sta_ps_send_null_frame(ieee, 0);
1941 }
1942 else
1943 {
1944 ieee80211_sta_ps_send_pspoll_frame(ieee);
1945 }
1946 spin_unlock(&ieee->mgmt_tx_lock);
1947 }
1948 }
1949 spin_unlock_irqrestore(&ieee->lock, flags);
1950}
1951
1952void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
1953{
1954 struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
1955 u8* act = ieee80211_get_payload(header);
1956 u8 tmp = 0;
1957
1958 if (act == NULL)
1959 {
1960 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1961 return;
1962 }
1963 tmp = *act;
1964 act ++;
1965 switch (tmp)
1966 {
1967 case ACT_CAT_BA:
1968 if (*act == ACT_ADDBAREQ)
1969 ieee80211_rx_ADDBAReq(ieee, skb);
1970 else if (*act == ACT_ADDBARSP)
1971 ieee80211_rx_ADDBARsp(ieee, skb);
1972 else if (*act == ACT_DELBA)
1973 ieee80211_rx_DELBA(ieee, skb);
1974 break;
1975 default:
1976 break;
1977 }
1978 return;
1979
1980}
1981inline int
1982ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1983 struct ieee80211_rx_stats *rx_stats, u16 type,
1984 u16 stype)
1985{
1986 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
1987 u16 errcode;
1988 u8* challenge;
1989 int chlen=0;
1990 int aid;
1991 struct ieee80211_assoc_response_frame *assoc_resp;
1992 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
1993
1994 if(!ieee->proto_started)
1995 return 0;
1996
1997 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1998
1999 case IEEE80211_STYPE_ASSOC_RESP:
2000 case IEEE80211_STYPE_REASSOC_RESP:
2001
2002 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2003 WLAN_FC_GET_STYPE(header->frame_ctl));
2004 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2005 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2006 ieee->iw_mode == IW_MODE_INFRA){
2007 struct ieee80211_network network_resp;
2008 struct ieee80211_network *network = &network_resp;
2009
2010 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2011 ieee->state=IEEE80211_LINKED;
2012 ieee->assoc_id = aid;
2013 ieee->softmac_stats.rx_ass_ok++;
2014 /* station support qos */
2015 /* Let the register setting defaultly with Legacy station */
2016 if(ieee->qos_support) {
2017 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2018 memset(network, 0, sizeof(*network));
2019 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2020 rx_stats->len - sizeof(*assoc_resp),\
2021 network,rx_stats)){
2022 return 1;
2023 }
2024 else
2025 { //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
2026 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2027 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2028 }
2029 if (ieee->handle_assoc_response != NULL)
2030 ieee->handle_assoc_response(ieee, (struct ieee80211_assoc_response_frame*)header, network);
2031 }
2032 ieee80211_associate_complete(ieee);
2033 } else {
2034 /* aid could not been allocated */
2035 ieee->softmac_stats.rx_ass_err++;
2036 printk(
2037 "Association response status code 0x%x\n",
2038 errcode);
2039 IEEE80211_DEBUG_MGMT(
2040 "Association response status code 0x%x\n",
2041 errcode);
2042 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2043 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2044 } else {
2045 ieee80211_associate_abort(ieee);
2046 }
2047 }
2048 }
2049 break;
2050
2051 case IEEE80211_STYPE_ASSOC_REQ:
2052 case IEEE80211_STYPE_REASSOC_REQ:
2053
2054 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2055 ieee->iw_mode == IW_MODE_MASTER)
2056
2057 ieee80211_rx_assoc_rq(ieee, skb);
2058 break;
2059
2060 case IEEE80211_STYPE_AUTH:
2061
2062 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2063 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2064 ieee->iw_mode == IW_MODE_INFRA){
2065
2066 IEEE80211_DEBUG_MGMT("Received authentication response");
2067
2068 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2069 if(ieee->open_wep || !challenge){
2070 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2071 ieee->softmac_stats.rx_auth_rs_ok++;
2072 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2073 {
2074 if (!ieee->GetNmodeSupportBySecCfg(ieee))
2075 {
2076 // WEP or TKIP encryption
2077 if(IsHTHalfNmodeAPs(ieee))
2078 {
2079 bSupportNmode = true;
2080 bHalfSupportNmode = true;
2081 }
2082 else
2083 {
2084 bSupportNmode = false;
2085 bHalfSupportNmode = false;
2086 }
2087 printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
2088 }
2089 }
2090 /* Dummy wirless mode setting to avoid encryption issue */
2091 if(bSupportNmode) {
2092 //N mode setting
2093 ieee->SetWirelessMode(ieee,
2094 ieee->current_network.mode);
2095 }else{
2096 //b/g mode setting
2097 /*TODO*/
2098 ieee->SetWirelessMode(ieee, IEEE_G);
2099 }
2100
2101 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2102 {
2103 printk("===============>entern half N mode\n");
2104 ieee->bHalfWirelessN24GMode = true;
2105 }
2106 else
2107 ieee->bHalfWirelessN24GMode = false;
2108
2109 ieee80211_associate_step2(ieee);
2110 }else{
2111 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2112 }
2113 }else{
2114 ieee->softmac_stats.rx_auth_rs_err++;
2115 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2116
2117 printk("Authentication respose status code 0x%x",errcode);
2118 ieee80211_associate_abort(ieee);
2119 }
2120
2121 }else if (ieee->iw_mode == IW_MODE_MASTER){
2122 ieee80211_rx_auth_rq(ieee, skb);
2123 }
2124 }
2125 break;
2126
2127 case IEEE80211_STYPE_PROBE_REQ:
2128
2129 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2130 ((ieee->iw_mode == IW_MODE_ADHOC ||
2131 ieee->iw_mode == IW_MODE_MASTER) &&
2132 ieee->state == IEEE80211_LINKED)){
2133 ieee80211_rx_probe_rq(ieee, skb);
2134 }
2135 break;
2136
2137 case IEEE80211_STYPE_DISASSOC:
2138 case IEEE80211_STYPE_DEAUTH:
2139 /* FIXME for now repeat all the association procedure
2140 * both for disassociation and deauthentication
2141 */
2142 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2143 ieee->state == IEEE80211_LINKED &&
2144 ieee->iw_mode == IW_MODE_INFRA){
2145
2146 ieee->state = IEEE80211_ASSOCIATING;
2147 ieee->softmac_stats.reassoc++;
2148 ieee->is_roaming = true;
2149 ieee80211_disassociate(ieee);
2150 RemovePeerTS(ieee, header->addr2);
2151 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2152 }
2153 break;
2154 case IEEE80211_STYPE_MANAGE_ACT:
2155 ieee80211_process_action(ieee,skb);
2156 break;
2157 default:
2158 return -1;
2159 break;
2160 }
2161
2162 return 0;
2163}
2164
2165/* following are for a simpler TX queue management.
2166 * Instead of using netif_[stop/wake]_queue the driver
2167 * will uses these two function (plus a reset one), that
2168 * will internally uses the kernel netif_* and takes
2169 * care of the ieee802.11 fragmentation.
2170 * So the driver receives a fragment per time and might
2171 * call the stop function when it want without take care
2172 * to have enough room to TX an entire packet.
2173 * This might be useful if each fragment need it's own
2174 * descriptor, thus just keep a total free memory > than
2175 * the max fragmentation threshold is not enough.. If the
2176 * ieee802.11 stack passed a TXB struct then you needed
2177 * to keep N free descriptors where
2178 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2179 * In this way you need just one and the 802.11 stack
2180 * will take care of buffering fragments and pass them to
2181 * to the driver later, when it wakes the queue.
2182 */
2183void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2184{
2185
2186 unsigned int queue_index = txb->queue_index;
2187 unsigned long flags;
2188 int i;
2189 cb_desc *tcb_desc = NULL;
2190
2191 spin_lock_irqsave(&ieee->lock,flags);
2192
2193 /* called with 2nd parm 0, no tx mgmt lock required */
2194 ieee80211_sta_wakeup(ieee,0);
2195
2196 /* update the tx status */
2197 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2198 if(tcb_desc->bMulticast) {
2199 ieee->stats.multicast++;
2200 }
2201
2202 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2203 for(i = 0; i < txb->nr_frags; i++) {
2204#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2205 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2206#else
2207 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2208#endif
2209 (!ieee->check_nic_enough_desc(ieee, queue_index))||
2210 (ieee->queue_stop)) {
2211 /* insert the skb packet to the wait queue */
2212 /* as for the completion function, it does not need
2213 * to check it any more.
2214 * */
2215#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2216 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2217#else
2218 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2219#endif
2220 }else{
2221 ieee->softmac_data_hard_start_xmit(
2222 txb->fragments[i],
2223 ieee, ieee->rate);
2224 }
2225 }
2226
2227 ieee80211_txb_free(txb);
2228
2229 spin_unlock_irqrestore(&ieee->lock,flags);
2230
2231}
2232
2233/* called with ieee->lock acquired */
2234void ieee80211_resume_tx(struct ieee80211_device *ieee)
2235{
2236 int i;
2237 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2238
2239 if (ieee->queue_stop){
2240 ieee->tx_pending.frag = i;
2241 return;
2242 }else{
2243
2244 ieee->softmac_data_hard_start_xmit(
2245 ieee->tx_pending.txb->fragments[i],
2246 ieee, ieee->rate);
2247 ieee->stats.tx_packets++;
2248 }
2249 }
2250
2251
2252 ieee80211_txb_free(ieee->tx_pending.txb);
2253 ieee->tx_pending.txb = NULL;
2254}
2255
2256
2257void ieee80211_reset_queue(struct ieee80211_device *ieee)
2258{
2259 unsigned long flags;
2260
2261 spin_lock_irqsave(&ieee->lock,flags);
2262 init_mgmt_queue(ieee);
2263 if (ieee->tx_pending.txb){
2264 ieee80211_txb_free(ieee->tx_pending.txb);
2265 ieee->tx_pending.txb = NULL;
2266 }
2267 ieee->queue_stop = 0;
2268 spin_unlock_irqrestore(&ieee->lock,flags);
2269
2270}
2271
2272void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2273{
2274
2275 unsigned long flags;
2276 struct sk_buff *skb;
2277 struct ieee80211_hdr_3addr *header;
2278
2279 spin_lock_irqsave(&ieee->lock,flags);
2280 if (! ieee->queue_stop) goto exit;
2281
2282 ieee->queue_stop = 0;
2283
2284 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2285 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2286
2287 header = (struct ieee80211_hdr_3addr *) skb->data;
2288
2289 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2290
2291 if (ieee->seq_ctrl[0] == 0xFFF)
2292 ieee->seq_ctrl[0] = 0;
2293 else
2294 ieee->seq_ctrl[0]++;
2295
2296 ieee->softmac_data_hard_start_xmit(skb, ieee, ieee->basic_rate);
2297 }
2298 }
2299 if (!ieee->queue_stop && ieee->tx_pending.txb)
2300 ieee80211_resume_tx(ieee);
2301
2302 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2303 ieee->softmac_stats.swtxawake++;
2304 netif_wake_queue(ieee->dev);
2305 }
2306
2307exit :
2308 spin_unlock_irqrestore(&ieee->lock,flags);
2309}
2310
2311
2312void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2313{
2314 if (! netif_queue_stopped(ieee->dev)){
2315 netif_stop_queue(ieee->dev);
2316 ieee->softmac_stats.swtxstop++;
2317 }
2318 ieee->queue_stop = 1;
2319}
2320
2321
2322inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2323{
2324
2325 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2326
2327 /* an IBSS cell address must have the two less significant
2328 * bits of the first byte = 2
2329 */
2330 ieee->current_network.bssid[0] &= ~0x01;
2331 ieee->current_network.bssid[0] |= 0x02;
2332}
2333
2334/* called in user context only */
2335void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2336{
2337 ieee->assoc_id = 1;
2338
2339 if (ieee->current_network.ssid_len == 0){
2340 strncpy(ieee->current_network.ssid,
2341 IEEE80211_DEFAULT_TX_ESSID,
2342 IW_ESSID_MAX_SIZE);
2343
2344 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2345 ieee->ssid_set = 1;
2346 }
2347
2348 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2349
2350 ieee->set_chan(ieee, ieee->current_network.channel);
2351 ieee->state = IEEE80211_LINKED;
2352 ieee->link_change(ieee);
2353 notify_wx_assoc_event(ieee);
2354
2355 if (ieee->data_hard_resume)
2356 ieee->data_hard_resume(ieee);
2357
2358 netif_carrier_on(ieee->dev);
2359}
2360
2361void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2362{
2363 if(ieee->raw_tx){
2364
2365 if (ieee->data_hard_resume)
2366 ieee->data_hard_resume(ieee);
2367
2368 netif_carrier_on(ieee->dev);
2369 }
2370}
2371void ieee80211_start_ibss_wq(struct work_struct *work)
2372{
2373
2374 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2375 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2376 /* iwconfig mode ad-hoc will schedule this and return
2377 * on the other hand this will block further iwconfig SET
2378 * operations because of the wx_sem hold.
2379 * Anyway some most set operations set a flag to speed-up
2380 * (abort) this wq (when syncro scanning) before sleeping
2381 * on the semaphore
2382 */
2383 if(!ieee->proto_started){
2384 printk("==========oh driver down return\n");
2385 return;
2386 }
2387 down(&ieee->wx_sem);
2388
2389 if (ieee->current_network.ssid_len == 0){
2390 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2391 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2392 ieee->ssid_set = 1;
2393 }
2394
2395 ieee->state = IEEE80211_NOLINK;
2396 /* check if we have this cell in our network list */
2397 ieee80211_softmac_check_all_nets(ieee);
2398
2399
2400#ifdef ENABLE_DOT11D //if creating an ad-hoc, set its channel to 10 temporarily--this is the requirement for ASUS, not 11D, so disable 11d.
2401 if (ieee->state == IEEE80211_NOLINK)
2402 ieee->current_network.channel = 6;
2403#endif
2404 /* if not then the state is not linked. Maybe the user swithced to
2405 * ad-hoc mode just after being in monitor mode, or just after
2406 * being very few time in managed mode (so the card have had no
2407 * time to scan all the chans..) or we have just run up the iface
2408 * after setting ad-hoc mode. So we have to give another try..
2409 * Here, in ibss mode, should be safe to do this without extra care
2410 * (in bss mode we had to make sure no-one tryed to associate when
2411 * we had just checked the ieee->state and we was going to start the
2412 * scan) beacause in ibss mode the ieee80211_new_net function, when
2413 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2414 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2415 * scan, that will stop at the first round because it sees the state
2416 * associated.
2417 */
2418 if (ieee->state == IEEE80211_NOLINK)
2419 ieee80211_start_scan_syncro(ieee);
2420
2421 /* the network definitively is not here.. create a new cell */
2422 if (ieee->state == IEEE80211_NOLINK){
2423 printk("creating new IBSS cell\n");
2424 if(!ieee->wap_set)
2425 ieee80211_randomize_cell(ieee);
2426
2427 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2428
2429 ieee->current_network.rates_len = 4;
2430
2431 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2432 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2433 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2434 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2435
2436 }else
2437 ieee->current_network.rates_len = 0;
2438
2439 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2440 ieee->current_network.rates_ex_len = 8;
2441
2442 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2443 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2444 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2445 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2446 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2447 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2448 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2449 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2450
2451 ieee->rate = 108;
2452 }else{
2453 ieee->current_network.rates_ex_len = 0;
2454 ieee->rate = 22;
2455 }
2456
2457 // By default, WMM function will be disabled in IBSS mode
2458 ieee->current_network.QoS_Enable = 0;
2459 ieee->SetWirelessMode(ieee, IEEE_G);
2460 ieee->current_network.atim_window = 0;
2461 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2462 if(ieee->short_slot)
2463 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2464
2465 }
2466
2467 ieee->state = IEEE80211_LINKED;
2468
2469 ieee->set_chan(ieee, ieee->current_network.channel);
2470 ieee->link_change(ieee);
2471
2472 notify_wx_assoc_event(ieee);
2473
2474 ieee80211_start_send_beacons(ieee);
2475
2476 if (ieee->data_hard_resume)
2477 ieee->data_hard_resume(ieee);
2478 netif_carrier_on(ieee->dev);
2479
2480 up(&ieee->wx_sem);
2481}
2482
2483inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2484{
2485 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2486}
2487
2488/* this is called only in user context, with wx_sem held */
2489void ieee80211_start_bss(struct ieee80211_device *ieee)
2490{
2491 unsigned long flags;
2492#ifdef ENABLE_DOT11D
2493 //
2494 // Ref: 802.11d 11.1.3.3
2495 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2496 //
2497 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2498 {
2499 if(! ieee->bGlobalDomain)
2500 {
2501 return;
2502 }
2503 }
2504#endif
2505 /* check if we have already found the net we
2506 * are interested in (if any).
2507 * if not (we are disassociated and we are not
2508 * in associating / authenticating phase) start the background scanning.
2509 */
2510 ieee80211_softmac_check_all_nets(ieee);
2511
2512 /* ensure no-one start an associating process (thus setting
2513 * the ieee->state to ieee80211_ASSOCIATING) while we
2514 * have just cheked it and we are going to enable scan.
2515 * The ieee80211_new_net function is always called with
2516 * lock held (from both ieee80211_softmac_check_all_nets and
2517 * the rx path), so we cannot be in the middle of such function
2518 */
2519 spin_lock_irqsave(&ieee->lock, flags);
2520
2521 if (ieee->state == IEEE80211_NOLINK){
2522#ifdef ENABLE_IPS
2523 if(ieee->ieee80211_ips_leave_wq != NULL)
2524 ieee->ieee80211_ips_leave_wq(ieee);
2525#endif
2526 ieee->actscanning = true;
2527 ieee80211_rtl_start_scan(ieee);
2528 }
2529 spin_unlock_irqrestore(&ieee->lock, flags);
2530}
2531
2532/* called only in userspace context */
2533void ieee80211_disassociate(struct ieee80211_device *ieee)
2534{
2535
2536
2537 netif_carrier_off(ieee->dev);
2538 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2539 ieee80211_reset_queue(ieee);
2540
2541 if (ieee->data_hard_stop)
2542 ieee->data_hard_stop(ieee);
2543#ifdef ENABLE_DOT11D
2544 if(IS_DOT11D_ENABLE(ieee))
2545 Dot11d_Reset(ieee);
2546#endif
2547 ieee->is_set_key = false;
2548 ieee->link_change(ieee);
2549 if (ieee->state == IEEE80211_LINKED ||
2550 ieee->state == IEEE80211_ASSOCIATING) {
2551 ieee->state = IEEE80211_NOLINK;
2552 notify_wx_assoc_event(ieee);
2553 }
2554
2555 ieee->state = IEEE80211_NOLINK;
2556
2557}
2558void ieee80211_associate_retry_wq(struct work_struct *work)
2559{
2560 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2561 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2562 unsigned long flags;
2563
2564 down(&ieee->wx_sem);
2565 if(!ieee->proto_started)
2566 goto exit;
2567
2568 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2569 goto exit;
2570
2571 /* until we do not set the state to IEEE80211_NOLINK
2572 * there are no possibility to have someone else trying
2573 * to start an association procdure (we get here with
2574 * ieee->state = IEEE80211_ASSOCIATING).
2575 * When we set the state to IEEE80211_NOLINK it is possible
2576 * that the RX path run an attempt to associate, but
2577 * both ieee80211_softmac_check_all_nets and the
2578 * RX path works with ieee->lock held so there are no
2579 * problems. If we are still disassociated then start a scan.
2580 * the lock here is necessary to ensure no one try to start
2581 * an association procedure when we have just checked the
2582 * state and we are going to start the scan.
2583 */
2584 ieee->beinretry = true;
2585 ieee->state = IEEE80211_NOLINK;
2586
2587 ieee80211_softmac_check_all_nets(ieee);
2588
2589 spin_lock_irqsave(&ieee->lock, flags);
2590
2591 if(ieee->state == IEEE80211_NOLINK)
2592 {
2593 ieee->is_roaming= false;
2594 ieee->actscanning = true;
2595 ieee80211_rtl_start_scan(ieee);
2596 }
2597 spin_unlock_irqrestore(&ieee->lock, flags);
2598
2599 ieee->beinretry = false;
2600exit:
2601 up(&ieee->wx_sem);
2602}
2603
2604struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2605{
2606 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2607
2608 struct sk_buff *skb;
2609 struct ieee80211_probe_response *b;
2610
2611 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2612
2613 if (!skb)
2614 return NULL;
2615
2616 b = (struct ieee80211_probe_response *) skb->data;
2617 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2618
2619 return skb;
2620
2621}
2622
2623struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2624{
2625 struct sk_buff *skb;
2626 struct ieee80211_probe_response *b;
2627
2628 skb = ieee80211_get_beacon_(ieee);
2629 if(!skb)
2630 return NULL;
2631
2632 b = (struct ieee80211_probe_response *) skb->data;
2633 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2634
2635 if (ieee->seq_ctrl[0] == 0xFFF)
2636 ieee->seq_ctrl[0] = 0;
2637 else
2638 ieee->seq_ctrl[0]++;
2639
2640 return skb;
2641}
2642
2643void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2644{
2645 ieee->sync_scan_hurryup = 1;
2646 down(&ieee->wx_sem);
2647 ieee80211_stop_protocol(ieee, shutdown);
2648 up(&ieee->wx_sem);
2649}
2650
2651
2652void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2653{
2654 if (!ieee->proto_started)
2655 return;
2656
2657 if(shutdown)
2658 ieee->proto_started = 0;
2659 ieee->proto_stoppping = 1;
2660
2661 ieee80211_stop_send_beacons(ieee);
2662 del_timer_sync(&ieee->associate_timer);
2663 cancel_delayed_work(&ieee->associate_retry_wq);
2664 cancel_delayed_work(&ieee->start_ibss_wq);
2665 ieee80211_stop_scan(ieee);
2666
2667 ieee80211_disassociate(ieee);
2668 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2669
2670 ieee->proto_stoppping = 0;
2671}
2672
2673void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2674{
2675 ieee->sync_scan_hurryup = 0;
2676 down(&ieee->wx_sem);
2677 ieee80211_start_protocol(ieee);
2678 up(&ieee->wx_sem);
2679}
2680
2681void ieee80211_start_protocol(struct ieee80211_device *ieee)
2682{
2683 short ch = 0;
2684 int i = 0;
2685 if (ieee->proto_started)
2686 return;
2687
2688 ieee->proto_started = 1;
2689
2690 if (ieee->current_network.channel == 0){
2691 do{
2692 ch++;
2693 if (ch > MAX_CHANNEL_NUMBER)
2694 return; /* no channel found */
2695#ifdef ENABLE_DOT11D
2696 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2697#else
2698 }while(!ieee->channel_map[ch]);
2699#endif
2700 ieee->current_network.channel = ch;
2701 }
2702
2703 if (ieee->current_network.beacon_interval == 0)
2704 ieee->current_network.beacon_interval = 100;
2705
2706 for(i = 0; i < 17; i++) {
2707 ieee->last_rxseq_num[i] = -1;
2708 ieee->last_rxfrag_num[i] = -1;
2709 ieee->last_packet_time[i] = 0;
2710 }
2711
2712 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2713
2714 ieee->state = IEEE80211_NOLINK;
2715
2716
2717 /* if the user set the MAC of the ad-hoc cell and then
2718 * switch to managed mode, shall we make sure that association
2719 * attempts does not fail just because the user provide the essid
2720 * and the nic is still checking for the AP MAC ??
2721 */
2722 if (ieee->iw_mode == IW_MODE_INFRA)
2723 ieee80211_start_bss(ieee);
2724
2725 else if (ieee->iw_mode == IW_MODE_ADHOC)
2726 ieee80211_start_ibss(ieee);
2727
2728 else if (ieee->iw_mode == IW_MODE_MASTER)
2729 ieee80211_start_master_bss(ieee);
2730
2731 else if(ieee->iw_mode == IW_MODE_MONITOR)
2732 ieee80211_start_monitor_mode(ieee);
2733}
2734
2735
2736#define DRV_NAME "Ieee80211"
2737void ieee80211_softmac_init(struct ieee80211_device *ieee)
2738{
2739 int i;
2740 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2741
2742 ieee->state = IEEE80211_NOLINK;
2743 ieee->sync_scan_hurryup = 0;
2744 for(i = 0; i < 5; i++) {
2745 ieee->seq_ctrl[i] = 0;
2746 }
2747#ifdef ENABLE_DOT11D
2748 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2749 if (!ieee->pDot11dInfo)
2750 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2751#endif
2752 //added for AP roaming
2753 ieee->LinkDetectInfo.SlotNum = 2;
2754 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2755 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2756
2757 ieee->assoc_id = 0;
2758 ieee->queue_stop = 0;
2759 ieee->scanning = 0;
2760 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2761 ieee->wap_set = 0;
2762 ieee->ssid_set = 0;
2763 ieee->proto_started = 0;
2764 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2765 ieee->rate = 22;
2766 ieee->ps = IEEE80211_PS_DISABLED;
2767 ieee->sta_sleep = 0;
2768 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2769 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2770 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2771 //added by amy
2772 ieee->actscanning = false;
2773 ieee->beinretry = false;
2774 ieee->is_set_key = false;
2775 init_mgmt_queue(ieee);
2776
2777 ieee->sta_edca_param[0] = 0x0000A403;
2778 ieee->sta_edca_param[1] = 0x0000A427;
2779 ieee->sta_edca_param[2] = 0x005E4342;
2780 ieee->sta_edca_param[3] = 0x002F3262;
2781 ieee->aggregation = true;
2782 ieee->enable_rx_imm_BA = 1;
2783 ieee->tx_pending.txb = NULL;
2784
2785 init_timer(&ieee->associate_timer);
2786 ieee->associate_timer.data = (unsigned long)ieee;
2787 ieee->associate_timer.function = ieee80211_associate_abort_cb;
2788
2789 init_timer(&ieee->beacon_timer);
2790 ieee->beacon_timer.data = (unsigned long) ieee;
2791 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2792
2793 ieee->wq = create_workqueue(DRV_NAME);
2794
2795 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2796 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2797 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2798 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2799 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2800 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2801
2802 sema_init(&ieee->wx_sem, 1);
2803 sema_init(&ieee->scan_sem, 1);
2804#ifdef ENABLE_IPS
2805 sema_init(&ieee->ips_sem,1);
2806#endif
2807 spin_lock_init(&ieee->mgmt_tx_lock);
2808 spin_lock_init(&ieee->beacon_lock);
2809
2810 tasklet_init(&ieee->ps_task,
2811 (void(*)(unsigned long)) ieee80211_sta_ps,
2812 (unsigned long)ieee);
2813
2814}
2815
2816void ieee80211_softmac_free(struct ieee80211_device *ieee)
2817{
2818 down(&ieee->wx_sem);
2819#ifdef ENABLE_DOT11D
2820 kfree(ieee->pDot11dInfo);
2821 ieee->pDot11dInfo = NULL;
2822#endif
2823 del_timer_sync(&ieee->associate_timer);
2824
2825 cancel_delayed_work(&ieee->associate_retry_wq);
2826 destroy_workqueue(ieee->wq);
2827
2828 up(&ieee->wx_sem);
2829}
2830
2831/********************************************************
2832 * Start of WPA code. *
2833 * this is stolen from the ipw2200 driver *
2834 ********************************************************/
2835
2836
2837static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2838{
2839 /* This is called when wpa_supplicant loads and closes the driver
2840 * interface. */
2841 printk("%s WPA\n",value ? "enabling" : "disabling");
2842 ieee->wpa_enabled = value;
2843 return 0;
2844}
2845
2846
2847void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
2848{
2849 /* make sure WPA is enabled */
2850 ieee80211_wpa_enable(ieee, 1);
2851
2852 ieee80211_disassociate(ieee);
2853}
2854
2855
2856static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2857{
2858
2859 int ret = 0;
2860
2861 switch (command) {
2862 case IEEE_MLME_STA_DEAUTH:
2863 // silently ignore
2864 break;
2865
2866 case IEEE_MLME_STA_DISASSOC:
2867 ieee80211_disassociate(ieee);
2868 break;
2869
2870 default:
2871 printk("Unknown MLME request: %d\n", command);
2872 ret = -EOPNOTSUPP;
2873 }
2874
2875 return ret;
2876}
2877
2878
2879static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2880 struct ieee_param *param, int plen)
2881{
2882 u8 *buf;
2883
2884 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2885 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2886 return -EINVAL;
2887
2888 if (param->u.wpa_ie.len) {
2889 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2890 GFP_KERNEL);
2891 if (buf == NULL)
2892 return -ENOMEM;
2893
2894 kfree(ieee->wpa_ie);
2895 ieee->wpa_ie = buf;
2896 ieee->wpa_ie_len = param->u.wpa_ie.len;
2897 } else {
2898 kfree(ieee->wpa_ie);
2899 ieee->wpa_ie = NULL;
2900 ieee->wpa_ie_len = 0;
2901 }
2902
2903 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2904 return 0;
2905}
2906
2907#define AUTH_ALG_OPEN_SYSTEM 0x1
2908#define AUTH_ALG_SHARED_KEY 0x2
2909
2910static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2911{
2912
2913 struct ieee80211_security sec = {
2914 .flags = SEC_AUTH_MODE,
2915 };
2916 int ret = 0;
2917
2918 if (value & AUTH_ALG_SHARED_KEY) {
2919 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2920 ieee->open_wep = 0;
2921 ieee->auth_mode = 1;
2922 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2923 sec.auth_mode = WLAN_AUTH_OPEN;
2924 ieee->open_wep = 1;
2925 ieee->auth_mode = 0;
2926 }
2927 else if (value & IW_AUTH_ALG_LEAP){
2928 sec.auth_mode = WLAN_AUTH_LEAP;
2929 ieee->open_wep = 1;
2930 ieee->auth_mode = 2;
2931 }
2932
2933
2934 if (ieee->set_security)
2935 ieee->set_security(ieee, &sec);
2936
2937 return ret;
2938}
2939
2940static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2941{
2942 int ret=0;
2943 unsigned long flags;
2944
2945 switch (name) {
2946 case IEEE_PARAM_WPA_ENABLED:
2947 ret = ieee80211_wpa_enable(ieee, value);
2948 break;
2949
2950 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2951 ieee->tkip_countermeasures=value;
2952 break;
2953
2954 case IEEE_PARAM_DROP_UNENCRYPTED: {
2955 /* HACK:
2956 *
2957 * wpa_supplicant calls set_wpa_enabled when the driver
2958 * is loaded and unloaded, regardless of if WPA is being
2959 * used. No other calls are made which can be used to
2960 * determine if encryption will be used or not prior to
2961 * association being expected. If encryption is not being
2962 * used, drop_unencrypted is set to false, else true -- we
2963 * can use this to determine if the CAP_PRIVACY_ON bit should
2964 * be set.
2965 */
2966 struct ieee80211_security sec = {
2967 .flags = SEC_ENABLED,
2968 .enabled = value,
2969 };
2970 ieee->drop_unencrypted = value;
2971 /* We only change SEC_LEVEL for open mode. Others
2972 * are set by ipw_wpa_set_encryption.
2973 */
2974 if (!value) {
2975 sec.flags |= SEC_LEVEL;
2976 sec.level = SEC_LEVEL_0;
2977 }
2978 else {
2979 sec.flags |= SEC_LEVEL;
2980 sec.level = SEC_LEVEL_1;
2981 }
2982 if (ieee->set_security)
2983 ieee->set_security(ieee, &sec);
2984 break;
2985 }
2986
2987 case IEEE_PARAM_PRIVACY_INVOKED:
2988 ieee->privacy_invoked=value;
2989 break;
2990
2991 case IEEE_PARAM_AUTH_ALGS:
2992 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2993 break;
2994
2995 case IEEE_PARAM_IEEE_802_1X:
2996 ieee->ieee802_1x=value;
2997 break;
2998 case IEEE_PARAM_WPAX_SELECT:
2999 // added for WPA2 mixed mode
3000 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3001 ieee->wpax_type_set = 1;
3002 ieee->wpax_type_notify = value;
3003 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3004 break;
3005
3006 default:
3007 printk("Unknown WPA param: %d\n",name);
3008 ret = -EOPNOTSUPP;
3009 }
3010
3011 return ret;
3012}
3013
3014/* implementation borrowed from hostap driver */
3015
3016static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3017 struct ieee_param *param, int param_len)
3018{
3019 int ret = 0;
3020
3021 struct ieee80211_crypto_ops *ops;
3022 struct ieee80211_crypt_data **crypt;
3023
3024 struct ieee80211_security sec = {
3025 .flags = 0,
3026 };
3027
3028 param->u.crypt.err = 0;
3029 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3030
3031 if (param_len !=
3032 (int) ((char *) param->u.crypt.key - (char *) param) +
3033 param->u.crypt.key_len) {
3034 printk("Len mismatch %d, %d\n", param_len,
3035 param->u.crypt.key_len);
3036 return -EINVAL;
3037 }
3038 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3039 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3040 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3041 if (param->u.crypt.idx >= WEP_KEYS)
3042 return -EINVAL;
3043 crypt = &ieee->crypt[param->u.crypt.idx];
3044 } else {
3045 return -EINVAL;
3046 }
3047
3048 if (strcmp(param->u.crypt.alg, "none") == 0) {
3049 if (crypt) {
3050 sec.enabled = 0;
3051 // FIXME FIXME
3052 //sec.encrypt = 0;
3053 sec.level = SEC_LEVEL_0;
3054 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3055 ieee80211_crypt_delayed_deinit(ieee, crypt);
3056 }
3057 goto done;
3058 }
3059 sec.enabled = 1;
3060// FIXME FIXME
3061// sec.encrypt = 1;
3062 sec.flags |= SEC_ENABLED;
3063
3064 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3065 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3066 strcmp(param->u.crypt.alg, "TKIP"))
3067 goto skip_host_crypt;
3068
3069 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3070 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3071 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3072 /* set WEP40 first, it will be modified according to WEP104 or
3073 * WEP40 at other place */
3074 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3075 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3076 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3077 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3078 if (ops == NULL) {
3079 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3080 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3081 ret = -EINVAL;
3082 goto done;
3083 }
3084
3085 if (*crypt == NULL || (*crypt)->ops != ops) {
3086 struct ieee80211_crypt_data *new_crypt;
3087
3088 ieee80211_crypt_delayed_deinit(ieee, crypt);
3089
3090 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3091 if (new_crypt == NULL) {
3092 ret = -ENOMEM;
3093 goto done;
3094 }
3095 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3096 new_crypt->ops = ops;
3097 if (new_crypt->ops)
3098 new_crypt->priv =
3099 new_crypt->ops->init(param->u.crypt.idx);
3100
3101 if (new_crypt->priv == NULL) {
3102 kfree(new_crypt);
3103 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3104 ret = -EINVAL;
3105 goto done;
3106 }
3107
3108 *crypt = new_crypt;
3109 }
3110
3111 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3112 (*crypt)->ops->set_key(param->u.crypt.key,
3113 param->u.crypt.key_len, param->u.crypt.seq,
3114 (*crypt)->priv) < 0) {
3115 printk("key setting failed\n");
3116 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3117 ret = -EINVAL;
3118 goto done;
3119 }
3120
3121 skip_host_crypt:
3122 if (param->u.crypt.set_tx) {
3123 ieee->tx_keyidx = param->u.crypt.idx;
3124 sec.active_key = param->u.crypt.idx;
3125 sec.flags |= SEC_ACTIVE_KEY;
3126 } else
3127 sec.flags &= ~SEC_ACTIVE_KEY;
3128
3129 if (param->u.crypt.alg != NULL) {
3130 memcpy(sec.keys[param->u.crypt.idx],
3131 param->u.crypt.key,
3132 param->u.crypt.key_len);
3133 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3134 sec.flags |= (1 << param->u.crypt.idx);
3135
3136 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3137 sec.flags |= SEC_LEVEL;
3138 sec.level = SEC_LEVEL_1;
3139 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3140 sec.flags |= SEC_LEVEL;
3141 sec.level = SEC_LEVEL_2;
3142 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3143 sec.flags |= SEC_LEVEL;
3144 sec.level = SEC_LEVEL_3;
3145 }
3146 }
3147 done:
3148 if (ieee->set_security)
3149 ieee->set_security(ieee, &sec);
3150
3151 /* Do not reset port if card is in Managed mode since resetting will
3152 * generate new IEEE 802.11 authentication which may end up in looping
3153 * with IEEE 802.1X. If your hardware requires a reset after WEP
3154 * configuration (for example... Prism2), implement the reset_port in
3155 * the callbacks structures used to initialize the 802.11 stack. */
3156 if (ieee->reset_on_keychange &&
3157 ieee->iw_mode != IW_MODE_INFRA &&
3158 ieee->reset_port &&
3159 ieee->reset_port(ieee)) {
3160 printk("reset_port failed\n");
3161 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3162 return -EINVAL;
3163 }
3164
3165 return ret;
3166}
3167
3168inline struct sk_buff *ieee80211_disassociate_skb(
3169 struct ieee80211_network *beacon,
3170 struct ieee80211_device *ieee,
3171 u8 asRsn)
3172{
3173 struct sk_buff *skb;
3174 struct ieee80211_disassoc *disass;
3175
3176 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3177 if (!skb)
3178 return NULL;
3179
3180 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3181 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3182 disass->header.duration_id = 0;
3183
3184 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3185 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3186 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3187
3188 disass->reason = asRsn;
3189 return skb;
3190}
3191
3192
3193void
3194SendDisassociation(
3195 struct ieee80211_device *ieee,
3196 u8* asSta,
3197 u8 asRsn
3198)
3199{
3200 struct ieee80211_network *beacon = &ieee->current_network;
3201 struct sk_buff *skb;
3202 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3203 if (skb){
3204 softmac_mgmt_xmit(skb, ieee);
3205 //dev_kfree_skb_any(skb);//edit by thomas
3206 }
3207}
3208
3209int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3210{
3211 struct ieee_param *param;
3212 int ret=0;
3213
3214 down(&ieee->wx_sem);
3215 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3216
3217 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3218 ret = -EINVAL;
3219 goto out;
3220 }
3221
3222 param = kmalloc(p->length, GFP_KERNEL);
3223 if (param == NULL){
3224 ret = -ENOMEM;
3225 goto out;
3226 }
3227 if (copy_from_user(param, p->pointer, p->length)) {
3228 kfree(param);
3229 ret = -EFAULT;
3230 goto out;
3231 }
3232
3233 switch (param->cmd) {
3234
3235 case IEEE_CMD_SET_WPA_PARAM:
3236 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3237 param->u.wpa_param.value);
3238 break;
3239
3240 case IEEE_CMD_SET_WPA_IE:
3241 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3242 break;
3243
3244 case IEEE_CMD_SET_ENCRYPTION:
3245 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3246 break;
3247
3248 case IEEE_CMD_MLME:
3249 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3250 param->u.mlme.reason_code);
3251 break;
3252
3253 default:
3254 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3255 ret = -EOPNOTSUPP;
3256 break;
3257 }
3258
3259 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3260 ret = -EFAULT;
3261
3262 kfree(param);
3263out:
3264 up(&ieee->wx_sem);
3265
3266 return ret;
3267}
3268
3269void notify_wx_assoc_event(struct ieee80211_device *ieee)
3270{
3271 union iwreq_data wrqu;
3272 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3273 if (ieee->state == IEEE80211_LINKED)
3274 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3275 else
3276 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3277 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3278}
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
new file mode 100644
index 00000000000..d8a068e32e5
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
@@ -0,0 +1,600 @@
1/* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
3 *
4 * Mostly extracted from the rtl8180-sa2400 driver for the
5 * in-kernel generic ieee802.11 stack.
6 *
7 * Some pieces of code might be stolen from ipw2100 driver
8 * copyright of who own it's copyright ;-)
9 *
10 * PS wx handler mostly stolen from hostap, copyright who
11 * own it's copyright ;-)
12 *
13 * released under the GPL
14 */
15
16
17#include "ieee80211.h"
18#ifdef ENABLE_DOT11D
19#include "dot11d.h"
20#endif
21/* FIXME: add A freqs */
22
23const long ieee80211_wlan_frequencies[] = {
24 2412, 2417, 2422, 2427,
25 2432, 2437, 2442, 2447,
26 2452, 2457, 2462, 2467,
27 2472, 2484
28};
29
30
31int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
32 union iwreq_data *wrqu, char *b)
33{
34 int ret;
35 struct iw_freq *fwrq = & wrqu->freq;
36
37 down(&ieee->wx_sem);
38
39 if(ieee->iw_mode == IW_MODE_INFRA){
40 ret = -EOPNOTSUPP;
41 goto out;
42 }
43
44 /* if setting by freq convert to channel */
45 if (fwrq->e == 1) {
46 if ((fwrq->m >= (int) 2.412e8 &&
47 fwrq->m <= (int) 2.487e8)) {
48 int f = fwrq->m / 100000;
49 int c = 0;
50
51 while ((c < 14) && (f != ieee80211_wlan_frequencies[c]))
52 c++;
53
54 /* hack to fall through */
55 fwrq->e = 0;
56 fwrq->m = c + 1;
57 }
58 }
59
60 if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){
61 ret = -EOPNOTSUPP;
62 goto out;
63
64 }else { /* Set the channel */
65
66#ifdef ENABLE_DOT11D
67 if (!(GET_DOT11D_INFO(ieee)->channel_map)[fwrq->m]) {
68 ret = -EINVAL;
69 goto out;
70 }
71#endif
72 ieee->current_network.channel = fwrq->m;
73 ieee->set_chan(ieee, ieee->current_network.channel);
74
75 if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
76 if(ieee->state == IEEE80211_LINKED){
77
78 ieee80211_stop_send_beacons(ieee);
79 ieee80211_start_send_beacons(ieee);
80 }
81 }
82
83 ret = 0;
84out:
85 up(&ieee->wx_sem);
86 return ret;
87}
88
89
90int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
91 struct iw_request_info *a,
92 union iwreq_data *wrqu, char *b)
93{
94 struct iw_freq *fwrq = & wrqu->freq;
95
96 if (ieee->current_network.channel == 0)
97 return -1;
98 //NM 0.7.0 will not accept channel any more.
99 fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel-1] * 100000;
100 fwrq->e = 1;
101
102 return 0;
103}
104
105int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
106 struct iw_request_info *info,
107 union iwreq_data *wrqu, char *extra)
108{
109 unsigned long flags;
110 wrqu->ap_addr.sa_family = ARPHRD_ETHER;
111
112 if (ieee->iw_mode == IW_MODE_MONITOR)
113 return -1;
114
115 /* We want avoid to give to the user inconsistent infos*/
116 spin_lock_irqsave(&ieee->lock, flags);
117
118 if (ieee->state != IEEE80211_LINKED &&
119 ieee->state != IEEE80211_LINKED_SCANNING &&
120 ieee->wap_set == 0)
121
122 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
123 else
124 memcpy(wrqu->ap_addr.sa_data,
125 ieee->current_network.bssid, ETH_ALEN);
126
127 spin_unlock_irqrestore(&ieee->lock, flags);
128
129 return 0;
130}
131
132
133int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
134 struct iw_request_info *info,
135 union iwreq_data *awrq,
136 char *extra)
137{
138
139 int ret = 0;
140 u8 zero[] = {0,0,0,0,0,0};
141 unsigned long flags;
142
143 short ifup = ieee->proto_started;//dev->flags & IFF_UP;
144 struct sockaddr *temp = (struct sockaddr *)awrq;
145
146 ieee->sync_scan_hurryup = 1;
147
148 down(&ieee->wx_sem);
149 /* use ifconfig hw ether */
150 if (ieee->iw_mode == IW_MODE_MASTER){
151 ret = -1;
152 goto out;
153 }
154
155 if (temp->sa_family != ARPHRD_ETHER){
156 ret = -EINVAL;
157 goto out;
158 }
159
160 if (ifup)
161 ieee80211_stop_protocol(ieee,true);
162
163 /* just to avoid to give inconsistent infos in the
164 * get wx method. not really needed otherwise
165 */
166 spin_lock_irqsave(&ieee->lock, flags);
167
168 memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN);
169 ieee->wap_set = memcmp(temp->sa_data, zero,ETH_ALEN)!=0;
170
171 spin_unlock_irqrestore(&ieee->lock, flags);
172
173 if (ifup)
174 ieee80211_start_protocol(ieee);
175out:
176 up(&ieee->wx_sem);
177 return ret;
178}
179
180 int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b)
181{
182 int len,ret = 0;
183 unsigned long flags;
184
185 if (ieee->iw_mode == IW_MODE_MONITOR)
186 return -1;
187
188 /* We want avoid to give to the user inconsistent infos*/
189 spin_lock_irqsave(&ieee->lock, flags);
190
191 if (ieee->current_network.ssid[0] == '\0' ||
192 ieee->current_network.ssid_len == 0){
193 ret = -1;
194 goto out;
195 }
196
197 if (ieee->state != IEEE80211_LINKED &&
198 ieee->state != IEEE80211_LINKED_SCANNING &&
199 ieee->ssid_set == 0){
200 ret = -1;
201 goto out;
202 }
203 len = ieee->current_network.ssid_len;
204 wrqu->essid.length = len;
205 strncpy(b,ieee->current_network.ssid,len);
206 wrqu->essid.flags = 1;
207
208out:
209 spin_unlock_irqrestore(&ieee->lock, flags);
210
211 return ret;
212
213}
214
215int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
216 struct iw_request_info *info,
217 union iwreq_data *wrqu, char *extra)
218{
219
220 u32 target_rate = wrqu->bitrate.value;
221
222 ieee->rate = target_rate/100000;
223 //FIXME: we might want to limit rate also in management protocols.
224 return 0;
225}
226
227
228
229int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
230 struct iw_request_info *info,
231 union iwreq_data *wrqu, char *extra)
232{
233 u32 tmp_rate;
234 tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate);
235
236 wrqu->bitrate.value = tmp_rate * 500000;
237
238 return 0;
239}
240
241
242int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
243 struct iw_request_info *info,
244 union iwreq_data *wrqu, char *extra)
245{
246 if (wrqu->rts.disabled || !wrqu->rts.fixed)
247 ieee->rts = DEFAULT_RTS_THRESHOLD;
248 else
249 {
250 if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
251 wrqu->rts.value > MAX_RTS_THRESHOLD)
252 return -EINVAL;
253 ieee->rts = wrqu->rts.value;
254 }
255 return 0;
256}
257
258int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
259 struct iw_request_info *info,
260 union iwreq_data *wrqu, char *extra)
261{
262 wrqu->rts.value = ieee->rts;
263 wrqu->rts.fixed = 0; /* no auto select */
264 wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD);
265 return 0;
266}
267int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
268 union iwreq_data *wrqu, char *b)
269{
270
271 ieee->sync_scan_hurryup = 1;
272
273 down(&ieee->wx_sem);
274
275 if (wrqu->mode == ieee->iw_mode)
276 goto out;
277
278 if (wrqu->mode == IW_MODE_MONITOR){
279
280 ieee->dev->type = ARPHRD_IEEE80211;
281 }else{
282 ieee->dev->type = ARPHRD_ETHER;
283 }
284
285 if (!ieee->proto_started){
286 ieee->iw_mode = wrqu->mode;
287 }else{
288 ieee80211_stop_protocol(ieee,true);
289 ieee->iw_mode = wrqu->mode;
290 ieee80211_start_protocol(ieee);
291 }
292
293out:
294 up(&ieee->wx_sem);
295 return 0;
296}
297
298void ieee80211_wx_sync_scan_wq(struct work_struct *work)
299{
300 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq);
301 short chan;
302 HT_EXTCHNL_OFFSET chan_offset=0;
303 HT_CHANNEL_WIDTH bandwidth=0;
304 int b40M = 0;
305 static int count = 0;
306 chan = ieee->current_network.channel;
307
308#ifdef ENABLE_LPS
309 if (ieee->LeisurePSLeave) {
310 ieee->LeisurePSLeave(ieee);
311 }
312
313 /* notify AP to be in PS mode */
314 ieee80211_sta_ps_send_null_frame(ieee, 1);
315 ieee80211_sta_ps_send_null_frame(ieee, 1);
316#endif
317
318 if (ieee->data_hard_stop)
319 ieee->data_hard_stop(ieee);
320
321 ieee80211_stop_send_beacons(ieee);
322
323 ieee->state = IEEE80211_LINKED_SCANNING;
324 ieee->link_change(ieee);
325 ieee->InitialGainHandler(ieee, IG_Backup);
326 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) {
327 b40M = 1;
328 chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
329 bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz;
330 printk("Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth);
331 ieee->SetBWModeHandler(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
332 }
333 ieee80211_start_scan_syncro(ieee);
334 if (b40M) {
335 printk("Scan in 20M, back to 40M\n");
336 if (chan_offset == HT_EXTCHNL_OFFSET_UPPER)
337 ieee->set_chan(ieee, chan + 2);
338 else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER)
339 ieee->set_chan(ieee, chan - 2);
340 else
341 ieee->set_chan(ieee, chan);
342 ieee->SetBWModeHandler(ieee, bandwidth, chan_offset);
343 } else {
344 ieee->set_chan(ieee, chan);
345 }
346
347 ieee->InitialGainHandler(ieee, IG_Restore);
348 ieee->state = IEEE80211_LINKED;
349 ieee->link_change(ieee);
350
351#ifdef ENABLE_LPS
352 /* Notify AP that I wake up again */
353 ieee80211_sta_ps_send_null_frame(ieee, 0);
354#endif
355
356 // To prevent the immediately calling watch_dog after scan.
357 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
358 {
359 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
360 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
361 }
362 if (ieee->data_hard_resume)
363 ieee->data_hard_resume(ieee);
364
365 if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
366 ieee80211_start_send_beacons(ieee);
367
368 count = 0;
369 up(&ieee->wx_sem);
370
371}
372
373int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
374 union iwreq_data *wrqu, char *b)
375{
376 int ret = 0;
377
378 down(&ieee->wx_sem);
379
380 if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){
381 ret = -1;
382 goto out;
383 }
384
385 if ( ieee->state == IEEE80211_LINKED){
386 queue_work(ieee->wq, &ieee->wx_sync_scan_wq);
387 /* intentionally forget to up sem */
388 return 0;
389 }
390
391out:
392 up(&ieee->wx_sem);
393 return ret;
394}
395
396int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
397 struct iw_request_info *a,
398 union iwreq_data *wrqu, char *extra)
399{
400
401 int ret=0,len;
402 short proto_started;
403 unsigned long flags;
404
405 ieee->sync_scan_hurryup = 1;
406 down(&ieee->wx_sem);
407
408 proto_started = ieee->proto_started;
409
410 if (wrqu->essid.length > IW_ESSID_MAX_SIZE){
411 ret= -E2BIG;
412 goto out;
413 }
414
415 if (ieee->iw_mode == IW_MODE_MONITOR){
416 ret= -1;
417 goto out;
418 }
419
420 if(proto_started){
421 ieee80211_stop_protocol(ieee,true);
422 }
423
424
425 /* this is just to be sure that the GET wx callback
426 * has consisten infos. not needed otherwise
427 */
428 spin_lock_irqsave(&ieee->lock, flags);
429
430 if (wrqu->essid.flags && wrqu->essid.length) {
431 //first flush current network.ssid
432 len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE;
433 strncpy(ieee->current_network.ssid, extra, len+1);
434 ieee->current_network.ssid_len = len+1;
435 ieee->ssid_set = 1;
436 }
437 else{
438 ieee->ssid_set = 0;
439 ieee->current_network.ssid[0] = '\0';
440 ieee->current_network.ssid_len = 0;
441 }
442 spin_unlock_irqrestore(&ieee->lock, flags);
443
444 if (proto_started)
445 ieee80211_start_protocol(ieee);
446out:
447 up(&ieee->wx_sem);
448 return ret;
449}
450
451 int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
452 union iwreq_data *wrqu, char *b)
453{
454
455 wrqu->mode = ieee->iw_mode;
456 return 0;
457}
458
459 int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
460 struct iw_request_info *info,
461 union iwreq_data *wrqu, char *extra)
462{
463
464 int *parms = (int *)extra;
465 int enable = (parms[0] > 0);
466 short prev = ieee->raw_tx;
467
468 down(&ieee->wx_sem);
469
470 if(enable)
471 ieee->raw_tx = 1;
472 else
473 ieee->raw_tx = 0;
474
475 printk(KERN_INFO"raw TX is %s\n",
476 ieee->raw_tx ? "enabled" : "disabled");
477
478 if(ieee->iw_mode == IW_MODE_MONITOR)
479 {
480 if(prev == 0 && ieee->raw_tx){
481 if (ieee->data_hard_resume)
482 ieee->data_hard_resume(ieee);
483
484 netif_carrier_on(ieee->dev);
485 }
486
487 if(prev && ieee->raw_tx == 1)
488 netif_carrier_off(ieee->dev);
489 }
490
491 up(&ieee->wx_sem);
492
493 return 0;
494}
495
496int ieee80211_wx_get_name(struct ieee80211_device *ieee,
497 struct iw_request_info *info,
498 union iwreq_data *wrqu, char *extra)
499{
500 strcpy(wrqu->name, "802.11");
501 if(ieee->modulation & IEEE80211_CCK_MODULATION)
502 strcat(wrqu->name, "b");
503 if(ieee->modulation & IEEE80211_OFDM_MODULATION)
504 strcat(wrqu->name, "g");
505 if (ieee->mode & (IEEE_N_24G | IEEE_N_5G))
506 strcat(wrqu->name, "n");
507 return 0;
508}
509
510
511/* this is mostly stolen from hostap */
512int ieee80211_wx_set_power(struct ieee80211_device *ieee,
513 struct iw_request_info *info,
514 union iwreq_data *wrqu, char *extra)
515{
516 int ret = 0;
517
518 if(
519 (!ieee->sta_wake_up) ||
520 (!ieee->enter_sleep_state) ||
521 (!ieee->ps_is_queue_empty)){
522
523 return -1;
524 }
525
526 down(&ieee->wx_sem);
527
528 if (wrqu->power.disabled){
529 ieee->ps = IEEE80211_PS_DISABLED;
530 goto exit;
531 }
532 if (wrqu->power.flags & IW_POWER_TIMEOUT) {
533 ieee->ps_timeout = wrqu->power.value / 1000;
534 }
535
536 if (wrqu->power.flags & IW_POWER_PERIOD) {
537 ieee->ps_period = wrqu->power.value / 1000;
538 }
539 switch (wrqu->power.flags & IW_POWER_MODE) {
540 case IW_POWER_UNICAST_R:
541 ieee->ps = IEEE80211_PS_UNICAST;
542 break;
543 case IW_POWER_MULTICAST_R:
544 ieee->ps = IEEE80211_PS_MBCAST;
545 break;
546 case IW_POWER_ALL_R:
547 ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST;
548 break;
549
550 case IW_POWER_ON:
551 break;
552
553 default:
554 ret = -EINVAL;
555 goto exit;
556
557 }
558exit:
559 up(&ieee->wx_sem);
560 return ret;
561
562}
563
564/* this is stolen from hostap */
565int ieee80211_wx_get_power(struct ieee80211_device *ieee,
566 struct iw_request_info *info,
567 union iwreq_data *wrqu, char *extra)
568{
569 int ret =0;
570
571 down(&ieee->wx_sem);
572
573 if(ieee->ps == IEEE80211_PS_DISABLED){
574 wrqu->power.disabled = 1;
575 goto exit;
576 }
577
578 wrqu->power.disabled = 0;
579
580 if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
581 wrqu->power.flags = IW_POWER_TIMEOUT;
582 wrqu->power.value = ieee->ps_timeout * 1000;
583 } else {
584 wrqu->power.flags = IW_POWER_PERIOD;
585 wrqu->power.value = ieee->ps_period * 1000;
586 }
587
588 if ((ieee->ps & (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST)) == (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST))
589 wrqu->power.flags |= IW_POWER_ALL_R;
590 else if (ieee->ps & IEEE80211_PS_MBCAST)
591 wrqu->power.flags |= IW_POWER_MULTICAST_R;
592 else
593 wrqu->power.flags |= IW_POWER_UNICAST_R;
594
595exit:
596 up(&ieee->wx_sem);
597 return ret;
598
599}
600
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
new file mode 100644
index 00000000000..424dd48da66
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
@@ -0,0 +1,955 @@
1/******************************************************************************
2
3 Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of version 2 of the GNU General Public License as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 The full GNU General Public License is included in this distribution in the
19 file called LICENSE.
20
21 Contact Information:
22 James P. Ketrenos <ipw2100-admin@linux.intel.com>
23 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24
25******************************************************************************
26
27 Few modifications for Realtek's Wi-Fi drivers by
28 Andrea Merello <andreamrl@tiscali.it>
29
30 A special thanks goes to Realtek for their support !
31
32******************************************************************************/
33
34#include <linux/compiler.h>
35#include <linux/errno.h>
36#include <linux/if_arp.h>
37#include <linux/in6.h>
38#include <linux/in.h>
39#include <linux/ip.h>
40#include <linux/kernel.h>
41#include <linux/module.h>
42#include <linux/netdevice.h>
43#include <linux/pci.h>
44#include <linux/proc_fs.h>
45#include <linux/skbuff.h>
46#include <linux/slab.h>
47#include <linux/tcp.h>
48#include <linux/types.h>
49#include <linux/wireless.h>
50#include <linux/etherdevice.h>
51#include <asm/uaccess.h>
52#include <linux/if_vlan.h>
53
54#include "ieee80211.h"
55
56
57/*
58
59
60802.11 Data Frame
61
62
63802.11 frame_contorl for data frames - 2 bytes
64 ,-----------------------------------------------------------------------------------------.
65bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
66 |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
67val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x |
68 |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
69desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep |
70 | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
71 '-----------------------------------------------------------------------------------------'
72 /\
73 |
74802.11 Data Frame |
75 ,--------- 'ctrl' expands to >-----------'
76 |
77 ,--'---,-------------------------------------------------------------.
78Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
79 |------|------|---------|---------|---------|------|---------|------|
80Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
81 | | tion | (BSSID) | | | ence | data | |
82 `--------------------------------------------------| |------'
83Total: 28 non-data bytes `----.----'
84 |
85 .- 'Frame data' expands to <---------------------------'
86 |
87 V
88 ,---------------------------------------------------.
89Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
90 |------|------|---------|----------|------|---------|
91Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
92 | DSAP | SSAP | | | | Packet |
93 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
94 `-----------------------------------------| |
95Total: 8 non-data bytes `----.----'
96 |
97 .- 'IP Packet' expands, if WEP enabled, to <--'
98 |
99 V
100 ,-----------------------.
101Bytes | 4 | 0-2296 | 4 |
102 |-----|-----------|-----|
103Desc. | IV | Encrypted | ICV |
104 | | IP Packet | |
105 `-----------------------'
106Total: 8 non-data bytes
107
108
109802.3 Ethernet Data Frame
110
111 ,-----------------------------------------.
112Bytes | 6 | 6 | 2 | Variable | 4 |
113 |-------|-------|------|-----------|------|
114Desc. | Dest. | Source| Type | IP Packet | fcs |
115 | MAC | MAC | | | |
116 `-----------------------------------------'
117Total: 18 non-data bytes
118
119In the event that fragmentation is required, the incoming payload is split into
120N parts of size ieee->fts. The first fragment contains the SNAP header and the
121remaining packets are just data.
122
123If encryption is enabled, each fragment payload size is reduced by enough space
124to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
125So if you have 1500 bytes of payload with ieee->fts set to 500 without
126encryption it will take 3 frames. With WEP it will take 4 frames as the
127payload of each frame is reduced to 492 bytes.
128
129* SKB visualization
130*
131* ,- skb->data
132* |
133* | ETHERNET HEADER ,-<-- PAYLOAD
134* | | 14 bytes from skb->data
135* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
136* | | | |
137* |,-Dest.--. ,--Src.---. | | |
138* | 6 bytes| | 6 bytes | | | |
139* v | | | | | |
140* 0 | v 1 | v | v 2
141* 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
142* ^ | ^ | ^ |
143* | | | | | |
144* | | | | `T' <---- 2 bytes for Type
145* | | | |
146* | | '---SNAP--' <-------- 6 bytes for SNAP
147* | |
148* `-IV--' <-------------------- 4 bytes for IV (WEP)
149*
150* SNAP HEADER
151*
152*/
153
154static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
155static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
156
157static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
158{
159 struct ieee80211_snap_hdr *snap;
160 u8 *oui;
161
162 snap = (struct ieee80211_snap_hdr *)data;
163 snap->dsap = 0xaa;
164 snap->ssap = 0xaa;
165 snap->ctrl = 0x03;
166
167 if (h_proto == 0x8137 || h_proto == 0x80f3)
168 oui = P802_1H_OUI;
169 else
170 oui = RFC1042_OUI;
171 snap->oui[0] = oui[0];
172 snap->oui[1] = oui[1];
173 snap->oui[2] = oui[2];
174
175 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
176
177 return SNAP_SIZE + sizeof(u16);
178}
179
180int ieee80211_encrypt_fragment(
181 struct ieee80211_device *ieee,
182 struct sk_buff *frag,
183 int hdr_len)
184{
185 struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
186 int res;
187
188 if (!(crypt && crypt->ops))
189 {
190 printk("=========>%s(), crypt is null\n", __FUNCTION__);
191 return -1;
192 }
193#ifdef CONFIG_IEEE80211_CRYPT_TKIP
194 struct ieee80211_hdr *header;
195
196 if (ieee->tkip_countermeasures &&
197 crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
198 header = (struct ieee80211_hdr *) frag->data;
199 if (net_ratelimit()) {
200 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
201 "TX packet to %pM\n",
202 ieee->dev->name, header->addr1);
203 }
204 return -1;
205 }
206#endif
207 /* To encrypt, frame format is:
208 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
209
210 // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
211 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
212 * call both MSDU and MPDU encryption functions from here. */
213 atomic_inc(&crypt->refcnt);
214 res = 0;
215 if (crypt->ops->encrypt_msdu)
216 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
217 if (res == 0 && crypt->ops->encrypt_mpdu)
218 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
219
220 atomic_dec(&crypt->refcnt);
221 if (res < 0) {
222 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
223 ieee->dev->name, frag->len);
224 ieee->ieee_stats.tx_discards++;
225 return -1;
226 }
227
228 return 0;
229}
230
231
232void ieee80211_txb_free(struct ieee80211_txb *txb) {
233 if (unlikely(!txb))
234 return;
235 kfree(txb);
236}
237
238struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
239 int gfp_mask)
240{
241 struct ieee80211_txb *txb;
242 int i;
243 txb = kmalloc(
244 sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags),
245 gfp_mask);
246 if (!txb)
247 return NULL;
248
249 memset(txb, 0, sizeof(struct ieee80211_txb));
250 txb->nr_frags = nr_frags;
251 txb->frag_size = txb_size;
252
253 for (i = 0; i < nr_frags; i++) {
254 txb->fragments[i] = dev_alloc_skb(txb_size);
255 if (unlikely(!txb->fragments[i])) {
256 i--;
257 break;
258 }
259 memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb));
260 }
261 if (unlikely(i != nr_frags)) {
262 while (i >= 0)
263 dev_kfree_skb_any(txb->fragments[i--]);
264 kfree(txb);
265 return NULL;
266 }
267 return txb;
268}
269
270// Classify the to-be send data packet
271// Need to acquire the sent queue index.
272static int
273ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network)
274{
275 struct ethhdr *eth;
276 struct iphdr *ip;
277 eth = (struct ethhdr *)skb->data;
278 if (eth->h_proto != htons(ETH_P_IP))
279 return 0;
280
281 ip = ip_hdr(skb);
282 switch (ip->tos & 0xfc) {
283 case 0x20:
284 return 2;
285 case 0x40:
286 return 1;
287 case 0x60:
288 return 3;
289 case 0x80:
290 return 4;
291 case 0xa0:
292 return 5;
293 case 0xc0:
294 return 6;
295 case 0xe0:
296 return 7;
297 default:
298 return 0;
299 }
300}
301
302#define SN_LESS(a, b) (((a-b)&0x800)!=0)
303void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc)
304{
305 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
306 PTX_TS_RECORD pTxTs = NULL;
307 struct ieee80211_hdr_1addr* hdr = (struct ieee80211_hdr_1addr*)skb->data;
308
309 if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
310 return;
311 if (!IsQoSDataFrame(skb->data))
312 return;
313
314 if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1))
315 return;
316 //check packet and mode later
317#ifdef TO_DO_LIST
318 if(pTcb->PacketLength >= 4096)
319 return;
320 // For RTL819X, if pairwisekey = wep/tkip, we don't aggrregation.
321 if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
322 return;
323#endif
324
325 if(tcb_desc->bdhcp)// || ieee->CntAfterLink<2)
326 {
327 return;
328 }
329
330
331#if 1
332 if (!ieee->GetNmodeSupportBySecCfg(ieee))
333 {
334 return;
335 }
336#endif
337 if(pHTInfo->bCurrentAMPDUEnable)
338 {
339 if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true))
340 {
341 printk("===>can't get TS\n");
342 return;
343 }
344 if (pTxTs->TxAdmittedBARecord.bValid == false)
345 {
346 //as some AP will refuse our action frame until key handshake has been finished. WB
347 if (ieee->wpa_ie_len && (ieee->pairwise_key_type == KEY_TYPE_NA))
348 ;
349 else
350 TsStartAddBaProcess(ieee, pTxTs);
351 goto FORCED_AGG_SETTING;
352 }
353 else if (pTxTs->bUsingBa == false)
354 {
355 if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
356 pTxTs->bUsingBa = true;
357 else
358 goto FORCED_AGG_SETTING;
359 }
360
361 if (ieee->iw_mode == IW_MODE_INFRA)
362 {
363 tcb_desc->bAMPDUEnable = true;
364 tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor;
365 tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity;
366 }
367 }
368FORCED_AGG_SETTING:
369 switch(pHTInfo->ForcedAMPDUMode )
370 {
371 case HT_AGG_AUTO:
372 break;
373
374 case HT_AGG_FORCE_ENABLE:
375 tcb_desc->bAMPDUEnable = true;
376 tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity;
377 tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor;
378 break;
379
380 case HT_AGG_FORCE_DISABLE:
381 tcb_desc->bAMPDUEnable = false;
382 tcb_desc->ampdu_density = 0;
383 tcb_desc->ampdu_factor = 0;
384 break;
385
386 }
387 return;
388}
389
390extern void ieee80211_qurey_ShortPreambleMode(struct ieee80211_device* ieee, cb_desc* tcb_desc)
391{
392 tcb_desc->bUseShortPreamble = false;
393 if (tcb_desc->data_rate == 2)
394 {//// 1M can only use Long Preamble. 11B spec
395 return;
396 }
397 else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
398 {
399 tcb_desc->bUseShortPreamble = true;
400 }
401 return;
402}
403extern void
404ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, cb_desc *tcb_desc)
405{
406 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
407
408 tcb_desc->bUseShortGI = false;
409
410 if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
411 return;
412
413 if(pHTInfo->bForcedShortGI)
414 {
415 tcb_desc->bUseShortGI = true;
416 return;
417 }
418
419 if((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz)
420 tcb_desc->bUseShortGI = true;
421 else if((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz)
422 tcb_desc->bUseShortGI = true;
423}
424
425void ieee80211_query_BandwidthMode(struct ieee80211_device* ieee, cb_desc *tcb_desc)
426{
427 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
428
429 tcb_desc->bPacketBW = false;
430
431 if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT)
432 return;
433
434 if(tcb_desc->bMulticast || tcb_desc->bBroadcast)
435 return;
436
437 if((tcb_desc->data_rate & 0x80)==0) // If using legacy rate, it shall use 20MHz channel.
438 return;
439 //BandWidthAutoSwitch is for auto switch to 20 or 40 in long distance
440 if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz)
441 tcb_desc->bPacketBW = true;
442 return;
443}
444
445void ieee80211_query_protectionmode(struct ieee80211_device* ieee, cb_desc* tcb_desc, struct sk_buff* skb)
446{
447 // Common Settings
448 tcb_desc->bRTSSTBC = false;
449 tcb_desc->bRTSUseShortGI = false; // Since protection frames are always sent by legacy rate, ShortGI will never be used.
450 tcb_desc->bCTSEnable = false; // Most of protection using RTS/CTS
451 tcb_desc->RTSSC = 0; // 20MHz: Don't care; 40MHz: Duplicate.
452 tcb_desc->bRTSBW = false; // RTS frame bandwidth is always 20MHz
453
454 if(tcb_desc->bBroadcast || tcb_desc->bMulticast)//only unicast frame will use rts/cts
455 return;
456
457 if (is_broadcast_ether_addr(skb->data+16)) //check addr3 as infrastructure add3 is DA.
458 return;
459
460 if (ieee->mode < IEEE_N_24G) //b, g mode
461 {
462 // (1) RTS_Threshold is compared to the MPDU, not MSDU.
463 // (2) If there are more than one frag in this MSDU, only the first frag uses protection frame.
464 // Other fragments are protected by previous fragment.
465 // So we only need to check the length of first fragment.
466 if (skb->len > ieee->rts)
467 {
468 tcb_desc->bRTSEnable = true;
469 tcb_desc->rts_rate = MGN_24M;
470 }
471 else if (ieee->current_network.buseprotection)
472 {
473 // Use CTS-to-SELF in protection mode.
474 tcb_desc->bRTSEnable = true;
475 tcb_desc->bCTSEnable = true;
476 tcb_desc->rts_rate = MGN_24M;
477 }
478 //otherwise return;
479 return;
480 }
481 else
482 {// 11n High throughput case.
483 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
484 while (true)
485 {
486 //check ERP protection
487 if (ieee->current_network.buseprotection)
488 {// CTS-to-SELF
489 tcb_desc->bRTSEnable = true;
490 tcb_desc->bCTSEnable = true;
491 tcb_desc->rts_rate = MGN_24M;
492 break;
493 }
494 //check HT op mode
495 if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT)
496 {
497 u8 HTOpMode = pHTInfo->CurrentOpMode;
498 if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) ||
499 (!pHTInfo->bCurBW40MHz && HTOpMode == 3) )
500 {
501 tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
502 tcb_desc->bRTSEnable = true;
503 break;
504 }
505 }
506 //check rts
507 if (skb->len > ieee->rts)
508 {
509 tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
510 tcb_desc->bRTSEnable = true;
511 break;
512 }
513 //to do list: check MIMO power save condition.
514 //check AMPDU aggregation for TXOP
515 if(tcb_desc->bAMPDUEnable)
516 {
517 tcb_desc->rts_rate = MGN_24M; // Rate is 24Mbps.
518 // According to 8190 design, firmware sends CF-End only if RTS/CTS is enabled. However, it degrads
519 // throughput around 10M, so we disable of this mechanism. 2007.08.03 by Emily
520 tcb_desc->bRTSEnable = false;
521 break;
522 }
523 //check IOT action
524 if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF)
525 {
526 tcb_desc->bCTSEnable = true;
527 tcb_desc->rts_rate = MGN_24M;
528 tcb_desc->bRTSEnable = true;
529 break;
530 }
531 // Totally no protection case!!
532 goto NO_PROTECTION;
533 }
534 }
535 // For test , CTS replace with RTS
536 if( 0 )
537 {
538 tcb_desc->bCTSEnable = true;
539 tcb_desc->rts_rate = MGN_24M;
540 tcb_desc->bRTSEnable = true;
541 }
542 if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
543 tcb_desc->bUseShortPreamble = true;
544 if (ieee->mode == IW_MODE_MASTER)
545 goto NO_PROTECTION;
546 return;
547NO_PROTECTION:
548 tcb_desc->bRTSEnable = false;
549 tcb_desc->bCTSEnable = false;
550 tcb_desc->rts_rate = 0;
551 tcb_desc->RTSSC = 0;
552 tcb_desc->bRTSBW = false;
553}
554
555
556void ieee80211_txrate_selectmode(struct ieee80211_device* ieee, cb_desc* tcb_desc)
557{
558#ifdef TO_DO_LIST
559 if(!IsDataFrame(pFrame))
560 {
561 pTcb->bTxDisableRateFallBack = TRUE;
562 pTcb->bTxUseDriverAssingedRate = TRUE;
563 pTcb->RATRIndex = 7;
564 return;
565 }
566
567 if(pMgntInfo->ForcedDataRate!= 0)
568 {
569 pTcb->bTxDisableRateFallBack = TRUE;
570 pTcb->bTxUseDriverAssingedRate = TRUE;
571 return;
572 }
573#endif
574 if(ieee->bTxDisableRateFallBack)
575 tcb_desc->bTxDisableRateFallBack = true;
576
577 if(ieee->bTxUseDriverAssingedRate)
578 tcb_desc->bTxUseDriverAssingedRate = true;
579 if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate)
580 {
581 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
582 tcb_desc->RATRIndex = 0;
583 }
584}
585
586void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u8* dst)
587{
588 if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst))
589 return;
590 if (IsQoSDataFrame(skb->data)) //we deal qos data only
591 {
592 PTX_TS_RECORD pTS = NULL;
593 if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true))
594 {
595 return;
596 }
597 pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096;
598 }
599}
600
601int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
602{
603 struct ieee80211_device *ieee = netdev_priv(dev);
604 struct ieee80211_txb *txb = NULL;
605 struct ieee80211_hdr_3addrqos *frag_hdr;
606 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
607 unsigned long flags;
608 struct net_device_stats *stats = &ieee->stats;
609 int ether_type = 0, encrypt;
610 int bytes, fc, qos_ctl = 0, hdr_len;
611 struct sk_buff *skb_frag;
612 struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */
613 .duration_id = 0,
614 .seq_ctl = 0,
615 .qos_ctl = 0
616 };
617 u8 dest[ETH_ALEN], src[ETH_ALEN];
618 int qos_actived = ieee->current_network.qos_data.active;
619
620 struct ieee80211_crypt_data* crypt;
621 bool bdhcp =false;
622
623 cb_desc *tcb_desc;
624
625 spin_lock_irqsave(&ieee->lock, flags);
626
627 /* If there is no driver handler to take the TXB, dont' bother
628 * creating it... */
629 if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))||
630 ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
631 printk(KERN_WARNING "%s: No xmit handler.\n",
632 ieee->dev->name);
633 goto success;
634 }
635
636
637 if(likely(ieee->raw_tx == 0)){
638 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
639 printk(KERN_WARNING "%s: skb too small (%d).\n",
640 ieee->dev->name, skb->len);
641 goto success;
642 }
643
644 memset(skb->cb, 0, sizeof(skb->cb));
645 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
646
647 crypt = ieee->crypt[ieee->tx_keyidx];
648
649 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
650 ieee->host_encrypt && crypt && crypt->ops;
651
652 if (!encrypt && ieee->ieee802_1x &&
653 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
654 stats->tx_dropped++;
655 goto success;
656 }
657 #ifdef CONFIG_IEEE80211_DEBUG
658 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
659 struct eapol *eap = (struct eapol *)(skb->data +
660 sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
661 IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
662 eap_get_type(eap->type));
663 }
664 #endif
665
666 // The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time
667 // to prevent DHCP protocol fail
668 if (skb->len > 282){//MINIMUM_DHCP_PACKET_SIZE) {
669 if (ETH_P_IP == ether_type) {// IP header
670 const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14);
671 if (IPPROTO_UDP == ip->protocol) {//FIXME windows is 11 but here UDP in linux kernel is 17.
672 struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
673 if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) ||
674 ((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) {
675 // 68 : UDP BOOTP client
676 // 67 : UDP BOOTP server
677 printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]);
678
679 bdhcp = true;
680#ifdef _RTL8192_EXT_PATCH_
681 ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2; //AMY,090701
682#else
683 ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2;
684#endif
685 }
686 }
687 }else if(ETH_P_ARP == ether_type){// IP ARP packet
688 printk("=================>DHCP Protocol start tx ARP pkt!!\n");
689 bdhcp = true;
690 ieee->LPSDelayCnt = ieee->current_network.tim.tim_count;
691
692 }
693 }
694
695 /* Save source and destination addresses */
696 memcpy(&dest, skb->data, ETH_ALEN);
697 memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
698
699 /* Advance the SKB to the start of the payload */
700 skb_pull(skb, sizeof(struct ethhdr));
701
702 /* Determine total amount of storage required for TXB packets */
703 bytes = skb->len + SNAP_SIZE + sizeof(u16);
704
705 if (encrypt)
706 fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_WEP;
707 else
708
709 fc = IEEE80211_FTYPE_DATA;
710
711 if(qos_actived)
712 fc |= IEEE80211_STYPE_QOS_DATA;
713 else
714 fc |= IEEE80211_STYPE_DATA;
715
716 if (ieee->iw_mode == IW_MODE_INFRA) {
717 fc |= IEEE80211_FCTL_TODS;
718 /* To DS: Addr1 = BSSID, Addr2 = SA,
719 Addr3 = DA */
720 memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
721 memcpy(&header.addr2, &src, ETH_ALEN);
722 memcpy(&header.addr3, &dest, ETH_ALEN);
723 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
724 /* not From/To DS: Addr1 = DA, Addr2 = SA,
725 Addr3 = BSSID */
726 memcpy(&header.addr1, dest, ETH_ALEN);
727 memcpy(&header.addr2, src, ETH_ALEN);
728 memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
729 }
730
731 header.frame_ctl = cpu_to_le16(fc);
732
733 /* Determine fragmentation size based on destination (multicast
734 * and broadcast are not fragmented) */
735 if (is_multicast_ether_addr(header.addr1) ||
736 is_broadcast_ether_addr(header.addr1)) {
737 frag_size = MAX_FRAG_THRESHOLD;
738 qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
739 }
740 else {
741 frag_size = ieee->fts;//default:392
742 qos_ctl = 0;
743 }
744
745 if(qos_actived)
746 {
747 hdr_len = IEEE80211_3ADDR_LEN + 2;
748
749 skb->priority = ieee80211_classify(skb, &ieee->current_network);
750 qos_ctl |= skb->priority; //set in the ieee80211_classify
751 header.qos_ctl = cpu_to_le16(qos_ctl & IEEE80211_QOS_TID);
752 } else {
753 hdr_len = IEEE80211_3ADDR_LEN;
754 }
755 /* Determine amount of payload per fragment. Regardless of if
756 * this stack is providing the full 802.11 header, one will
757 * eventually be affixed to this fragment -- so we must account for
758 * it when determining the amount of payload space. */
759 bytes_per_frag = frag_size - hdr_len;
760 if (ieee->config &
761 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
762 bytes_per_frag -= IEEE80211_FCS_LEN;
763
764 /* Each fragment may need to have room for encryption pre/postfix */
765 if (encrypt)
766 bytes_per_frag -= crypt->ops->extra_prefix_len +
767 crypt->ops->extra_postfix_len;
768
769 /* Number of fragments is the total bytes_per_frag /
770 * payload_per_fragment */
771 nr_frags = bytes / bytes_per_frag;
772 bytes_last_frag = bytes % bytes_per_frag;
773 if (bytes_last_frag)
774 nr_frags++;
775 else
776 bytes_last_frag = bytes_per_frag;
777
778 /* When we allocate the TXB we allocate enough space for the reserve
779 * and full fragment bytes (bytes_per_frag doesn't include prefix,
780 * postfix, header, FCS, etc.) */
781 txb = ieee80211_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC);
782 if (unlikely(!txb)) {
783 printk(KERN_WARNING "%s: Could not allocate TXB\n",
784 ieee->dev->name);
785 goto failed;
786 }
787 txb->encrypted = encrypt;
788 txb->payload_size = bytes;
789
790 if(qos_actived)
791 {
792 txb->queue_index = UP2AC(skb->priority);
793 } else {
794 txb->queue_index = WME_AC_BK;
795 }
796
797
798
799 for (i = 0; i < nr_frags; i++) {
800 skb_frag = txb->fragments[i];
801 tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE);
802 if(qos_actived){
803 skb_frag->priority = skb->priority;//UP2AC(skb->priority);
804 tcb_desc->queue_index = UP2AC(skb->priority);
805 } else {
806 skb_frag->priority = WME_AC_BK;
807 tcb_desc->queue_index = WME_AC_BK;
808 }
809 skb_reserve(skb_frag, ieee->tx_headroom);
810
811 if (encrypt){
812 if (ieee->hwsec_active)
813 tcb_desc->bHwSec = 1;
814 else
815 tcb_desc->bHwSec = 0;
816 skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
817 }
818 else
819 {
820 tcb_desc->bHwSec = 0;
821 }
822 frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
823 memcpy(frag_hdr, &header, hdr_len);
824
825 /* If this is not the last fragment, then add the MOREFRAGS
826 * bit to the frame control */
827 if (i != nr_frags - 1) {
828 frag_hdr->frame_ctl = cpu_to_le16(
829 fc | IEEE80211_FCTL_MOREFRAGS);
830 bytes = bytes_per_frag;
831
832 } else {
833 /* The last fragment takes the remaining length */
834 bytes = bytes_last_frag;
835 }
836
837 if(qos_actived)
838 {
839 // add 1 only indicate to corresponding seq number control 2006/7/12
840 frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
841 } else {
842 frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
843 }
844
845 /* Put a SNAP header on the first fragment */
846 if (i == 0) {
847 ieee80211_put_snap(
848 skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
849 ether_type);
850 bytes -= SNAP_SIZE + sizeof(u16);
851 }
852
853 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
854
855 /* Advance the SKB... */
856 skb_pull(skb, bytes);
857
858 /* Encryption routine will move the header forward in order
859 * to insert the IV between the header and the payload */
860 if (encrypt)
861 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
862 if (ieee->config &
863 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
864 skb_put(skb_frag, 4);
865 }
866
867 if(qos_actived)
868 {
869 if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
870 ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
871 else
872 ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
873 } else {
874 if (ieee->seq_ctrl[0] == 0xFFF)
875 ieee->seq_ctrl[0] = 0;
876 else
877 ieee->seq_ctrl[0]++;
878 }
879 }else{
880 if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
881 printk(KERN_WARNING "%s: skb too small (%d).\n",
882 ieee->dev->name, skb->len);
883 goto success;
884 }
885
886 txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
887 if(!txb){
888 printk(KERN_WARNING "%s: Could not allocate TXB\n",
889 ieee->dev->name);
890 goto failed;
891 }
892
893 txb->encrypted = 0;
894 txb->payload_size = skb->len;
895 memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len);
896 }
897
898 success:
899//WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place.
900 if (txb)
901 {
902 cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
903 tcb_desc->bTxEnableFwCalcDur = 1;
904 if (is_multicast_ether_addr(header.addr1))
905 tcb_desc->bMulticast = 1;
906 if (is_broadcast_ether_addr(header.addr1))
907 tcb_desc->bBroadcast = 1;
908 ieee80211_txrate_selectmode(ieee, tcb_desc);
909 if ( tcb_desc->bMulticast || tcb_desc->bBroadcast)
910 tcb_desc->data_rate = ieee->basic_rate;
911 else
912 tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
913
914 if(bdhcp == true){
915 tcb_desc->data_rate = MGN_1M;
916 tcb_desc->bTxDisableRateFallBack = 1;
917
918 tcb_desc->RATRIndex = 7;
919 tcb_desc->bTxUseDriverAssingedRate = 1;
920 tcb_desc->bdhcp = 1;
921 }
922
923
924 ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc);
925 ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
926 ieee80211_query_HTCapShortGI(ieee, tcb_desc);
927 ieee80211_query_BandwidthMode(ieee, tcb_desc);
928 ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]);
929 ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1);
930 }
931 spin_unlock_irqrestore(&ieee->lock, flags);
932 dev_kfree_skb_any(skb);
933 if (txb) {
934 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){
935 ieee80211_softmac_xmit(txb, ieee);
936 }else{
937 if ((*ieee->hard_start_xmit)(txb, ieee) == 0) {
938 stats->tx_packets++;
939 stats->tx_bytes += txb->payload_size;
940 return 0;
941 }
942 ieee80211_txb_free(txb);
943 }
944 }
945
946 return 0;
947
948 failed:
949 spin_unlock_irqrestore(&ieee->lock, flags);
950 netif_stop_queue(dev);
951 stats->tx_errors++;
952 return 1;
953
954}
955
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
new file mode 100644
index 00000000000..6530d9b6829
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
@@ -0,0 +1,872 @@
1/******************************************************************************
2
3 Copyright(c) 2004 Intel Corporation. All rights reserved.
4
5 Portions of this file are based on the WEP enablement code provided by the
6 Host AP project hostap-drivers v0.1.3
7 Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
8 <jkmaline@cc.hut.fi>
9 Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of version 2 of the GNU General Public License as
13 published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 more details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 59
22 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 The full GNU General Public License is included in this distribution in the
25 file called LICENSE.
26
27 Contact Information:
28 James P. Ketrenos <ipw2100-admin@linux.intel.com>
29 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
30
31******************************************************************************/
32#include <linux/wireless.h>
33#include <linux/version.h>
34#include <linux/kmod.h>
35#include <linux/slab.h>
36#include <linux/module.h>
37
38#include "ieee80211.h"
39
40struct modes_unit {
41 char *mode_string;
42 int mode_size;
43};
44struct modes_unit ieee80211_modes[] = {
45 {"a",1},
46 {"b",1},
47 {"g",1},
48 {"?",1},
49 {"N-24G",5},
50 {"N-5G",4},
51};
52
53#define iwe_stream_add_event_rsl iwe_stream_add_event
54
55#define MAX_CUSTOM_LEN 64
56static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
57 char *start, char *stop,
58 struct ieee80211_network *network,
59 struct iw_request_info *info)
60{
61 char custom[MAX_CUSTOM_LEN];
62 char proto_name[IFNAMSIZ];
63 char *pname = proto_name;
64 char *p;
65 struct iw_event iwe;
66 int i, j;
67 u16 max_rate, rate;
68 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33};
69
70 /* First entry *MUST* be the AP MAC address */
71 iwe.cmd = SIOCGIWAP;
72 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
73 memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
74 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN);
75 /* Remaining entries will be displayed in the order we provide them */
76
77 /* Add the ESSID */
78 iwe.cmd = SIOCGIWESSID;
79 iwe.u.data.flags = 1;
80// if (network->flags & NETWORK_EMPTY_ESSID) {
81 if (network->ssid_len == 0) {
82 iwe.u.data.length = sizeof("<hidden>");
83 start = iwe_stream_add_point(info, start, stop, &iwe, "<hidden>");
84 } else {
85 iwe.u.data.length = min(network->ssid_len, (u8)32);
86 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
87 }
88 /* Add the protocol name */
89 iwe.cmd = SIOCGIWNAME;
90 for(i=0; i<ARRAY_SIZE(ieee80211_modes); i++) {
91 if(network->mode&(1<<i)) {
92 sprintf(pname,ieee80211_modes[i].mode_string,ieee80211_modes[i].mode_size);
93 pname +=ieee80211_modes[i].mode_size;
94 }
95 }
96 *pname = '\0';
97 snprintf(iwe.u.name, IFNAMSIZ, "IEEE802.11%s", proto_name);
98 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_CHAR_LEN);
99 /* Add mode */
100 iwe.cmd = SIOCGIWMODE;
101 if (network->capability &
102 (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) {
103 if (network->capability & WLAN_CAPABILITY_BSS)
104 iwe.u.mode = IW_MODE_MASTER;
105 else
106 iwe.u.mode = IW_MODE_ADHOC;
107 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN);
108 }
109
110 /* Add frequency/channel */
111 iwe.cmd = SIOCGIWFREQ;
112/* iwe.u.freq.m = ieee80211_frequency(network->channel, network->mode);
113 iwe.u.freq.e = 3; */
114 iwe.u.freq.m = network->channel;
115 iwe.u.freq.e = 0;
116 iwe.u.freq.i = 0;
117 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN);
118 /* Add encryption capability */
119 iwe.cmd = SIOCGIWENCODE;
120 if (network->capability & WLAN_CAPABILITY_PRIVACY)
121 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
122 else
123 iwe.u.data.flags = IW_ENCODE_DISABLED;
124 iwe.u.data.length = 0;
125 start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid);
126 /* Add basic and extended rates */
127 max_rate = 0;
128 p = custom;
129 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
130 for (i = 0, j = 0; i < network->rates_len; ) {
131 if (j < network->rates_ex_len &&
132 ((network->rates_ex[j] & 0x7F) <
133 (network->rates[i] & 0x7F)))
134 rate = network->rates_ex[j++] & 0x7F;
135 else
136 rate = network->rates[i++] & 0x7F;
137 if (rate > max_rate)
138 max_rate = rate;
139 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
140 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
141 }
142 for (; j < network->rates_ex_len; j++) {
143 rate = network->rates_ex[j] & 0x7F;
144 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
145 "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
146 if (rate > max_rate)
147 max_rate = rate;
148 }
149
150 if (network->mode >= IEEE_N_24G)//add N rate here;
151 {
152 PHT_CAPABILITY_ELE ht_cap = NULL;
153 bool is40M = false, isShortGI = false;
154 u8 max_mcs = 0;
155 if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4))
156 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4];
157 else
158 ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0];
159 is40M = (ht_cap->ChlWidth)?1:0;
160 isShortGI = (ht_cap->ChlWidth)?
161 ((ht_cap->ShortGI40Mhz)?1:0):
162 ((ht_cap->ShortGI20Mhz)?1:0);
163
164 max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL);
165 rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f];
166 if (rate > max_rate)
167 max_rate = rate;
168 }
169 iwe.cmd = SIOCGIWRATE;
170 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
171 iwe.u.bitrate.value = max_rate * 500000;
172 start = iwe_stream_add_event_rsl(info, start, stop, &iwe,
173 IW_EV_PARAM_LEN);
174 iwe.cmd = IWEVCUSTOM;
175 iwe.u.data.length = p - custom;
176 if (iwe.u.data.length)
177 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
178 /* Add quality statistics */
179 /* TODO: Fix these values... */
180 iwe.cmd = IWEVQUAL;
181 iwe.u.qual.qual = network->stats.signal;
182 iwe.u.qual.level = network->stats.rssi;
183 iwe.u.qual.noise = network->stats.noise;
184 iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK;
185 if (!(network->stats.mask & IEEE80211_STATMASK_RSSI))
186 iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
187 if (!(network->stats.mask & IEEE80211_STATMASK_NOISE))
188 iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
189 if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL))
190 iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID;
191 iwe.u.qual.updated = 7;
192 start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN);
193 iwe.cmd = IWEVCUSTOM;
194 p = custom;
195
196 iwe.u.data.length = p - custom;
197 if (iwe.u.data.length)
198 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
199#if (WIRELESS_EXT < 18)
200 if (ieee->wpa_enabled && network->wpa_ie_len){
201 char buf[MAX_WPA_IE_LEN * 2 + 30];
202 u8 *p = buf;
203 p += sprintf(p, "wpa_ie=");
204 for (i = 0; i < network->wpa_ie_len; i++) {
205 p += sprintf(p, "%02x", network->wpa_ie[i]);
206 }
207
208 memset(&iwe, 0, sizeof(iwe));
209 iwe.cmd = IWEVCUSTOM;
210 iwe.u.data.length = strlen(buf);
211 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
212 }
213
214 if (ieee->wpa_enabled && network->rsn_ie_len){
215 char buf[MAX_WPA_IE_LEN * 2 + 30];
216
217 u8 *p = buf;
218 p += sprintf(p, "rsn_ie=");
219 for (i = 0; i < network->rsn_ie_len; i++) {
220 p += sprintf(p, "%02x", network->rsn_ie[i]);
221 }
222
223 memset(&iwe, 0, sizeof(iwe));
224 iwe.cmd = IWEVCUSTOM;
225 iwe.u.data.length = strlen(buf);
226 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
227 }
228#else
229 memset(&iwe, 0, sizeof(iwe));
230 if (network->wpa_ie_len)
231 {
232 char buf[MAX_WPA_IE_LEN];
233 memcpy(buf, network->wpa_ie, network->wpa_ie_len);
234 iwe.cmd = IWEVGENIE;
235 iwe.u.data.length = network->wpa_ie_len;
236 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
237 }
238 memset(&iwe, 0, sizeof(iwe));
239 if (network->rsn_ie_len)
240 {
241 char buf[MAX_WPA_IE_LEN];
242 memcpy(buf, network->rsn_ie, network->rsn_ie_len);
243 iwe.cmd = IWEVGENIE;
244 iwe.u.data.length = network->rsn_ie_len;
245 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
246 }
247#endif
248
249
250 /* Add EXTRA: Age to display seconds since last beacon/probe response
251 * for given network. */
252 iwe.cmd = IWEVCUSTOM;
253 p = custom;
254 p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
255 " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100));
256 iwe.u.data.length = p - custom;
257 if (iwe.u.data.length)
258 start = iwe_stream_add_point(info, start, stop, &iwe, custom);
259
260 return start;
261}
262
263int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
264 struct iw_request_info *info,
265 union iwreq_data *wrqu, char *extra)
266{
267 struct ieee80211_network *network;
268 unsigned long flags;
269
270 char *ev = extra;
271// char *stop = ev + IW_SCAN_MAX_DATA;
272 char *stop = ev + wrqu->data.length;//IW_SCAN_MAX_DATA;
273 //char *stop = ev + IW_SCAN_MAX_DATA;
274 int i = 0;
275 int err = 0;
276 IEEE80211_DEBUG_WX("Getting scan\n");
277 down(&ieee->wx_sem);
278 spin_lock_irqsave(&ieee->lock, flags);
279
280 list_for_each_entry(network, &ieee->network_list, list) {
281 i++;
282 if((stop-ev)<200)
283 {
284 err = -E2BIG;
285 break;
286 }
287 if (ieee->scan_age == 0 ||
288 time_after(network->last_scanned + ieee->scan_age, jiffies))
289 ev = rtl819x_translate_scan(ieee, ev, stop, network, info);
290 else
291 IEEE80211_DEBUG_SCAN(
292 "Not showing network '%s ("
293 "%pM)' due to age (%lums).\n",
294 escape_essid(network->ssid,
295 network->ssid_len),
296 network->bssid,
297 (jiffies - network->last_scanned) / (HZ / 100));
298 }
299
300 spin_unlock_irqrestore(&ieee->lock, flags);
301 up(&ieee->wx_sem);
302 wrqu->data.length = ev - extra;
303 wrqu->data.flags = 0;
304
305 IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
306
307 return err;
308}
309
310int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
311 struct iw_request_info *info,
312 union iwreq_data *wrqu, char *keybuf)
313{
314 struct iw_point *erq = &(wrqu->encoding);
315 struct net_device *dev = ieee->dev;
316 struct ieee80211_security sec = {
317 .flags = 0
318 };
319 int i, key, key_provided, len;
320 struct ieee80211_crypt_data **crypt;
321
322 IEEE80211_DEBUG_WX("SET_ENCODE\n");
323
324 key = erq->flags & IW_ENCODE_INDEX;
325 if (key) {
326 if (key > WEP_KEYS)
327 return -EINVAL;
328 key--;
329 key_provided = 1;
330 } else {
331 key_provided = 0;
332 key = ieee->tx_keyidx;
333 }
334
335 IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
336 "provided" : "default");
337 crypt = &ieee->crypt[key];
338
339 if (erq->flags & IW_ENCODE_DISABLED) {
340 if (key_provided && *crypt) {
341 IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
342 key);
343 ieee80211_crypt_delayed_deinit(ieee, crypt);
344 } else
345 IEEE80211_DEBUG_WX("Disabling encryption.\n");
346
347 /* Check all the keys to see if any are still configured,
348 * and if no key index was provided, de-init them all */
349 for (i = 0; i < WEP_KEYS; i++) {
350 if (ieee->crypt[i] != NULL) {
351 if (key_provided)
352 break;
353 ieee80211_crypt_delayed_deinit(
354 ieee, &ieee->crypt[i]);
355 }
356 }
357
358 if (i == WEP_KEYS) {
359 sec.enabled = 0;
360 sec.level = SEC_LEVEL_0;
361 sec.flags |= SEC_ENABLED | SEC_LEVEL;
362 }
363
364 goto done;
365 }
366
367
368
369 sec.enabled = 1;
370 sec.flags |= SEC_ENABLED;
371
372 if (*crypt != NULL && (*crypt)->ops != NULL &&
373 strcmp((*crypt)->ops->name, "WEP") != 0) {
374 /* changing to use WEP; deinit previously used algorithm
375 * on this key */
376 ieee80211_crypt_delayed_deinit(ieee, crypt);
377 }
378
379 if (*crypt == NULL) {
380 struct ieee80211_crypt_data *new_crypt;
381
382 /* take WEP into use */
383 new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
384 GFP_KERNEL);
385 if (new_crypt == NULL)
386 return -ENOMEM;
387 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
388 if (!new_crypt->ops)
389 new_crypt->ops = ieee80211_get_crypto_ops("WEP");
390 if (new_crypt->ops)
391 new_crypt->priv = new_crypt->ops->init(key);
392
393 if (!new_crypt->ops || !new_crypt->priv) {
394 kfree(new_crypt);
395 new_crypt = NULL;
396
397 printk(KERN_WARNING "%s: could not initialize WEP: "
398 "load module ieee80211_crypt_wep\n",
399 dev->name);
400 return -EOPNOTSUPP;
401 }
402 *crypt = new_crypt;
403 }
404
405 /* If a new key was provided, set it up */
406 if (erq->length > 0) {
407 len = erq->length <= 5 ? 5 : 13;
408 memcpy(sec.keys[key], keybuf, erq->length);
409 if (len > erq->length)
410 memset(sec.keys[key] + erq->length, 0,
411 len - erq->length);
412 IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
413 key, escape_essid(sec.keys[key], len),
414 erq->length, len);
415 sec.key_sizes[key] = len;
416 (*crypt)->ops->set_key(sec.keys[key], len, NULL,
417 (*crypt)->priv);
418 sec.flags |= (1 << key);
419 /* This ensures a key will be activated if no key is
420 * explicitely set */
421 if (key == sec.active_key)
422 sec.flags |= SEC_ACTIVE_KEY;
423 ieee->tx_keyidx = key;
424
425 } else {
426 len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
427 NULL, (*crypt)->priv);
428 if (len == 0) {
429 /* Set a default key of all 0 */
430 printk("Setting key %d to all zero.\n",
431 key);
432
433 IEEE80211_DEBUG_WX("Setting key %d to all zero.\n",
434 key);
435 memset(sec.keys[key], 0, 13);
436 (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
437 (*crypt)->priv);
438 sec.key_sizes[key] = 13;
439 sec.flags |= (1 << key);
440 }
441
442 /* No key data - just set the default TX key index */
443 if (key_provided) {
444 IEEE80211_DEBUG_WX(
445 "Setting key %d to default Tx key.\n", key);
446 ieee->tx_keyidx = key;
447 sec.active_key = key;
448 sec.flags |= SEC_ACTIVE_KEY;
449 }
450 }
451
452 done:
453 ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
454 ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
455 sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
456 sec.flags |= SEC_AUTH_MODE;
457 IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ?
458 "OPEN" : "SHARED KEY");
459
460 /* For now we just support WEP, so only set that security level...
461 * TODO: When WPA is added this is one place that needs to change */
462 sec.flags |= SEC_LEVEL;
463 sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
464
465 if (ieee->set_security)
466 ieee->set_security(ieee, &sec);
467
468 /* Do not reset port if card is in Managed mode since resetting will
469 * generate new IEEE 802.11 authentication which may end up in looping
470 * with IEEE 802.1X. If your hardware requires a reset after WEP
471 * configuration (for example... Prism2), implement the reset_port in
472 * the callbacks structures used to initialize the 802.11 stack. */
473 if (ieee->reset_on_keychange &&
474 ieee->iw_mode != IW_MODE_INFRA &&
475 ieee->reset_port && ieee->reset_port(ieee)) {
476 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
477 return -EINVAL;
478 }
479 return 0;
480}
481
482int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
483 struct iw_request_info *info,
484 union iwreq_data *wrqu, char *keybuf)
485{
486 struct iw_point *erq = &(wrqu->encoding);
487 int len, key;
488 struct ieee80211_crypt_data *crypt;
489
490 IEEE80211_DEBUG_WX("GET_ENCODE\n");
491
492 if(ieee->iw_mode == IW_MODE_MONITOR)
493 return -1;
494
495 key = erq->flags & IW_ENCODE_INDEX;
496 if (key) {
497 if (key > WEP_KEYS)
498 return -EINVAL;
499 key--;
500 } else
501 key = ieee->tx_keyidx;
502
503 crypt = ieee->crypt[key];
504 erq->flags = key + 1;
505
506 if (crypt == NULL || crypt->ops == NULL) {
507 erq->length = 0;
508 erq->flags |= IW_ENCODE_DISABLED;
509 return 0;
510 }
511#if 0
512 if (strcmp(crypt->ops->name, "WEP") != 0) {
513 /* only WEP is supported with wireless extensions, so just
514 * report that encryption is used */
515 erq->length = 0;
516 erq->flags |= IW_ENCODE_ENABLED;
517 return 0;
518 }
519#endif
520 len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv);
521 erq->length = (len >= 0 ? len : 0);
522
523 erq->flags |= IW_ENCODE_ENABLED;
524
525 if (ieee->open_wep)
526 erq->flags |= IW_ENCODE_OPEN;
527 else
528 erq->flags |= IW_ENCODE_RESTRICTED;
529
530 return 0;
531}
532#if (WIRELESS_EXT >= 18)
533int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
534 struct iw_request_info *info,
535 union iwreq_data *wrqu, char *extra)
536{
537 int ret = 0;
538 struct net_device *dev = ieee->dev;
539 struct iw_point *encoding = &wrqu->encoding;
540 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
541 int i, idx;
542 int group_key = 0;
543 const char *alg;
544 struct ieee80211_crypto_ops *ops;
545 struct ieee80211_crypt_data **crypt;
546
547 struct ieee80211_security sec = {
548 .flags = 0,
549 };
550 idx = encoding->flags & IW_ENCODE_INDEX;
551 if (idx) {
552 if (idx < 1 || idx > WEP_KEYS)
553 return -EINVAL;
554 idx--;
555 } else
556 idx = ieee->tx_keyidx;
557
558 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
559
560 crypt = &ieee->crypt[idx];
561
562 group_key = 1;
563 } else {
564 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
565 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
566 return -EINVAL;
567 if (ieee->iw_mode == IW_MODE_INFRA)
568
569 crypt = &ieee->crypt[idx];
570
571 else
572 return -EINVAL;
573 }
574
575 sec.flags |= SEC_ENABLED;// | SEC_ENCRYPT;
576 if ((encoding->flags & IW_ENCODE_DISABLED) ||
577 ext->alg == IW_ENCODE_ALG_NONE) {
578 if (*crypt)
579 ieee80211_crypt_delayed_deinit(ieee, crypt);
580
581 for (i = 0; i < WEP_KEYS; i++)
582
583 if (ieee->crypt[i] != NULL)
584
585 break;
586
587 if (i == WEP_KEYS) {
588 sec.enabled = 0;
589 // sec.encrypt = 0;
590 sec.level = SEC_LEVEL_0;
591 sec.flags |= SEC_LEVEL;
592 }
593 goto done;
594 }
595
596 sec.enabled = 1;
597 // sec.encrypt = 1;
598#if 0
599 if (group_key ? !ieee->host_mc_decrypt :
600 !(ieee->host_encrypt || ieee->host_decrypt ||
601 ieee->host_encrypt_msdu))
602 goto skip_host_crypt;
603#endif
604 switch (ext->alg) {
605 case IW_ENCODE_ALG_WEP:
606 alg = "WEP";
607 break;
608 case IW_ENCODE_ALG_TKIP:
609 alg = "TKIP";
610 break;
611 case IW_ENCODE_ALG_CCMP:
612 alg = "CCMP";
613 break;
614 default:
615 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
616 dev->name, ext->alg);
617 ret = -EINVAL;
618 goto done;
619 }
620 printk("alg name:%s\n",alg);
621
622 ops = ieee80211_get_crypto_ops(alg);
623 if (ops == NULL)
624 ops = ieee80211_get_crypto_ops(alg);
625 if (ops == NULL) {
626 IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
627 dev->name, ext->alg);
628 printk("========>unknown crypto alg %d\n", ext->alg);
629 ret = -EINVAL;
630 goto done;
631 }
632
633 if (*crypt == NULL || (*crypt)->ops != ops) {
634 struct ieee80211_crypt_data *new_crypt;
635
636 ieee80211_crypt_delayed_deinit(ieee, crypt);
637
638#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
639 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
640#else
641 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
642 memset(new_crypt,0,sizeof(*new_crypt));
643#endif
644 if (new_crypt == NULL) {
645 ret = -ENOMEM;
646 goto done;
647 }
648 new_crypt->ops = ops;
649 if (new_crypt->ops)
650 new_crypt->priv = new_crypt->ops->init(idx);
651 if (new_crypt->priv == NULL) {
652 kfree(new_crypt);
653 ret = -EINVAL;
654 goto done;
655 }
656 *crypt = new_crypt;
657
658 }
659
660 if (ext->key_len > 0 && (*crypt)->ops->set_key &&
661 (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
662 (*crypt)->priv) < 0) {
663 IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
664 printk("key setting failed\n");
665 ret = -EINVAL;
666 goto done;
667 }
668#if 1
669 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
670 ieee->tx_keyidx = idx;
671 sec.active_key = idx;
672 sec.flags |= SEC_ACTIVE_KEY;
673 }
674
675 if (ext->alg != IW_ENCODE_ALG_NONE) {
676 //memcpy(sec.keys[idx], ext->key, ext->key_len);
677 sec.key_sizes[idx] = ext->key_len;
678 sec.flags |= (1 << idx);
679 if (ext->alg == IW_ENCODE_ALG_WEP) {
680 // sec.encode_alg[idx] = SEC_ALG_WEP;
681 sec.flags |= SEC_LEVEL;
682 sec.level = SEC_LEVEL_1;
683 } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
684 // sec.encode_alg[idx] = SEC_ALG_TKIP;
685 sec.flags |= SEC_LEVEL;
686 sec.level = SEC_LEVEL_2;
687 } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
688 // sec.encode_alg[idx] = SEC_ALG_CCMP;
689 sec.flags |= SEC_LEVEL;
690 sec.level = SEC_LEVEL_3;
691 }
692 /* Don't set sec level for group keys. */
693 if (group_key)
694 sec.flags &= ~SEC_LEVEL;
695 }
696#endif
697done:
698 if (ieee->set_security)
699 ieee->set_security(ieee, &sec);
700
701 if (ieee->reset_on_keychange &&
702 ieee->iw_mode != IW_MODE_INFRA &&
703 ieee->reset_port && ieee->reset_port(ieee)) {
704 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
705 return -EINVAL;
706 }
707 return ret;
708}
709
710int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
711 struct iw_request_info *info,
712 union iwreq_data *wrqu, char *extra)
713{
714 struct iw_point *encoding = &wrqu->encoding;
715 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
716 struct ieee80211_crypt_data *crypt;
717 int idx, max_key_len;
718
719 max_key_len = encoding->length - sizeof(*ext);
720 if (max_key_len < 0)
721 return -EINVAL;
722
723 idx = encoding->flags & IW_ENCODE_INDEX;
724 if (idx) {
725 if (idx < 1 || idx > WEP_KEYS)
726 return -EINVAL;
727 idx--;
728 } else
729 idx = ieee->tx_keyidx;
730
731 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
732 ext->alg != IW_ENCODE_ALG_WEP)
733 if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
734 return -EINVAL;
735
736 crypt = ieee->crypt[idx];
737 encoding->flags = idx + 1;
738 memset(ext, 0, sizeof(*ext));
739
740 if (crypt == NULL || crypt->ops == NULL ) {
741 ext->alg = IW_ENCODE_ALG_NONE;
742 ext->key_len = 0;
743 encoding->flags |= IW_ENCODE_DISABLED;
744 } else {
745 if (strcmp(crypt->ops->name, "WEP") == 0 )
746 ext->alg = IW_ENCODE_ALG_WEP;
747 else if (strcmp(crypt->ops->name, "TKIP"))
748 ext->alg = IW_ENCODE_ALG_TKIP;
749 else if (strcmp(crypt->ops->name, "CCMP"))
750 ext->alg = IW_ENCODE_ALG_CCMP;
751 else
752 return -EINVAL;
753 ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv);
754 encoding->flags |= IW_ENCODE_ENABLED;
755 if (ext->key_len &&
756 (ext->alg == IW_ENCODE_ALG_TKIP ||
757 ext->alg == IW_ENCODE_ALG_CCMP))
758 ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
759
760 }
761
762 return 0;
763}
764
765int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
766 struct iw_request_info *info,
767 union iwreq_data *wrqu, char *extra)
768{
769 struct iw_mlme *mlme = (struct iw_mlme *) extra;
770 switch (mlme->cmd) {
771 case IW_MLME_DEAUTH:
772 case IW_MLME_DISASSOC:
773 ieee80211_disassociate(ieee);
774 break;
775 default:
776 return -EOPNOTSUPP;
777 }
778 return 0;
779}
780
781int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
782 struct iw_request_info *info,
783 struct iw_param *data, char *extra)
784{
785 switch (data->flags & IW_AUTH_INDEX) {
786 case IW_AUTH_WPA_VERSION:
787 /*need to support wpa2 here*/
788 break;
789 case IW_AUTH_CIPHER_PAIRWISE:
790 case IW_AUTH_CIPHER_GROUP:
791 case IW_AUTH_KEY_MGMT:
792 /*
793 * * Host AP driver does not use these parameters and allows
794 * * wpa_supplicant to control them internally.
795 * */
796 break;
797 case IW_AUTH_TKIP_COUNTERMEASURES:
798 ieee->tkip_countermeasures = data->value;
799 break;
800 case IW_AUTH_DROP_UNENCRYPTED:
801 ieee->drop_unencrypted = data->value;
802 break;
803
804 case IW_AUTH_80211_AUTH_ALG:
805 if(data->value & IW_AUTH_ALG_SHARED_KEY){
806 ieee->open_wep = 0;
807 ieee->auth_mode = 1;
808 }
809 else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){
810 ieee->open_wep = 1;
811 ieee->auth_mode = 0;
812 }
813 else if(data->value & IW_AUTH_ALG_LEAP){
814 ieee->open_wep = 1;
815 ieee->auth_mode = 2;
816 }
817 else
818 return -EINVAL;
819 break;
820
821#if 1
822 case IW_AUTH_WPA_ENABLED:
823 ieee->wpa_enabled = (data->value)?1:0;
824 break;
825
826#endif
827 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
828 ieee->ieee802_1x = data->value;
829 break;
830 case IW_AUTH_PRIVACY_INVOKED:
831 ieee->privacy_invoked = data->value;
832 break;
833 default:
834 return -EOPNOTSUPP;
835 }
836 return 0;
837}
838#endif
839#if 1
840int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
841{
842 u8 *buf;
843
844 if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
845 {
846 return -EINVAL;
847 }
848
849
850 if (len)
851 {
852 if (len != ie[1]+2)
853 {
854 printk("len:%zu, ie:%d\n", len, ie[1]);
855 return -EINVAL;
856 }
857 buf = kmemdup(ie, len, GFP_KERNEL);
858 if (buf == NULL)
859 return -ENOMEM;
860 kfree(ieee->wpa_ie);
861 ieee->wpa_ie = buf;
862 ieee->wpa_ie_len = len;
863 }
864 else{
865 kfree(ieee->wpa_ie);
866 ieee->wpa_ie = NULL;
867 ieee->wpa_ie_len = 0;
868 }
869 return 0;
870
871}
872#endif
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_BA.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_BA.h
new file mode 100644
index 00000000000..8ddc8bf9dc2
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_BA.h
@@ -0,0 +1,69 @@
1#ifndef _BATYPE_H_
2#define _BATYPE_H_
3
4#define TOTAL_TXBA_NUM 16
5#define TOTAL_RXBA_NUM 16
6
7#define BA_SETUP_TIMEOUT 200
8#define BA_INACT_TIMEOUT 60000
9
10#define BA_POLICY_DELAYED 0
11#define BA_POLICY_IMMEDIATE 1
12
13#define ADDBA_STATUS_SUCCESS 0
14#define ADDBA_STATUS_REFUSED 37
15#define ADDBA_STATUS_INVALID_PARAM 38
16
17#define DELBA_REASON_QSTA_LEAVING 36
18#define DELBA_REASON_END_BA 37
19#define DELBA_REASON_UNKNOWN_BA 38
20#define DELBA_REASON_TIMEOUT 39
21/* whether need define BA Action frames here?
22struct ieee80211_ADDBA_Req{
23 struct ieee80211_header_data header;
24 u8 category;
25 u8
26} __attribute__ ((packed));
27*/
28//Is this need?I put here just to make it easier to define structure BA_RECORD //WB
29typedef union _SEQUENCE_CONTROL{
30 u16 ShortData;
31 struct
32 {
33 u16 FragNum:4;
34 u16 SeqNum:12;
35 }field;
36}SEQUENCE_CONTROL, *PSEQUENCE_CONTROL;
37
38typedef union _BA_PARAM_SET {
39 u8 charData[2];
40 u16 shortData;
41 struct {
42 u16 AMSDU_Support:1;
43 u16 BAPolicy:1;
44 u16 TID:4;
45 u16 BufferSize:10;
46 } field;
47} BA_PARAM_SET, *PBA_PARAM_SET;
48
49typedef union _DELBA_PARAM_SET {
50 u8 charData[2];
51 u16 shortData;
52 struct {
53 u16 Reserved:11;
54 u16 Initiator:1;
55 u16 TID:4;
56 } field;
57} DELBA_PARAM_SET, *PDELBA_PARAM_SET;
58
59typedef struct _BA_RECORD {
60 struct timer_list Timer;
61 u8 bValid;
62 u8 DialogToken;
63 BA_PARAM_SET BaParamSet;
64 u16 BaTimeoutValue;
65 SEQUENCE_CONTROL BaStartSeqCtrl;
66} BA_RECORD, *PBA_RECORD;
67
68#endif //end _BATYPE_H_
69
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
new file mode 100644
index 00000000000..b690cbc5136
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
@@ -0,0 +1,676 @@
1/*
2 * This file is created to process BA Action Frame. According to 802.11 spec,
3 * there are 3 BA action types at all. And as BA is related to TS, this part
4 * need some struture defined in QOS side code. Also TX RX is going to be
5 * resturctured, so how to send ADDBAREQ ADDBARSP and DELBA packet is still
6 * on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
7 */
8#include "ieee80211.h"
9#include "rtl819x_BA.h"
10
11/*
12 * Activate BA entry. And if Time is nozero, start timer.
13 */
14void ActivateBAEntry(struct ieee80211_device* ieee, PBA_RECORD pBA, u16 Time)
15{
16 pBA->bValid = true;
17 if(Time != 0)
18 mod_timer(&pBA->Timer, jiffies + MSECS(Time));
19}
20
21/*
22 * deactivate BA entry, including its timer.
23 */
24void DeActivateBAEntry( struct ieee80211_device* ieee, PBA_RECORD pBA)
25{
26 pBA->bValid = false;
27 del_timer_sync(&pBA->Timer);
28}
29
30/*
31 * deactivete BA entry in Tx Ts, and send DELBA.
32 */
33u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD pTxTs)
34{
35 PBA_RECORD pAdmittedBa = &pTxTs->TxAdmittedBARecord; //These two BA entries must exist in TS structure
36 PBA_RECORD pPendingBa = &pTxTs->TxPendingBARecord;
37 u8 bSendDELBA = false;
38
39 // Delete pending BA
40 if(pPendingBa->bValid)
41 {
42 DeActivateBAEntry(ieee, pPendingBa);
43 bSendDELBA = true;
44 }
45
46 // Delete admitted BA
47 if(pAdmittedBa->bValid)
48 {
49 DeActivateBAEntry(ieee, pAdmittedBa);
50 bSendDELBA = true;
51 }
52
53 return bSendDELBA;
54}
55
56/*
57 * deactivete BA entry in Tx Ts, and send DELBA.
58 */
59u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD pRxTs)
60{
61 PBA_RECORD pBa = &pRxTs->RxAdmittedBARecord;
62 u8 bSendDELBA = false;
63
64 if(pBa->bValid)
65 {
66 DeActivateBAEntry(ieee, pBa);
67 bSendDELBA = true;
68 }
69
70 return bSendDELBA;
71}
72
73/*
74 * reset BA entry
75 */
76void ResetBaEntry( PBA_RECORD pBA)
77{
78 pBA->bValid = false;
79 pBA->BaParamSet.shortData = 0;
80 pBA->BaTimeoutValue = 0;
81 pBA->DialogToken = 0;
82 pBA->BaStartSeqCtrl.ShortData = 0;
83}
84
85/*
86 * construct ADDBAREQ and ADDBARSP frame here together.
87 * return constructed skb to xmit
88 */
89static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
90{
91 struct sk_buff *skb = NULL;
92 struct ieee80211_hdr_3addr* BAReq = NULL;
93 u8* tag = NULL;
94 u16 tmp = 0;
95 u16 len = ieee->tx_headroom + 9;
96 //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2))
97 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
98 if (pBA == NULL||ieee == NULL)
99 {
100 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
101 return NULL;
102 }
103 skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME
104 if (skb == NULL)
105 {
106 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
107 return NULL;
108 }
109
110 memset(skb->data, 0, sizeof( struct ieee80211_hdr_3addr)); //I wonder whether it's necessary. Apparently kernel will not do it when alloc a skb.
111 skb_reserve(skb, ieee->tx_headroom);
112
113 BAReq = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
114
115 memcpy(BAReq->addr1, Dst, ETH_ALEN);
116 memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
117
118 memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
119
120 BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
121
122 //tag += sizeof( struct ieee80211_hdr_3addr); //move to action field
123 tag = (u8*)skb_put(skb, 9);
124 *tag ++= ACT_CAT_BA;
125 *tag ++= type;
126 // Dialog Token
127 *tag ++= pBA->DialogToken;
128
129 if (ACT_ADDBARSP == type)
130 {
131 // Status Code
132 printk("=====>to send ADDBARSP\n");
133 tmp = cpu_to_le16(StatusCode);
134 memcpy(tag, (u8*)&tmp, 2);
135 tag += 2;
136 }
137 // BA Parameter Set
138 tmp = cpu_to_le16(pBA->BaParamSet.shortData);
139 memcpy(tag, (u8*)&tmp, 2);
140 tag += 2;
141 // BA Timeout Value
142 tmp = cpu_to_le16(pBA->BaTimeoutValue);
143 memcpy(tag, (u8*)&tmp, 2);
144 tag += 2;
145
146 if (ACT_ADDBAREQ == type)
147 {
148 // BA Start SeqCtrl
149 memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2);
150 tag += 2;
151 }
152
153 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
154 return skb;
155 //return NULL;
156}
157
158/*
159 * construct DELBA frame
160 */
161static struct sk_buff* ieee80211_DELBA(
162 struct ieee80211_device* ieee,
163 u8* dst,
164 PBA_RECORD pBA,
165 TR_SELECT TxRxSelect,
166 u16 ReasonCode
167 )
168{
169 DELBA_PARAM_SET DelbaParamSet;
170 struct sk_buff *skb = NULL;
171 struct ieee80211_hdr_3addr* Delba = NULL;
172 u8* tag = NULL;
173 u16 tmp = 0;
174 //len = head len + DELBA Parameter Set(2) + Reason Code(2)
175 u16 len = 6 + ieee->tx_headroom;
176
177 if (net_ratelimit())
178 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
179
180 memset(&DelbaParamSet, 0, 2);
181
182 DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0;
183 DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
184
185 skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME
186 if (skb == NULL)
187 {
188 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
189 return NULL;
190 }
191// memset(skb->data, 0, len+sizeof( struct ieee80211_hdr_3addr));
192 skb_reserve(skb, ieee->tx_headroom);
193
194 Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
195
196 memcpy(Delba->addr1, dst, ETH_ALEN);
197 memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
198 memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
199 Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
200
201 tag = (u8*)skb_put(skb, 6);
202
203 *tag ++= ACT_CAT_BA;
204 *tag ++= ACT_DELBA;
205
206 // DELBA Parameter Set
207 tmp = cpu_to_le16(DelbaParamSet.shortData);
208 memcpy(tag, (u8*)&tmp, 2);
209 tag += 2;
210 // Reason Code
211 tmp = cpu_to_le16(ReasonCode);
212 memcpy(tag, (u8*)&tmp, 2);
213 tag += 2;
214
215 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
216 if (net_ratelimit())
217 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __FUNCTION__);
218 return skb;
219}
220
221/*
222 * send ADDBAReq frame out
223 * If any possible, please hide pBA in ieee.
224 * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
225 */
226void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA)
227{
228 struct sk_buff *skb = NULL;
229 skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
230
231 if (skb)
232 {
233 softmac_mgmt_xmit(skb, ieee);
234 //add statistic needed here.
235 //and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
236 //WB
237 }
238 else
239 {
240 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
241 }
242}
243
244/*
245 * send ADDBARSP frame out
246 * If any possible, please hide pBA in ieee.
247 * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
248 */
249void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
250{
251 struct sk_buff *skb = NULL;
252 skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
253 if (skb)
254 {
255 softmac_mgmt_xmit(skb, ieee);
256 //same above
257 }
258 else
259 {
260 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
261 }
262}
263
264/*
265 * send ADDBARSP frame out
266 * If any possible, please hide pBA in ieee.
267 * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
268 */
269void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
270{
271 struct sk_buff *skb = NULL;
272 skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
273 if (skb)
274 {
275 softmac_mgmt_xmit(skb, ieee);
276 //same above
277 }
278 else
279 {
280 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
281 }
282 return ;
283}
284
285int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
286{
287 struct ieee80211_hdr_3addr* req = NULL;
288 u16 rc = 0;
289 u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL;
290 PBA_RECORD pBA = NULL;
291 PBA_PARAM_SET pBaParamSet = NULL;
292 u16* pBaTimeoutVal = NULL;
293 PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
294 PRX_TS_RECORD pTS = NULL;
295
296 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
297 {
298 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
299 return -1;
300 }
301
302 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
303
304 req = ( struct ieee80211_hdr_3addr*) skb->data;
305 tag = (u8*)req;
306 dst = (u8*)(&req->addr2[0]);
307 tag += sizeof( struct ieee80211_hdr_3addr);
308 pDialogToken = tag + 2; //category+action
309 pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken
310 pBaTimeoutVal = (u16*)(tag + 5);
311 pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
312
313 printk("====================>rx ADDBAREQ from :%pM\n", dst);
314//some other capability is not ready now.
315 if( (ieee->current_network.qos_data.active == 0) ||
316 (ieee->pHTInfo->bCurrentHTSupport == false)) //||
317 // (ieee->pStaQos->bEnableRxImmBA == false) )
318 {
319 rc = ADDBA_STATUS_REFUSED;
320 IEEE80211_DEBUG(IEEE80211_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);
321 goto OnADDBAReq_Fail;
322 }
323 // Search for related traffic stream.
324 // If there is no matched TS, reject the ADDBA request.
325 if( !GetTs(
326 ieee,
327 (PTS_COMMON_INFO*)(&pTS),
328 dst,
329 (u8)(pBaParamSet->field.TID),
330 RX_DIR,
331 true) )
332 {
333 rc = ADDBA_STATUS_REFUSED;
334 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
335 goto OnADDBAReq_Fail;
336 }
337 pBA = &pTS->RxAdmittedBARecord;
338 // To Determine the ADDBA Req content
339 // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
340 // I want to check StartSeqCtrl to make sure when we start aggregation!!!
341 //
342 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
343 {
344 rc = ADDBA_STATUS_INVALID_PARAM;
345 IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__);
346 goto OnADDBAReq_Fail;
347 }
348 // Admit the ADDBA Request
349 //
350 DeActivateBAEntry(ieee, pBA);
351 pBA->DialogToken = *pDialogToken;
352 pBA->BaParamSet = *pBaParamSet;
353 pBA->BaTimeoutValue = *pBaTimeoutVal;
354 pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
355 //for half N mode we only aggregate 1 frame
356 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
357 pBA->BaParamSet.field.BufferSize = 1;
358 else
359 pBA->BaParamSet.field.BufferSize = 32;
360 ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue);
361 ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
362
363 // End of procedure.
364 return 0;
365
366OnADDBAReq_Fail:
367 {
368 BA_RECORD BA;
369 BA.BaParamSet = *pBaParamSet;
370 BA.BaTimeoutValue = *pBaTimeoutVal;
371 BA.DialogToken = *pDialogToken;
372 BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
373 ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
374 return 0; //we send RSP out.
375 }
376
377}
378
379int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
380{
381 struct ieee80211_hdr_3addr* rsp = NULL;
382 PBA_RECORD pPendingBA, pAdmittedBA;
383 PTX_TS_RECORD pTS = NULL;
384 u8* dst = NULL, *pDialogToken = NULL, *tag = NULL;
385 u16* pStatusCode = NULL, *pBaTimeoutVal = NULL;
386 PBA_PARAM_SET pBaParamSet = NULL;
387 u16 ReasonCode;
388
389 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
390 {
391 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
392 return -1;
393 }
394 rsp = ( struct ieee80211_hdr_3addr*)skb->data;
395 tag = (u8*)rsp;
396 dst = (u8*)(&rsp->addr2[0]);
397 tag += sizeof( struct ieee80211_hdr_3addr);
398 pDialogToken = tag + 2;
399 pStatusCode = (u16*)(tag + 3);
400 pBaParamSet = (PBA_PARAM_SET)(tag + 5);
401 pBaTimeoutVal = (u16*)(tag + 7);
402
403 // Check the capability
404 // Since we can always receive A-MPDU, we just check if it is under HT mode.
405 if( ieee->current_network.qos_data.active == 0 ||
406 ieee->pHTInfo->bCurrentHTSupport == false ||
407 ieee->pHTInfo->bCurrentAMPDUEnable == false )
408 {
409 IEEE80211_DEBUG(IEEE80211_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);
410 ReasonCode = DELBA_REASON_UNKNOWN_BA;
411 goto OnADDBARsp_Reject;
412 }
413
414
415 //
416 // Search for related TS.
417 // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
418 //
419 if (!GetTs(
420 ieee,
421 (PTS_COMMON_INFO*)(&pTS),
422 dst,
423 (u8)(pBaParamSet->field.TID),
424 TX_DIR,
425 false) )
426 {
427 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
428 ReasonCode = DELBA_REASON_UNKNOWN_BA;
429 goto OnADDBARsp_Reject;
430 }
431
432 pTS->bAddBaReqInProgress = false;
433 pPendingBA = &pTS->TxPendingBARecord;
434 pAdmittedBA = &pTS->TxAdmittedBARecord;
435
436
437 //
438 // Check if related BA is waiting for setup.
439 // If not, reject by sending DELBA frame.
440 //
441 if((pAdmittedBA->bValid==true))
442 {
443 // Since BA is already setup, we ignore all other ADDBA Response.
444 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
445 return -1;
446 }
447 else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
448 {
449 IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
450 ReasonCode = DELBA_REASON_UNKNOWN_BA;
451 goto OnADDBARsp_Reject;
452 }
453 else
454 {
455 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
456 DeActivateBAEntry(ieee, pPendingBA);
457 }
458
459
460 if(*pStatusCode == ADDBA_STATUS_SUCCESS)
461 {
462 //
463 // Determine ADDBA Rsp content here.
464 // We can compare the value of BA parameter set that Peer returned and Self sent.
465 // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
466 //
467 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
468 {
469 // Since this is a kind of ADDBA failed, we delay next ADDBA process.
470 pTS->bAddBaReqDelayed = true;
471 DeActivateBAEntry(ieee, pAdmittedBA);
472 ReasonCode = DELBA_REASON_END_BA;
473 goto OnADDBARsp_Reject;
474 }
475
476
477 //
478 // Admitted condition
479 //
480 pAdmittedBA->DialogToken = *pDialogToken;
481 pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
482 pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
483 pAdmittedBA->BaParamSet = *pBaParamSet;
484 DeActivateBAEntry(ieee, pAdmittedBA);
485 ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
486 }
487 else
488 {
489 // Delay next ADDBA process.
490 pTS->bAddBaReqDelayed = true;
491 }
492
493 // End of procedure
494 return 0;
495
496OnADDBARsp_Reject:
497 {
498 BA_RECORD BA;
499 BA.BaParamSet = *pBaParamSet;
500 ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
501 return 0;
502 }
503
504}
505
506int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
507{
508 struct ieee80211_hdr_3addr* delba = NULL;
509 PDELBA_PARAM_SET pDelBaParamSet = NULL;
510 u16* pReasonCode = NULL;
511 u8* dst = NULL;
512
513 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
514 {
515 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6));
516 return -1;
517 }
518
519 if(ieee->current_network.qos_data.active == 0 ||
520 ieee->pHTInfo->bCurrentHTSupport == false )
521 {
522 IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
523 return -1;
524 }
525
526 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
527 delba = ( struct ieee80211_hdr_3addr*)skb->data;
528 dst = (u8*)(&delba->addr2[0]);
529 delba += sizeof( struct ieee80211_hdr_3addr);
530 pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
531 pReasonCode = (u16*)(delba+4);
532
533 if(pDelBaParamSet->field.Initiator == 1)
534 {
535 PRX_TS_RECORD pRxTs;
536
537 if( !GetTs(
538 ieee,
539 (PTS_COMMON_INFO*)&pRxTs,
540 dst,
541 (u8)pDelBaParamSet->field.TID,
542 RX_DIR,
543 false) )
544 {
545 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for RXTS in %s()\n", __FUNCTION__);
546 return -1;
547 }
548
549 RxTsDeleteBA(ieee, pRxTs);
550 }
551 else
552 {
553 PTX_TS_RECORD pTxTs;
554
555 if(!GetTs(
556 ieee,
557 (PTS_COMMON_INFO*)&pTxTs,
558 dst,
559 (u8)pDelBaParamSet->field.TID,
560 TX_DIR,
561 false) )
562 {
563 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for TXTS in %s()\n", __FUNCTION__);
564 return -1;
565 }
566
567 pTxTs->bUsingBa = false;
568 pTxTs->bAddBaReqInProgress = false;
569 pTxTs->bAddBaReqDelayed = false;
570 del_timer_sync(&pTxTs->TsAddBaTimer);
571 //PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
572 TxTsDeleteBA(ieee, pTxTs);
573 }
574 return 0;
575}
576
577/* ADDBA initiate. This can only be called by TX side. */
578void
579TsInitAddBA(
580 struct ieee80211_device* ieee,
581 PTX_TS_RECORD pTS,
582 u8 Policy,
583 u8 bOverwritePending
584 )
585{
586 PBA_RECORD pBA = &pTS->TxPendingBARecord;
587
588 if(pBA->bValid==true && bOverwritePending==false)
589 return;
590
591 // Set parameters to "Pending" variable set
592 DeActivateBAEntry(ieee, pBA);
593
594 pBA->DialogToken++; // DialogToken: Only keep the latest dialog token
595 pBA->BaParamSet.field.AMSDU_Support = 0; // Do not support A-MSDU with A-MPDU now!!
596 pBA->BaParamSet.field.BAPolicy = Policy; // Policy: Delayed or Immediate
597 pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID; // TID
598 // BufferSize: This need to be set according to A-MPDU vector
599 pBA->BaParamSet.field.BufferSize = 32; // BufferSize: This need to be set according to A-MPDU vector
600 pBA->BaTimeoutValue = 0; // Timeout value: Set 0 to disable Timer
601 pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; // Block Ack will start after 3 packets later.
602
603 ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
604
605 ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
606}
607
608void
609TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
610{
611
612 if(TxRxSelect == TX_DIR)
613 {
614 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
615
616 if(TxTsDeleteBA(ieee, pTxTs))
617 ieee80211_send_DELBA(
618 ieee,
619 pTsCommonInfo->Addr,
620 (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
621 TxRxSelect,
622 DELBA_REASON_END_BA);
623 }
624 else if(TxRxSelect == RX_DIR)
625 {
626 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
627 if(RxTsDeleteBA(ieee, pRxTs))
628 ieee80211_send_DELBA(
629 ieee,
630 pTsCommonInfo->Addr,
631 &pRxTs->RxAdmittedBARecord,
632 TxRxSelect,
633 DELBA_REASON_END_BA );
634 }
635}
636
637/*
638 * BA setup timer
639 * acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
640 */
641void BaSetupTimeOut(unsigned long data)
642{
643 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
644
645 pTxTs->bAddBaReqInProgress = false;
646 pTxTs->bAddBaReqDelayed = true;
647 pTxTs->TxPendingBARecord.bValid = false;
648}
649
650void TxBaInactTimeout(unsigned long data)
651{
652 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
653 struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
654 TxTsDeleteBA(ieee, pTxTs);
655 ieee80211_send_DELBA(
656 ieee,
657 pTxTs->TsCommonInfo.Addr,
658 &pTxTs->TxAdmittedBARecord,
659 TX_DIR,
660 DELBA_REASON_TIMEOUT);
661}
662
663void RxBaInactTimeout(unsigned long data)
664{
665 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data;
666 struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
667
668 RxTsDeleteBA(ieee, pRxTs);
669 ieee80211_send_DELBA(
670 ieee,
671 pRxTs->TsCommonInfo.Addr,
672 &pRxTs->RxAdmittedBARecord,
673 RX_DIR,
674 DELBA_REASON_TIMEOUT);
675}
676
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
new file mode 100644
index 00000000000..56a120cf629
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
@@ -0,0 +1,483 @@
1#ifndef _RTL819XU_HTTYPE_H_
2#define _RTL819XU_HTTYPE_H_
3
4//------------------------------------------------------------
5// The HT Capability element is present in beacons, association request,
6// reassociation request and probe response frames
7//------------------------------------------------------------
8
9//
10// Operation mode value
11//
12#define HT_OPMODE_NO_PROTECT 0
13#define HT_OPMODE_OPTIONAL 1
14#define HT_OPMODE_40MHZ_PROTECT 2
15#define HT_OPMODE_MIXED 3
16
17//
18// MIMO Power Save Setings
19//
20#define MIMO_PS_STATIC 0
21#define MIMO_PS_DYNAMIC 1
22#define MIMO_PS_NOLIMIT 3
23
24
25//
26// There should be 128 bits to cover all of the MCS rates. However, since
27// 8190 does not support too much rates, one integer is quite enough.
28//
29
30#define sHTCLng 4
31
32
33#define HT_SUPPORTED_MCS_1SS_BITMAP 0x000000ff
34#define HT_SUPPORTED_MCS_2SS_BITMAP 0x0000ff00
35#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP HT_MCS_1SS_BITMAP|HT_MCS_1SS_2SS_BITMAP
36
37
38typedef enum _HT_MCS_RATE{
39 HT_MCS0 = 0x00000001,
40 HT_MCS1 = 0x00000002,
41 HT_MCS2 = 0x00000004,
42 HT_MCS3 = 0x00000008,
43 HT_MCS4 = 0x00000010,
44 HT_MCS5 = 0x00000020,
45 HT_MCS6 = 0x00000040,
46 HT_MCS7 = 0x00000080,
47 HT_MCS8 = 0x00000100,
48 HT_MCS9 = 0x00000200,
49 HT_MCS10 = 0x00000400,
50 HT_MCS11 = 0x00000800,
51 HT_MCS12 = 0x00001000,
52 HT_MCS13 = 0x00002000,
53 HT_MCS14 = 0x00004000,
54 HT_MCS15 = 0x00008000,
55 // Do not define MCS32 here although 8190 support MCS32
56}HT_MCS_RATE,*PHT_MCS_RATE;
57
58//
59// Represent Channel Width in HT Capabilities
60//
61typedef enum _HT_CHANNEL_WIDTH{
62 HT_CHANNEL_WIDTH_20 = 0,
63 HT_CHANNEL_WIDTH_20_40 = 1,
64}HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH;
65
66//
67// Represent Extension Channel Offset in HT Capabilities
68// This is available only in 40Mhz mode.
69//
70typedef enum _HT_EXTCHNL_OFFSET{
71 HT_EXTCHNL_OFFSET_NO_EXT = 0,
72 HT_EXTCHNL_OFFSET_UPPER = 1,
73 HT_EXTCHNL_OFFSET_NO_DEF = 2,
74 HT_EXTCHNL_OFFSET_LOWER = 3,
75}HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET;
76
77typedef enum _CHNLOP{
78 CHNLOP_NONE = 0, // No Action now
79 CHNLOP_SCAN = 1, // Scan in progress
80 CHNLOP_SWBW = 2, // Bandwidth switching in progress
81 CHNLOP_SWCHNL = 3, // Software Channel switching in progress
82} CHNLOP, *PCHNLOP;
83
84// Determine if the Channel Operation is in progress
85#define CHHLOP_IN_PROGRESS(_pHTInfo) \
86 ((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE
87
88/*
89typedef union _HT_CAPABILITY{
90 u16 ShortData;
91 u8 CharData[2];
92 struct
93 {
94 u16 AdvCoding:1;
95 u16 ChlWidth:1;
96 u16 MimoPwrSave:2;
97 u16 GreenField:1;
98 u16 ShortGI20Mhz:1;
99 u16 ShortGI40Mhz:1;
100 u16 STBC:1;
101 u16 BeamForm:1;
102 u16 DelayBA:1;
103 u16 MaxAMSDUSize:1;
104 u16 DssCCk:1;
105 u16 PSMP:1;
106 u16 Rsvd:3;
107 }Field;
108}HT_CAPABILITY, *PHT_CAPABILITY;
109
110typedef union _HT_CAPABILITY_MACPARA{
111 u8 ShortData;
112 u8 CharData[1];
113 struct
114 {
115 u8 MaxRxAMPDU:2;
116 u8 MPDUDensity:2;
117 u8 Rsvd:4;
118 }Field;
119}HT_CAPABILITY_MACPARA, *PHT_CAPABILITY_MACPARA;
120*/
121
122typedef enum _HT_ACTION{
123 ACT_RECOMMAND_WIDTH = 0,
124 ACT_MIMO_PWR_SAVE = 1,
125 ACT_PSMP = 2,
126 ACT_SET_PCO_PHASE = 3,
127 ACT_MIMO_CHL_MEASURE = 4,
128 ACT_RECIPROCITY_CORRECT = 5,
129 ACT_MIMO_CSI_MATRICS = 6,
130 ACT_MIMO_NOCOMPR_STEER = 7,
131 ACT_MIMO_COMPR_STEER = 8,
132 ACT_ANTENNA_SELECT = 9,
133} HT_ACTION, *PHT_ACTION;
134
135
136/* 2007/06/07 MH Define sub-carrier mode for 40MHZ. */
137typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier{
138 SC_MODE_DUPLICATE = 0,
139 SC_MODE_LOWER = 1,
140 SC_MODE_UPPER = 2,
141 SC_MODE_FULL40MHZ = 3,
142}HT_BW40_SC_E;
143
144typedef struct _HT_CAPABILITY_ELE{
145
146 //HT capability info
147 u8 AdvCoding:1;
148 u8 ChlWidth:1;
149 u8 MimoPwrSave:2;
150 u8 GreenField:1;
151 u8 ShortGI20Mhz:1;
152 u8 ShortGI40Mhz:1;
153 u8 TxSTBC:1;
154 u8 RxSTBC:2;
155 u8 DelayBA:1;
156 u8 MaxAMSDUSize:1;
157 u8 DssCCk:1;
158 u8 PSMP:1;
159 u8 Rsvd1:1;
160 u8 LSigTxopProtect:1;
161
162 //MAC HT parameters info
163 u8 MaxRxAMPDUFactor:2;
164 u8 MPDUDensity:3;
165 u8 Rsvd2:3;
166
167 //Supported MCS set
168 u8 MCS[16];
169
170
171 //Extended HT Capability Info
172 u16 ExtHTCapInfo;
173
174 //TXBF Capabilities
175 u8 TxBFCap[4];
176
177 //Antenna Selection Capabilities
178 u8 ASCap;
179
180} __attribute__ ((packed)) HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE;
181
182//------------------------------------------------------------
183// The HT Information element is present in beacons
184// Only AP is required to include this element
185//------------------------------------------------------------
186
187typedef struct _HT_INFORMATION_ELE{
188 u8 ControlChl;
189
190 u8 ExtChlOffset:2;
191 u8 RecommemdedTxWidth:1;
192 u8 RIFS:1;
193 u8 PSMPAccessOnly:1;
194 u8 SrvIntGranularity:3;
195
196 u8 OptMode:2;
197 u8 NonGFDevPresent:1;
198 u8 Revd1:5;
199 u8 Revd2:8;
200
201 u8 Rsvd3:6;
202 u8 DualBeacon:1;
203 u8 DualCTSProtect:1;
204
205 u8 SecondaryBeacon:1;
206 u8 LSigTxopProtectFull:1;
207 u8 PcoActive:1;
208 u8 PcoPhase:1;
209 u8 Rsvd4:4;
210
211 u8 BasicMSC[16];
212} __attribute__ ((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE;
213
214//
215// MIMO Power Save control field.
216// This is appear in MIMO Power Save Action Frame
217//
218typedef struct _MIMOPS_CTRL{
219 u8 MimoPsEnable:1;
220 u8 MimoPsMode:1;
221 u8 Reserved:6;
222} MIMOPS_CTRL, *PMIMOPS_CTRL;
223
224typedef enum _HT_SPEC_VER{
225 HT_SPEC_VER_IEEE = 0,
226 HT_SPEC_VER_EWC = 1,
227}HT_SPEC_VER, *PHT_SPEC_VER;
228
229typedef enum _HT_AGGRE_MODE_E{
230 HT_AGG_AUTO = 0,
231 HT_AGG_FORCE_ENABLE = 1,
232 HT_AGG_FORCE_DISABLE = 2,
233}HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E;
234
235//------------------------------------------------------------
236// The Data structure is used to keep HT related variables when card is
237// configured as non-AP STA mode. **Note** Current_xxx should be set
238// to default value in HTInitializeHTInfo()
239//------------------------------------------------------------
240
241typedef struct _RT_HIGH_THROUGHPUT{
242 u8 bEnableHT;
243 u8 bCurrentHTSupport;
244
245 u8 bRegBW40MHz; // Tx 40MHz channel capablity
246 u8 bCurBW40MHz; // Tx 40MHz channel capability
247
248 u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz
249 u8 bCurShortGI40MHz; // Tx Short GI for 40MHz
250
251 u8 bRegShortGI20MHz; // Tx Short GI for 20MHz
252 u8 bCurShortGI20MHz; // Tx Short GI for 20MHz
253
254 u8 bRegSuppCCK; // Tx CCK rate capability
255 u8 bCurSuppCCK; // Tx CCK rate capability
256
257 // 802.11n spec version for "peer"
258 HT_SPEC_VER ePeerHTSpecVer;
259
260
261 // HT related information for "Self"
262 HT_CAPABILITY_ELE SelfHTCap; // This is HT cap element sent to peer STA, which also indicate HT Rx capabilities.
263 HT_INFORMATION_ELE SelfHTInfo; // This is HT info element sent to peer STA, which also indicate HT Rx capabilities.
264
265 // HT related information for "Peer"
266 u8 PeerHTCapBuf[32];
267 u8 PeerHTInfoBuf[32];
268
269
270 // A-MSDU related
271 u8 bAMSDU_Support; // This indicates Tx A-MSDU capability
272 u16 nAMSDU_MaxSize; // This indicates Tx A-MSDU capability
273 u8 bCurrent_AMSDU_Support; // This indicates Tx A-MSDU capability
274 u16 nCurrent_AMSDU_MaxSize; // This indicates Tx A-MSDU capability
275
276
277 // AMPDU related <2006.08.10 Emily>
278 u8 bAMPDUEnable; // This indicate Tx A-MPDU capability
279 u8 bCurrentAMPDUEnable; // This indicate Tx A-MPDU capability
280 u8 AMPDU_Factor; // This indicate Tx A-MPDU capability
281 u8 CurrentAMPDUFactor; // This indicate Tx A-MPDU capability
282 u8 MPDU_Density; // This indicate Tx A-MPDU capability
283 u8 CurrentMPDUDensity; // This indicate Tx A-MPDU capability
284
285 // Forced A-MPDU enable
286 HT_AGGRE_MODE_E ForcedAMPDUMode;
287 u8 ForcedAMPDUFactor;
288 u8 ForcedMPDUDensity;
289
290 // Forced A-MSDU enable
291 HT_AGGRE_MODE_E ForcedAMSDUMode;
292 u16 ForcedAMSDUMaxSize;
293
294 u8 bForcedShortGI;
295
296 u8 CurrentOpMode;
297
298 // MIMO PS related
299 u8 SelfMimoPs;
300 u8 PeerMimoPs;
301
302 // 40MHz Channel Offset settings.
303 HT_EXTCHNL_OFFSET CurSTAExtChnlOffset;
304 u8 bCurTxBW40MHz; // If we use 40 MHz to Tx
305 u8 PeerBandwidth;
306
307 // For Bandwidth Switching
308 u8 bSwBwInProgress;
309 CHNLOP ChnlOp; // software switching channel in progress. By Bruce, 2008-02-15.
310 u8 SwBwStep;
311 //struct timer_list SwBwTimer; //moved to ieee80211_device. as timer_list need include some header file here.
312
313 // For Realtek proprietary A-MPDU factor for aggregation
314 u8 bRegRT2RTAggregation;
315 u8 bCurrentRT2RTAggregation;
316 u8 bCurrentRT2RTLongSlotTime;
317 u8 szRT2RTAggBuffer[10];
318
319 // Rx Reorder control
320 u8 bRegRxReorderEnable;
321 u8 bCurRxReorderEnable;
322 u8 RxReorderWinSize;
323 u8 RxReorderPendingTime;
324 u16 RxReorderDropCounter;
325
326#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
327 u8 UsbTxAggrNum;
328#endif
329#ifdef USB_RX_AGGREGATION_SUPPORT
330 u8 UsbRxFwAggrEn;
331 u8 UsbRxFwAggrPageNum;
332 u8 UsbRxFwAggrPacketNum;
333 u8 UsbRxFwAggrTimeout;
334#endif
335
336 // Add for Broadcom(Linksys) IOT. Joseph
337 u8 bIsPeerBcm;
338
339 // For IOT issue.
340 u8 IOTPeer;
341 u32 IOTAction;
342} __attribute__ ((packed)) RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT;
343
344
345//------------------------------------------------------------
346// The Data structure is used to keep HT related variable for "each Sta"
347// when card is configured as "AP mode"
348//------------------------------------------------------------
349
350typedef struct _RT_HTINFO_STA_ENTRY{
351 u8 bEnableHT;
352
353 u8 bSupportCck;
354
355 u16 AMSDU_MaxSize;
356
357 u8 AMPDU_Factor;
358 u8 MPDU_Density;
359
360 u8 HTHighestOperaRate;
361
362 u8 bBw40MHz;
363
364 u8 MimoPs;
365
366 u8 McsRateSet[16];
367
368
369}RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY;
370
371
372
373
374
375//------------------------------------------------------------
376// The Data structure is used to keep HT related variable for "each AP"
377// when card is configured as "STA mode"
378//------------------------------------------------------------
379
380typedef struct _BSS_HT{
381
382 u8 bdSupportHT;
383
384 // HT related elements
385 u8 bdHTCapBuf[32];
386 u16 bdHTCapLen;
387 u8 bdHTInfoBuf[32];
388 u16 bdHTInfoLen;
389
390 HT_SPEC_VER bdHTSpecVer;
391 //HT_CAPABILITY_ELE bdHTCapEle;
392 //HT_INFORMATION_ELE bdHTInfoEle;
393
394 u8 bdRT2RTAggregation;
395 u8 bdRT2RTLongSlotTime;
396} __attribute__ ((packed)) BSS_HT, *PBSS_HT;
397
398typedef struct _MIMO_RSSI{
399 u32 EnableAntenna;
400 u32 AntennaA;
401 u32 AntennaB;
402 u32 AntennaC;
403 u32 AntennaD;
404 u32 Average;
405}MIMO_RSSI, *PMIMO_RSSI;
406
407typedef struct _MIMO_EVM{
408 u32 EVM1;
409 u32 EVM2;
410}MIMO_EVM, *PMIMO_EVM;
411
412typedef struct _FALSE_ALARM_STATISTICS{
413 u32 Cnt_Parity_Fail;
414 u32 Cnt_Rate_Illegal;
415 u32 Cnt_Crc8_fail;
416 u32 Cnt_all;
417}FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS;
418
419
420extern u8 MCS_FILTER_ALL[16];
421extern u8 MCS_FILTER_1SS[16];
422
423/* 2007/07/11 MH Modify the macro. Becaus STA may link with a N-AP. If we set
424 STA in A/B/G mode and AP is still in N mode. The macro will be wrong. We have
425 to add a macro to judge wireless mode. */
426#define PICK_RATE(_nLegacyRate, _nMcsRate) \
427 (_nMcsRate==0)?(_nLegacyRate&0x7f):(_nMcsRate)
428/* 2007/07/12 MH We only define legacy and HT wireless mode now. */
429#define LEGACY_WIRELESS_MODE IEEE_MODE_MASK
430
431#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \
432 ((WirelessMode & (LEGACY_WIRELESS_MODE))!=0)?\
433 (LegacyRate):\
434 (PICK_RATE(LegacyRate, HTRate))
435
436
437
438// MCS Bw 40 {1~7, 12~15,32}
439#define RATE_ADPT_1SS_MASK 0xFF
440#define RATE_ADPT_2SS_MASK 0xF0 //Skip MCS8~11 because mcs7 > mcs6, 9, 10, 11. 2007.01.16 by Emily
441#define RATE_ADPT_MCS32_MASK 0x01
442
443#define IS_11N_MCS_RATE(rate) (rate&0x80)
444
445typedef enum _HT_AGGRE_SIZE{
446 HT_AGG_SIZE_8K = 0,
447 HT_AGG_SIZE_16K = 1,
448 HT_AGG_SIZE_32K = 2,
449 HT_AGG_SIZE_64K = 3,
450}HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E;
451
452/* Indicate different AP vendor for IOT issue */
453typedef enum _HT_IOT_PEER
454{
455 HT_IOT_PEER_UNKNOWN = 0,
456 HT_IOT_PEER_REALTEK = 1,
457 HT_IOT_PEER_BROADCOM = 2,
458 HT_IOT_PEER_RALINK = 3,
459 HT_IOT_PEER_ATHEROS = 4,
460 HT_IOT_PEER_CISCO= 5,
461 HT_IOT_PEER_MARVELL=6,
462 HT_IOT_PEER_MAX = 7
463}HT_IOT_PEER_E, *PHTIOT_PEER_E;
464
465//
466// IOT Action for different AP
467//
468typedef enum _HT_IOT_ACTION{
469 HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001,
470 HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002,
471 HT_IOT_ACT_DISABLE_MCS14 = 0x00000004,
472 HT_IOT_ACT_DISABLE_MCS15 = 0x00000008,
473 HT_IOT_ACT_DISABLE_ALL_2SS = 0x00000010,
474 HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000020,
475 HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000040,
476 HT_IOT_ACT_CDD_FSYNC = 0x00000080,
477 HT_IOT_ACT_PURE_N_MODE = 0x00000100,
478 HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200,
479 HT_IOT_ACT_NULL_DATA_POWER_SAVING = 0x00800000,
480}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E;
481
482#endif //_RTL819XU_HTTYPE_H_
483
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
new file mode 100644
index 00000000000..f7a9da3ec82
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
@@ -0,0 +1,1732 @@
1
2//As this function is mainly ported from Windows driver, so leave the name little changed. If any confusion caused, tell me. Created by WB. 2008.05.08
3#include "ieee80211.h"
4#include "rtl819x_HT.h"
5u8 MCS_FILTER_ALL[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
6
7u8 MCS_FILTER_1SS[16] = {0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
8
9u16 MCS_DATA_RATE[2][2][77] =
10 { { {13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78 ,104, 156, 208, 234, 260,
11 39, 78, 117, 234, 312, 351, 390, 52, 104, 156, 208, 312, 416, 468, 520,
12 0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182, 182, 208, 156, 195,
13 195, 234, 273, 273, 312, 130, 156, 181, 156, 181, 208, 234, 208, 234, 260, 260,
14 286, 195, 234, 273, 234, 273, 312, 351, 312, 351, 390, 390, 429}, // Long GI, 20MHz
15 {14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289,
16 43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520, 578,
17 0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231, 173, 217,
18 217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260, 231, 260, 289, 289,
19 318, 217, 260, 303, 260, 303, 347, 390, 347, 390, 433, 433, 477} }, // Short GI, 20MHz
20 { {27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540,
21 81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648, 864, 972, 1080,
22 12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324, 378, 378, 432, 324, 405,
23 405, 486, 567, 567, 648, 270, 324, 378, 324, 378, 432, 486, 432, 486, 540, 540,
24 594, 405, 486, 567, 486, 567, 648, 729, 648, 729, 810, 810, 891}, // Long GI, 40MHz
25 {30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600,
26 90, 180, 270, 360, 540, 720, 810, 900, 120, 240, 360, 480, 720, 960, 1080, 1200,
27 13, 180, 240, 300, 270, 360, 450, 240, 300, 300, 360, 420, 420, 480, 360, 450,
28 450, 540, 630, 630, 720, 300, 360, 420, 360, 420, 480, 540, 480, 540, 600, 600,
29 660, 450, 540, 630, 540, 630, 720, 810, 720, 810, 900, 900, 990} } // Short GI, 40MHz
30 };
31
32static const u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf};
33static const u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70};
34static const u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e};
35//static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f};
36static const u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f};
37static const u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf};
38static const u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc};
39static const u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e};
40static const u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
41static const u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0};
42static const u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
43static const u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
44
45// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Should we put the
46// code in other place??
47//static u8 WIFI_CISCO_G_AP[3] = {0x00, 0x40, 0x96};
48/********************************************************************************************************************
49 *function: This function update default settings in pHTInfo structure
50 * input: PRT_HIGH_THROUGHPUT pHTInfo
51 * output: none
52 * return: none
53 * notice: These value need be modified if any changes.
54 * *****************************************************************************************************************/
55void HTUpdateDefaultSetting(struct ieee80211_device* ieee)
56{
57 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
58
59 // ShortGI support
60 pHTInfo->bRegShortGI20MHz= 1;
61 pHTInfo->bRegShortGI40MHz= 1;
62
63 // 40MHz channel support
64 pHTInfo->bRegBW40MHz = 1;
65
66 // CCK rate support in 40MHz channel
67 if(pHTInfo->bRegBW40MHz)
68 pHTInfo->bRegSuppCCK = 1;
69 else
70 pHTInfo->bRegSuppCCK = true;
71
72 // AMSDU related
73 pHTInfo->nAMSDU_MaxSize = 7935UL;
74 pHTInfo->bAMSDU_Support = 0;
75
76 // AMPDU related
77 pHTInfo->bAMPDUEnable = 1;
78 pHTInfo->AMPDU_Factor = 2; //// 0: 2n13(8K), 1:2n14(16K), 2:2n15(32K), 3:2n16(64k)
79 pHTInfo->MPDU_Density = 0;// 0: No restriction, 1: 1/8usec, 2: 1/4usec, 3: 1/2usec, 4: 1usec, 5: 2usec, 6: 4usec, 7:8usec
80
81 // MIMO Power Save
82 pHTInfo->SelfMimoPs = 3;// 0: Static Mimo Ps, 1: Dynamic Mimo Ps, 3: No Limitation, 2: Reserved(Set to 3 automatically.)
83 if(pHTInfo->SelfMimoPs == 2)
84 pHTInfo->SelfMimoPs = 3;
85 // 8190 only. Assign rate operation mode to firmware
86 ieee->bTxDisableRateFallBack = 0;
87 ieee->bTxUseDriverAssingedRate = 0;
88
89#ifdef TO_DO_LIST
90 // 8190 only. Assign duration operation mode to firmware
91 pMgntInfo->bTxEnableFwCalcDur = (BOOLEAN)pNdisCommon->bRegTxEnableFwCalcDur;
92#endif
93 // 8190 only, Realtek proprietary aggregation mode
94 // Set MPDUDensity=2, 1: Set MPDUDensity=2(32k) for Realtek AP and set MPDUDensity=0(8k) for others
95 pHTInfo->bRegRT2RTAggregation = 1;//0: Set MPDUDensity=2, 1: Set MPDUDensity=2(32k) for Realtek AP and set MPDUDensity=0(8k) for others
96
97 // For Rx Reorder Control
98 pHTInfo->bRegRxReorderEnable = 1;
99 pHTInfo->RxReorderWinSize = 64;
100 pHTInfo->RxReorderPendingTime = 30;
101
102#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
103 pHTInfo->UsbTxAggrNum = 4;
104#endif
105#ifdef USB_RX_AGGREGATION_SUPPORT
106 pHTInfo->UsbRxFwAggrEn = 1;
107 pHTInfo->UsbRxFwAggrPageNum = 24;
108 pHTInfo->UsbRxFwAggrPacketNum = 8;
109 pHTInfo->UsbRxFwAggrTimeout = 16; ////usb rx FW aggregation timeout threshold.It's in units of 64us
110#endif
111
112
113}
114/********************************************************************************************************************
115 *function: This function print out each field on HT capability IE mainly from (Beacon/ProbeRsp/AssocReq)
116 * input: u8* CapIE //Capability IE to be printed out
117 * u8* TitleString //mainly print out caller function
118 * output: none
119 * return: none
120 * notice: Driver should not print out this message by default.
121 * *****************************************************************************************************************/
122void HTDebugHTCapability(u8* CapIE, u8* TitleString )
123{
124
125 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily
126 PHT_CAPABILITY_ELE pCapELE;
127
128 if(!memcmp(CapIE, EWC11NHTCap, sizeof(EWC11NHTCap)))
129 {
130 //EWC IE
131 IEEE80211_DEBUG(IEEE80211_DL_HT, "EWC IE in %s()\n", __FUNCTION__);
132 pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[4]);
133 }else
134 pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[0]);
135
136 IEEE80211_DEBUG(IEEE80211_DL_HT, "<Log HT Capability>. Called by %s\n", TitleString );
137
138 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupported Channel Width = %s\n", (pCapELE->ChlWidth)?"20MHz": "20/40MHz");
139 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport Short GI for 20M = %s\n", (pCapELE->ShortGI20Mhz)?"YES": "NO");
140 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport Short GI for 40M = %s\n", (pCapELE->ShortGI40Mhz)?"YES": "NO");
141 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport TX STBC = %s\n", (pCapELE->TxSTBC)?"YES": "NO");
142 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMax AMSDU Size = %s\n", (pCapELE->MaxAMSDUSize)?"3839": "7935");
143 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSupport CCK in 20/40 mode = %s\n", (pCapELE->DssCCk)?"YES": "NO");
144 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMax AMPDU Factor = %d\n", pCapELE->MaxRxAMPDUFactor);
145 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMPDU Density = %d\n", pCapELE->MPDUDensity);
146 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tMCS Rate Set = [%x][%x][%x][%x][%x]\n", pCapELE->MCS[0],\
147 pCapELE->MCS[1], pCapELE->MCS[2], pCapELE->MCS[3], pCapELE->MCS[4]);
148}
149/********************************************************************************************************************
150 *function: This function print out each field on HT Information IE mainly from (Beacon/ProbeRsp)
151 * input: u8* InfoIE //Capability IE to be printed out
152 * u8* TitleString //mainly print out caller function
153 * output: none
154 * return: none
155 * notice: Driver should not print out this message by default.
156 * *****************************************************************************************************************/
157void HTDebugHTInfo(u8* InfoIE, u8* TitleString)
158{
159
160 static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; // For 11n EWC definition, 2007.07.17, by Emily
161 PHT_INFORMATION_ELE pHTInfoEle;
162
163 if(!memcmp(InfoIE, EWC11NHTInfo, sizeof(EWC11NHTInfo)))
164 {
165 // Not EWC IE
166 IEEE80211_DEBUG(IEEE80211_DL_HT, "EWC IE in %s()\n", __FUNCTION__);
167 pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[4]);
168 }else
169 pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[0]);
170
171
172 IEEE80211_DEBUG(IEEE80211_DL_HT, "<Log HT Information Element>. Called by %s\n", TitleString);
173
174 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tPrimary channel = %d\n", pHTInfoEle->ControlChl);
175 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tSenondary channel =");
176 switch(pHTInfoEle->ExtChlOffset)
177 {
178 case 0:
179 IEEE80211_DEBUG(IEEE80211_DL_HT, "Not Present\n");
180 break;
181 case 1:
182 IEEE80211_DEBUG(IEEE80211_DL_HT, "Upper channel\n");
183 break;
184 case 2:
185 IEEE80211_DEBUG(IEEE80211_DL_HT, "Reserved. Eooro!!!\n");
186 break;
187 case 3:
188 IEEE80211_DEBUG(IEEE80211_DL_HT, "Lower Channel\n");
189 break;
190 }
191 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tRecommended channel width = %s\n", (pHTInfoEle->RecommemdedTxWidth)?"20Mhz": "40Mhz");
192
193 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tOperation mode for protection = ");
194 switch(pHTInfoEle->OptMode)
195 {
196 case 0:
197 IEEE80211_DEBUG(IEEE80211_DL_HT, "No Protection\n");
198 break;
199 case 1:
200 IEEE80211_DEBUG(IEEE80211_DL_HT, "HT non-member protection mode\n");
201 break;
202 case 2:
203 IEEE80211_DEBUG(IEEE80211_DL_HT, "Suggest to open protection\n");
204 break;
205 case 3:
206 IEEE80211_DEBUG(IEEE80211_DL_HT, "HT mixed mode\n");
207 break;
208 }
209
210 IEEE80211_DEBUG(IEEE80211_DL_HT, "\tBasic MCS Rate Set = [%x][%x][%x][%x][%x]\n", pHTInfoEle->BasicMSC[0],\
211 pHTInfoEle->BasicMSC[1], pHTInfoEle->BasicMSC[2], pHTInfoEle->BasicMSC[3], pHTInfoEle->BasicMSC[4]);
212}
213
214/*
215* Return: true if station in half n mode and AP supports 40 bw
216*/
217bool IsHTHalfNmode40Bandwidth(struct ieee80211_device* ieee)
218{
219 bool retValue = false;
220 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
221
222 if(pHTInfo->bCurrentHTSupport == false ) // wireless is n mode
223 retValue = false;
224 else if(pHTInfo->bRegBW40MHz == false) // station supports 40 bw
225 retValue = false;
226 else if (!ieee->GetHalfNmodeSupportByAPsHandler(ieee)) // station in half n mode
227 retValue = false;
228 else if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ChlWidth) // ap support 40 bw
229 retValue = true;
230 else
231 retValue = false;
232
233 return retValue;
234}
235
236bool IsHTHalfNmodeSGI(struct ieee80211_device* ieee, bool is40MHz)
237{
238 bool retValue = false;
239 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
240
241 if(pHTInfo->bCurrentHTSupport == false ) // wireless is n mode
242 retValue = false;
243 else if (!ieee->GetHalfNmodeSupportByAPsHandler(ieee)) // station in half n mode
244 retValue = false;
245 else if(is40MHz) // ap support 40 bw
246 {
247 if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI40Mhz) // ap support 40 bw short GI
248 retValue = true;
249 else
250 retValue = false;
251 }
252 else
253 {
254 if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI20Mhz) // ap support 40 bw short GI
255 retValue = true;
256 else
257 retValue = false;
258 }
259
260 return retValue;
261}
262
263u16 HTHalfMcsToDataRate(struct ieee80211_device* ieee, u8 nMcsRate)
264{
265
266 u8 is40MHz;
267 u8 isShortGI;
268
269 is40MHz = (IsHTHalfNmode40Bandwidth(ieee))?1:0;
270 isShortGI = (IsHTHalfNmodeSGI(ieee, is40MHz))? 1:0;
271
272 return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate&0x7f)];
273}
274
275
276u16 HTMcsToDataRate( struct ieee80211_device* ieee, u8 nMcsRate)
277{
278 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
279
280 u8 is40MHz = (pHTInfo->bCurBW40MHz)?1:0;
281 u8 isShortGI = (pHTInfo->bCurBW40MHz)?
282 ((pHTInfo->bCurShortGI40MHz)?1:0):
283 ((pHTInfo->bCurShortGI20MHz)?1:0);
284 return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate&0x7f)];
285}
286
287/********************************************************************************************************************
288 *function: This function returns current datarate.
289 * input: struct ieee80211_device* ieee
290 * u8 nDataRate
291 * output: none
292 * return: tx rate
293 * notice: quite unsure about how to use this function //wb
294 * *****************************************************************************************************************/
295u16 TxCountToDataRate( struct ieee80211_device* ieee, u8 nDataRate)
296{
297 //PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
298 u16 CCKOFDMRate[12] = {0x02 , 0x04 , 0x0b , 0x16 , 0x0c , 0x12 , 0x18 , 0x24 , 0x30 , 0x48 , 0x60 , 0x6c};
299 u8 is40MHz = 0;
300 u8 isShortGI = 0;
301
302 if(nDataRate < 12)
303 {
304 return CCKOFDMRate[nDataRate];
305 }
306 else
307 {
308 if (nDataRate >= 0x10 && nDataRate <= 0x1f)//if(nDataRate > 11 && nDataRate < 28 )
309 {
310 is40MHz = 0;
311 isShortGI = 0;
312
313 // nDataRate = nDataRate - 12;
314 }
315 else if(nDataRate >=0x20 && nDataRate <= 0x2f ) //(27, 44)
316 {
317 is40MHz = 1;
318 isShortGI = 0;
319
320 //nDataRate = nDataRate - 28;
321 }
322 else if(nDataRate >= 0x30 && nDataRate <= 0x3f ) //(43, 60)
323 {
324 is40MHz = 0;
325 isShortGI = 1;
326
327 //nDataRate = nDataRate - 44;
328 }
329 else if(nDataRate >= 0x40 && nDataRate <= 0x4f ) //(59, 76)
330 {
331 is40MHz = 1;
332 isShortGI = 1;
333
334 //nDataRate = nDataRate - 60;
335 }
336 return MCS_DATA_RATE[is40MHz][isShortGI][nDataRate&0xf];
337 }
338}
339
340
341
342bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee)
343{
344 bool retValue = false;
345 struct ieee80211_network* net = &ieee->current_network;
346#if 0
347 if(ieee->bHalfNMode == false)
348 retValue = false;
349 else
350#endif
351 if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
352 (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
353 (memcmp(net->bssid, PCI_RALINK, 3)==0) ||
354 (memcmp(net->bssid, EDIMAX_RALINK, 3)==0) ||
355 (memcmp(net->bssid, AIRLINK_RALINK, 3)==0) ||
356 (net->ralink_cap_exist))
357 retValue = true;
358 else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
359 (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
360 (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
361 //(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ||
362 (net->broadcom_cap_exist))
363 retValue = true;
364 else if(net->bssht.bdRT2RTAggregation)
365 retValue = true;
366 else
367 retValue = false;
368
369 return retValue;
370}
371
372/********************************************************************************************************************
373 *function: This function returns peer IOT.
374 * input: struct ieee80211_device* ieee
375 * output: none
376 * return:
377 * notice:
378 * *****************************************************************************************************************/
379void HTIOTPeerDetermine(struct ieee80211_device* ieee)
380{
381 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
382 struct ieee80211_network* net = &ieee->current_network;
383 if(net->bssht.bdRT2RTAggregation)
384 pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK;
385 else if(net->broadcom_cap_exist){
386 pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
387 }
388 else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
389 (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
390 (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)){//||
391 //(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ){
392 pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
393 }
394 else if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
395 (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
396 (memcmp(net->bssid, PCI_RALINK, 3)==0) ||
397 (memcmp(net->bssid, EDIMAX_RALINK, 3)==0) ||
398 (memcmp(net->bssid, AIRLINK_RALINK, 3)==0) ||
399 net->ralink_cap_exist)
400 pHTInfo->IOTPeer = HT_IOT_PEER_RALINK;
401 else if((net->atheros_cap_exist )|| (memcmp(net->bssid, DLINK_ATHEROS, 3) == 0))
402 pHTInfo->IOTPeer = HT_IOT_PEER_ATHEROS;
403 else if(memcmp(net->bssid, CISCO_BROADCOM, 3)==0)
404 pHTInfo->IOTPeer = HT_IOT_PEER_CISCO;
405 else if ((memcmp(net->bssid, LINKSYS_MARVELL_4400N, 3) == 0) ||
406 net->marvell_cap_exist){
407 pHTInfo->IOTPeer = HT_IOT_PEER_MARVELL;
408 }
409 else
410 pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
411
412 IEEE80211_DEBUG(IEEE80211_DL_IOT, "Joseph debug!! IOTPEER: %x\n", pHTInfo->IOTPeer);
413}
414/********************************************************************************************************************
415 *function: Check whether driver should declare received rate up to MCS13 only since some chipset is not good
416 * at receiving MCS14~15 frame from some AP.
417 * input: struct ieee80211_device* ieee
418 * u8 * PeerMacAddr
419 * output: none
420 * return: return 1 if driver should declare MCS13 only(otherwise return 0)
421 * *****************************************************************************************************************/
422u8 HTIOTActIsDisableMCS14(struct ieee80211_device* ieee, u8* PeerMacAddr)
423{
424 u8 ret = 0;
425#if 0
426 // Apply for 819u only
427#if (HAL_CODE_BASE==RTL8192 && DEV_BUS_TYPE==USB_INTERFACE)
428 if((memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0) ||
429 (memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)
430 )
431 {
432 ret = 1;
433 }
434
435
436 if(pHTInfo->bCurrentRT2RTAggregation)
437 {
438 // The parameter of pHTInfo->bCurrentRT2RTAggregation must be decided previously
439 ret = 1;
440 }
441#endif
442#endif
443 return ret;
444 }
445
446u8 HTIOTActIsForcedCTS2Self(struct ieee80211_device *ieee, struct ieee80211_network *network)
447{
448 u8 retValue = 0;
449 //if(network->marvell_cap_exist)
450 if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL)
451 {
452 retValue = 1;
453 }
454
455 return retValue;
456}
457
458
459/**
460* Function: HTIOTActIsDisableMCS15
461*
462* Overview: Check whether driver should declare capability of receiving MCS15
463*
464* Input:
465* PADAPTER Adapter,
466*
467* Output: None
468* Return: true if driver should disable MCS15
469* 2008.04.15 Emily
470*/
471bool HTIOTActIsDisableMCS15(struct ieee80211_device* ieee)
472{
473 bool retValue = false;
474
475#ifdef TODO
476 // Apply for 819u only
477#if (HAL_CODE_BASE==RTL8192)
478
479#if (DEV_BUS_TYPE == USB_INTERFACE)
480 // Alway disable MCS15 by Jerry Chang's request.by Emily, 2008.04.15
481 retValue = true;
482#elif (DEV_BUS_TYPE == PCI_INTERFACE)
483 // Enable MCS15 if the peer is Cisco AP. by Emily, 2008.05.12
484// if(pBssDesc->bCiscoCapExist)
485// retValue = false;
486// else
487 retValue = false;
488#endif
489#endif
490#endif
491 // Jerry Chang suggest that 8190 1x2 does not need to disable MCS15
492
493 return retValue;
494}
495
496/**
497* Function: HTIOTActIsDisableMCSTwoSpatialStream
498*
499* Overview: Check whether driver should declare capability of receiving All 2 ss packets
500*
501* Input:
502* PADAPTER Adapter,
503*
504* Output: None
505* Return: true if driver should disable all two spatial stream packet
506* 2008.04.21 Emily
507*/
508bool HTIOTActIsDisableMCSTwoSpatialStream(struct ieee80211_device* ieee, u8 *PeerMacAddr)
509{
510 bool retValue = false;
511
512#ifdef TODO
513 // Apply for 819u only
514//#if (HAL_CODE_BASE==RTL8192)
515
516 //This rule only apply to Belkin(Ralink) AP
517 if(IS_UNDER_11N_AES_MODE(Adapter))
518 {
519 if((PlatformCompareMemory(PeerMacAddr, BELKINF5D8233V1_RALINK, 3)==0) ||
520 (PlatformCompareMemory(PeerMacAddr, PCI_RALINK, 3)==0) ||
521 (PlatformCompareMemory(PeerMacAddr, EDIMAX_RALINK, 3)==0))
522 {
523 //Set True to disable this function. Disable by default, Emily, 2008.04.23
524 retValue = false;
525 }
526 }
527
528//#endif
529#endif
530 return retValue;
531}
532
533/********************************************************************************************************************
534 *function: Check whether driver should disable EDCA turbo mode
535 * input: struct ieee80211_device* ieee
536 * u8* PeerMacAddr
537 * output: none
538 * return: return 1 if driver should disable EDCA turbo mode(otherwise return 0)
539 * *****************************************************************************************************************/
540u8 HTIOTActIsDisableEDCATurbo(struct ieee80211_device* ieee, u8* PeerMacAddr)
541{
542 u8 retValue = false; // default enable EDCA Turbo mode.
543 // Set specific EDCA parameter for different AP in DM handler.
544
545 return retValue;
546#if 0
547 if((memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0)||
548 (memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
549 (memcmp(PeerMacAddr, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
550 (memcmp(PeerMacAddr, NETGEAR834Bv2_BROADCOM, 3)==0))
551
552 {
553 retValue = 1; //Linksys disable EDCA turbo mode
554 }
555
556 return retValue;
557#endif
558}
559
560/********************************************************************************************************************
561 *function: Check whether we need to use OFDM to sned MGNT frame for broadcom AP
562 * input: struct ieee80211_network *network //current network we live
563 * output: none
564 * return: return 1 if true
565 * *****************************************************************************************************************/
566u8 HTIOTActIsMgntUseCCK6M(struct ieee80211_network *network)
567{
568 u8 retValue = 0;
569
570 // 2008/01/25 MH Judeg if we need to use OFDM to sned MGNT frame for broadcom AP.
571 // 2008/01/28 MH We must prevent that we select null bssid to link.
572
573 if(network->broadcom_cap_exist)
574 {
575 retValue = 1;
576 }
577
578 return retValue;
579}
580
581u8 HTIOTActIsCCDFsync(u8* PeerMacAddr)
582{
583 u8 retValue = 0;
584 if( (memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0) ||
585 (memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0) ||
586 (memcmp(PeerMacAddr, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3) ==0))
587 {
588 retValue = 1;
589 }
590
591 return retValue;
592}
593
594//
595// Send null data for to tell AP that we are awake.
596//
597bool
598HTIOTActIsNullDataPowerSaving(struct ieee80211_device* ieee,struct ieee80211_network *network)
599{
600 bool retValue = false;
601
602 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
603 {
604 if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) // ||(pBssDesc->Vender == HT_IOT_PEER_ATHEROS && pBssDesc->SubTypeOfVender == HT_IOT_PEER_ATHEROS_DIR635))
605 return true;
606
607 }
608 return retValue;
609}
610
611void HTResetIOTSetting(
612 PRT_HIGH_THROUGHPUT pHTInfo
613)
614{
615 pHTInfo->IOTAction = 0;
616 pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
617}
618
619
620/********************************************************************************************************************
621 *function: Construct Capablility Element in Beacon... if HTEnable is turned on
622 * input: struct ieee80211_device* ieee
623 * u8* posHTCap //pointer to store Capability Ele
624 * u8* len //store length of CE
625 * u8 IsEncrypt //whether encrypt, needed further
626 * output: none
627 * return: none
628 * notice: posHTCap can't be null and should be initialized before.
629 * *****************************************************************************************************************/
630void HTConstructCapabilityElement(struct ieee80211_device* ieee, u8* posHTCap, u8* len, u8 IsEncrypt)
631{
632 PRT_HIGH_THROUGHPUT pHT = ieee->pHTInfo;
633 PHT_CAPABILITY_ELE pCapELE = NULL;
634 //u8 bIsDeclareMCS13;
635
636 if ((posHTCap == NULL) || (pHT == NULL))
637 {
638 IEEE80211_DEBUG(IEEE80211_DL_ERR, "posHTCap or pHTInfo can't be null in HTConstructCapabilityElement()\n");
639 return;
640 }
641 memset(posHTCap, 0, *len);
642 if(pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)
643 {
644 u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily
645 memcpy(posHTCap, EWC11NHTCap, sizeof(EWC11NHTCap));
646 pCapELE = (PHT_CAPABILITY_ELE)&(posHTCap[4]);
647 }else
648 {
649 pCapELE = (PHT_CAPABILITY_ELE)posHTCap;
650 }
651
652
653 //HT capability info
654 pCapELE->AdvCoding = 0; // This feature is not supported now!!
655 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
656 {
657 pCapELE->ChlWidth = 0;
658 }
659 else
660 {
661 pCapELE->ChlWidth = (pHT->bRegBW40MHz?1:0);
662 }
663
664// pCapELE->ChlWidth = (pHT->bRegBW40MHz?1:0);
665 pCapELE->MimoPwrSave = pHT->SelfMimoPs;
666 pCapELE->GreenField = 0; // This feature is not supported now!!
667 pCapELE->ShortGI20Mhz = 1; // We can receive Short GI!!
668 pCapELE->ShortGI40Mhz = 1; // We can receive Short GI!!
669 //DbgPrint("TX HT cap/info ele BW=%d SG20=%d SG40=%d\n\r",
670 //pCapELE->ChlWidth, pCapELE->ShortGI20Mhz, pCapELE->ShortGI40Mhz);
671 pCapELE->TxSTBC = 1;
672 pCapELE->RxSTBC = 0;
673 pCapELE->DelayBA = 0; // Do not support now!!
674 pCapELE->MaxAMSDUSize = (MAX_RECEIVE_BUFFER_SIZE>=7935)?1:0;
675 pCapELE->DssCCk = ((pHT->bRegBW40MHz)?(pHT->bRegSuppCCK?1:0):0);
676 pCapELE->PSMP = 0; // Do not support now!!
677 pCapELE->LSigTxopProtect = 0; // Do not support now!!
678
679
680 //MAC HT parameters info
681 // TODO: Nedd to take care of this part
682 IEEE80211_DEBUG(IEEE80211_DL_HT, "TX HT cap/info ele BW=%d MaxAMSDUSize:%d DssCCk:%d\n", pCapELE->ChlWidth, pCapELE->MaxAMSDUSize, pCapELE->DssCCk);
683
684 if( IsEncrypt)
685 {
686 pCapELE->MPDUDensity = 7; // 8us
687 pCapELE->MaxRxAMPDUFactor = 2; // 2 is for 32 K and 3 is 64K
688 }
689 else
690 {
691 pCapELE->MaxRxAMPDUFactor = 3; // 2 is for 32 K and 3 is 64K
692 pCapELE->MPDUDensity = 0; // no density
693 }
694
695 //Supported MCS set
696 memcpy(pCapELE->MCS, ieee->Regdot11HTOperationalRateSet, 16);
697 if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS15)
698 pCapELE->MCS[1] &= 0x7f;
699
700 if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS14)
701 pCapELE->MCS[1] &= 0xbf;
702
703 if(pHT->IOTAction & HT_IOT_ACT_DISABLE_ALL_2SS)
704 pCapELE->MCS[1] &= 0x00;
705
706 // 2008.06.12
707 // For RTL819X, if pairwisekey = wep/tkip, ap is ralink, we support only MCS0~7.
708 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
709 {
710 int i;
711 for(i = 1; i< 16; i++)
712 pCapELE->MCS[i] = 0;
713 }
714
715 //Extended HT Capability Info
716 memset(&pCapELE->ExtHTCapInfo, 0, 2);
717
718
719 //TXBF Capabilities
720 memset(pCapELE->TxBFCap, 0, 4);
721
722 //Antenna Selection Capabilities
723 pCapELE->ASCap = 0;
724//add 2 to give space for element ID and len when construct frames
725 if(pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)
726 *len = 30 + 2;
727 else
728 *len = 26 + 2;
729}
730/********************************************************************************************************************
731 *function: Construct Information Element in Beacon... if HTEnable is turned on
732 * input: struct ieee80211_device* ieee
733 * u8* posHTCap //pointer to store Information Ele
734 * u8* len //store len of
735 * u8 IsEncrypt //whether encrypt, needed further
736 * output: none
737 * return: none
738 * notice: posHTCap can't be null and be initialized before. only AP and IBSS sta should do this
739 * *****************************************************************************************************************/
740void HTConstructInfoElement(struct ieee80211_device* ieee, u8* posHTInfo, u8* len, u8 IsEncrypt)
741{
742 PRT_HIGH_THROUGHPUT pHT = ieee->pHTInfo;
743 PHT_INFORMATION_ELE pHTInfoEle = (PHT_INFORMATION_ELE)posHTInfo;
744 if ((posHTInfo == NULL) || (pHTInfoEle == NULL))
745 {
746 IEEE80211_DEBUG(IEEE80211_DL_ERR, "posHTInfo or pHTInfoEle can't be null in HTConstructInfoElement()\n");
747 return;
748 }
749
750 memset(posHTInfo, 0, *len);
751 if ( (ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER)) //ap mode is not currently supported
752 {
753 pHTInfoEle->ControlChl = ieee->current_network.channel;
754 pHTInfoEle->ExtChlOffset = ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT:
755 (ieee->current_network.channel<=6)?
756 HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);
757 pHTInfoEle->RecommemdedTxWidth = pHT->bRegBW40MHz;
758 pHTInfoEle->RIFS = 0;
759 pHTInfoEle->PSMPAccessOnly = 0;
760 pHTInfoEle->SrvIntGranularity = 0;
761 pHTInfoEle->OptMode = pHT->CurrentOpMode;
762 pHTInfoEle->NonGFDevPresent = 0;
763 pHTInfoEle->DualBeacon = 0;
764 pHTInfoEle->SecondaryBeacon = 0;
765 pHTInfoEle->LSigTxopProtectFull = 0;
766 pHTInfoEle->PcoActive = 0;
767 pHTInfoEle->PcoPhase = 0;
768
769 memset(pHTInfoEle->BasicMSC, 0, 16);
770
771
772 *len = 22 + 2; //same above
773
774 }
775 else
776 {
777 //STA should not generate High Throughput Information Element
778 *len = 0;
779 }
780}
781
782/*
783 * According to experiment, Realtek AP to STA (based on rtl8190) may achieve best performance
784 * if both STA and AP set limitation of aggregation size to 32K, that is, set AMPDU density to 2
785 * (Ref: IEEE 11n specification). However, if Realtek STA associates to other AP, STA should set
786 * limitation of aggregation size to 8K, otherwise, performance of traffic stream from STA to AP
787 * will be much less than the traffic stream from AP to STA if both of the stream runs concurrently
788 * at the same time.
789 *
790 * Frame Format
791 * Element ID Length OUI Type1 Reserved
792 * 1 byte 1 byte 3 bytes 1 byte 1 byte
793 *
794 * OUI = 0x00, 0xe0, 0x4c,
795 * Type = 0x02
796 * Reserved = 0x00
797 *
798 * 2007.8.21 by Emily
799*/
800/********************************************************************************************************************
801 *function: Construct Information Element in Beacon... in RT2RT condition
802 * input: struct ieee80211_device* ieee
803 * u8* posRT2RTAgg //pointer to store Information Ele
804 * u8* len //store len
805 * output: none
806 * return: none
807 * notice:
808 * *****************************************************************************************************************/
809void HTConstructRT2RTAggElement(struct ieee80211_device* ieee, u8* posRT2RTAgg, u8* len)
810{
811 if (posRT2RTAgg == NULL) {
812 IEEE80211_DEBUG(IEEE80211_DL_ERR, "posRT2RTAgg can't be null in HTConstructRT2RTAggElement()\n");
813 return;
814 }
815 memset(posRT2RTAgg, 0, *len);
816 *posRT2RTAgg++ = 0x00;
817 *posRT2RTAgg++ = 0xe0;
818 *posRT2RTAgg++ = 0x4c;
819 *posRT2RTAgg++ = 0x02;
820 *posRT2RTAgg++ = 0x01;
821 *posRT2RTAgg = 0x10;//*posRT2RTAgg = 0x02;
822
823 if(ieee->bSupportRemoteWakeUp) {
824 *posRT2RTAgg |= 0x08;//RT_HT_CAP_USE_WOW;
825 }
826
827 *len = 6 + 2;
828 return;
829#ifdef TODO
830#if(HAL_CODE_BASE == RTL8192 && DEV_BUS_TYPE == USB_INTERFACE)
831 /*
832 //Emily. If it is required to Ask Realtek AP to send AMPDU during AES mode, enable this
833 section of code.
834 if(IS_UNDER_11N_AES_MODE(Adapter))
835 {
836 posRT2RTAgg->Octet[5] |=RT_HT_CAP_USE_AMPDU;
837 }else
838 {
839 posRT2RTAgg->Octet[5] &= 0xfb;
840 }
841 */
842
843#else
844 // Do Nothing
845#endif
846
847 posRT2RTAgg->Length = 6;
848#endif
849
850
851
852
853}
854
855
856/********************************************************************************************************************
857 *function: Pick the right Rate Adaptive table to use
858 * input: struct ieee80211_device* ieee
859 * u8* pOperateMCS //A pointer to MCS rate bitmap
860 * return: always we return true
861 * notice:
862 * *****************************************************************************************************************/
863u8 HT_PickMCSRate(struct ieee80211_device* ieee, u8* pOperateMCS)
864{
865 u8 i;
866 if (pOperateMCS == NULL)
867 {
868 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pOperateMCS can't be null in HT_PickMCSRate()\n");
869 return false;
870 }
871
872 switch(ieee->mode)
873 {
874 case IEEE_A:
875 case IEEE_B:
876 case IEEE_G:
877 //legacy rate routine handled at selectedrate
878
879 //no MCS rate
880 for(i=0;i<=15;i++){
881 pOperateMCS[i] = 0;
882 }
883 break;
884
885 case IEEE_N_24G: //assume CCK rate ok
886 case IEEE_N_5G:
887 // Legacy part we only use 6, 5.5,2,1 for N_24G and 6 for N_5G.
888 // Legacy part shall be handled at SelectRateSet().
889
890 //HT part
891 // TODO: may be different if we have different number of antenna
892 pOperateMCS[0] &=RATE_ADPT_1SS_MASK; //support MCS 0~7
893 pOperateMCS[1] &=RATE_ADPT_2SS_MASK;
894 pOperateMCS[3] &=RATE_ADPT_MCS32_MASK;
895 break;
896
897 //should never reach here
898 default:
899
900 break;
901
902 }
903
904 return true;
905}
906
907/*
908* Description:
909* This function will get the highest speed rate in input MCS set.
910*
911* /param Adapter Pionter to Adapter entity
912* pMCSRateSet Pointer to MCS rate bitmap
913* pMCSFilter Pointer to MCS rate filter
914*
915* /return Highest MCS rate included in pMCSRateSet and filtered by pMCSFilter.
916*
917*/
918/********************************************************************************************************************
919 *function: This function will get the highest speed rate in input MCS set.
920 * input: struct ieee80211_device* ieee
921 * u8* pMCSRateSet //Pointer to MCS rate bitmap
922 * u8* pMCSFilter //Pointer to MCS rate filter
923 * return: Highest MCS rate included in pMCSRateSet and filtered by pMCSFilter
924 * notice:
925 * *****************************************************************************************************************/
926u8 HTGetHighestMCSRate(struct ieee80211_device* ieee, u8* pMCSRateSet, u8* pMCSFilter)
927{
928 u8 i, j;
929 u8 bitMap;
930 u8 mcsRate = 0;
931 u8 availableMcsRate[16];
932 if (pMCSRateSet == NULL || pMCSFilter == NULL)
933 {
934 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pMCSRateSet or pMCSFilter can't be null in HTGetHighestMCSRate()\n");
935 return false;
936 }
937 for(i=0; i<16; i++)
938 availableMcsRate[i] = pMCSRateSet[i] & pMCSFilter[i];
939
940 for(i = 0; i < 16; i++)
941 {
942 if(availableMcsRate[i] != 0)
943 break;
944 }
945 if(i == 16)
946 return false;
947
948 for(i = 0; i < 16; i++)
949 {
950 if(availableMcsRate[i] != 0)
951 {
952 bitMap = availableMcsRate[i];
953 for(j = 0; j < 8; j++)
954 {
955 if((bitMap%2) != 0)
956 {
957 if(HTMcsToDataRate(ieee, (8*i+j)) > HTMcsToDataRate(ieee, mcsRate))
958 mcsRate = (8*i+j);
959 }
960 bitMap = bitMap>>1;
961 }
962 }
963 }
964 return (mcsRate|0x80);
965}
966
967
968
969/*
970**
971**1.Filter our operation rate set with AP's rate set
972**2.shall reference channel bandwidth, STBC, Antenna number
973**3.generate rate adative table for firmware
974**David 20060906
975**
976** \pHTSupportedCap: the connected STA's supported rate Capability element
977*/
978u8 HTFilterMCSRate( struct ieee80211_device* ieee, u8* pSupportMCS, u8* pOperateMCS)
979{
980
981 u8 i=0;
982
983 // filter out operational rate set not supported by AP, the lenth of it is 16
984 for(i=0;i<=15;i++){
985 pOperateMCS[i] = ieee->Regdot11HTOperationalRateSet[i]&pSupportMCS[i];
986 }
987
988
989 // TODO: adjust our operational rate set according to our channel bandwidth, STBC and Antenna number
990
991 // TODO: fill suggested rate adaptive rate index and give firmware info using Tx command packet
992 // we also shall suggested the first start rate set according to our singal strength
993 HT_PickMCSRate(ieee, pOperateMCS);
994
995 // For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7.
996 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
997 pOperateMCS[1] = 0;
998
999 //
1000 // For RTL819X, we support only MCS0~15.
1001 // And also, we do not know how to use MCS32 now.
1002 //
1003 for(i=2; i<=15; i++)
1004 pOperateMCS[i] = 0;
1005
1006 return true;
1007}
1008void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
1009void HTOnAssocRsp(struct ieee80211_device *ieee)
1010{
1011 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1012 PHT_CAPABILITY_ELE pPeerHTCap = NULL;
1013 PHT_INFORMATION_ELE pPeerHTInfo = NULL;
1014 u16 nMaxAMSDUSize = 0;
1015 u8* pMcsFilter = NULL;
1016
1017 static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily
1018 static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; // For 11n EWC definition, 2007.07.17, by Emily
1019
1020 if( pHTInfo->bCurrentHTSupport == false )
1021 {
1022 IEEE80211_DEBUG(IEEE80211_DL_ERR, "<=== HTOnAssocRsp(): HT_DISABLE\n");
1023 return;
1024 }
1025 IEEE80211_DEBUG(IEEE80211_DL_HT, "===> HTOnAssocRsp_wq(): HT_ENABLE\n");
1026// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, pHTInfo->PeerHTCapBuf, sizeof(HT_CAPABILITY_ELE));
1027// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, pHTInfo->PeerHTInfoBuf, sizeof(HT_INFORMATION_ELE));
1028
1029// HTDebugHTCapability(pHTInfo->PeerHTCapBuf,"HTOnAssocRsp_wq");
1030// HTDebugHTInfo(pHTInfo->PeerHTInfoBuf,"HTOnAssocRsp_wq");
1031 //
1032 if(!memcmp(pHTInfo->PeerHTCapBuf,EWC11NHTCap, sizeof(EWC11NHTCap)))
1033 pPeerHTCap = (PHT_CAPABILITY_ELE)(&pHTInfo->PeerHTCapBuf[4]);
1034 else
1035 pPeerHTCap = (PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf);
1036
1037 if(!memcmp(pHTInfo->PeerHTInfoBuf, EWC11NHTInfo, sizeof(EWC11NHTInfo)))
1038 pPeerHTInfo = (PHT_INFORMATION_ELE)(&pHTInfo->PeerHTInfoBuf[4]);
1039 else
1040 pPeerHTInfo = (PHT_INFORMATION_ELE)(pHTInfo->PeerHTInfoBuf);
1041
1042
1043 ////////////////////////////////////////////////////////
1044 // Configurations:
1045 ////////////////////////////////////////////////////////
1046 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_HT, pPeerHTCap, sizeof(HT_CAPABILITY_ELE));
1047// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_HT, pPeerHTInfo, sizeof(HT_INFORMATION_ELE));
1048 // Config Supported Channel Width setting
1049 //
1050 HTSetConnectBwMode(ieee, (HT_CHANNEL_WIDTH)(pPeerHTCap->ChlWidth), (HT_EXTCHNL_OFFSET)(pPeerHTInfo->ExtChlOffset));
1051
1052// if(pHTInfo->bCurBW40MHz == true)
1053 pHTInfo->bCurTxBW40MHz = ((pPeerHTInfo->RecommemdedTxWidth == 1)?true:false);
1054
1055 //
1056 // Update short GI/ long GI setting
1057 //
1058 // TODO:
1059 pHTInfo->bCurShortGI20MHz=
1060 ((pHTInfo->bRegShortGI20MHz)?((pPeerHTCap->ShortGI20Mhz==1)?true:false):false);
1061 pHTInfo->bCurShortGI40MHz=
1062 ((pHTInfo->bRegShortGI40MHz)?((pPeerHTCap->ShortGI40Mhz==1)?true:false):false);
1063
1064 //
1065 // Config TX STBC setting
1066 //
1067 // TODO:
1068
1069 //
1070 // Config DSSS/CCK mode in 40MHz mode
1071 //
1072 // TODO:
1073 pHTInfo->bCurSuppCCK =
1074 ((pHTInfo->bRegSuppCCK)?((pPeerHTCap->DssCCk==1)?true:false):false);
1075
1076
1077 //
1078 // Config and configure A-MSDU setting
1079 //
1080 pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
1081 if (ieee->rtllib_ap_sec_type &&
1082 (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))){
1083 if( (pHTInfo->IOTPeer== HT_IOT_PEER_ATHEROS) ||
1084 (pHTInfo->IOTPeer == HT_IOT_PEER_UNKNOWN) )
1085 pHTInfo->bCurrentAMPDUEnable = false;
1086 }
1087
1088
1089 nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize==0)?3839:7935;
1090
1091 if(pHTInfo->nAMSDU_MaxSize > nMaxAMSDUSize )
1092 pHTInfo->nCurrent_AMSDU_MaxSize = nMaxAMSDUSize;
1093 else
1094 pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
1095
1096
1097 //
1098 // Config A-MPDU setting
1099 //
1100 pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
1101
1102 // <1> Decide AMPDU Factor
1103
1104 // By Emily
1105 if(!pHTInfo->bRegRT2RTAggregation)
1106 {
1107 // Decide AMPDU Factor according to protocol handshake
1108 if(pHTInfo->AMPDU_Factor > pPeerHTCap->MaxRxAMPDUFactor)
1109 pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
1110 else
1111 pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
1112
1113 }else
1114 {
1115 // Set MPDU density to 2 to Realtek AP, and set it to 0 for others
1116 // Replace MPDU factor declared in original association response frame format. 2007.08.20 by Emily
1117#if 0
1118 osTmp= PacketGetElement( asocpdu, EID_Vendor, OUI_SUB_REALTEK_AGG, OUI_SUBTYPE_DONT_CARE);
1119 if(osTmp.Length >= 5) //00:e0:4c:02:00
1120#endif
1121 if (ieee->current_network.bssht.bdRT2RTAggregation)
1122 {
1123 if( ieee->pairwise_key_type != KEY_TYPE_NA)
1124 // Realtek may set 32k in security mode and 64k for others
1125 pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
1126 else
1127 pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_64K;
1128 }else
1129 {
1130 if(pPeerHTCap->MaxRxAMPDUFactor < HT_AGG_SIZE_32K)
1131 pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor;
1132 else
1133 pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_32K;
1134 }
1135 }
1136
1137 // <2> Set AMPDU Minimum MPDU Start Spacing
1138 // 802.11n 3.0 section 9.7d.3
1139#if 1
1140 if(pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity)
1141 pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
1142 else
1143 pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity;
1144 if(ieee->pairwise_key_type != KEY_TYPE_NA )
1145 pHTInfo->CurrentMPDUDensity = 7; // 8us
1146#else
1147 if(pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity)
1148 pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
1149 else
1150 pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity;
1151#endif
1152 // Force TX AMSDU
1153
1154 // Lanhsin: mark for tmp to avoid deauth by ap from s3
1155 //if(memcmp(pMgntInfo->Bssid, NETGEAR834Bv2_BROADCOM, 3)==0)
1156 if(0)
1157 {
1158
1159 pHTInfo->bCurrentAMPDUEnable = false;
1160 pHTInfo->ForcedAMSDUMode = HT_AGG_FORCE_ENABLE;
1161 pHTInfo->ForcedAMSDUMaxSize = 7935;
1162
1163 pHTInfo->IOTAction |= HT_IOT_ACT_TX_USE_AMSDU_8K;
1164 }
1165
1166 // Rx Reorder Setting
1167 pHTInfo->bCurRxReorderEnable = pHTInfo->bRegRxReorderEnable;
1168
1169 //
1170 // Filter out unsupported HT rate for this AP
1171 // Update RATR table
1172 // This is only for 8190 ,8192 or later product which using firmware to handle rate adaptive mechanism.
1173 //
1174
1175 // Handle Ralink AP bad MCS rate set condition. Joseph.
1176 // This fix the bug of Ralink AP. This may be removed in the future.
1177 if(pPeerHTCap->MCS[0] == 0)
1178 pPeerHTCap->MCS[0] = 0xff;
1179
1180 HTFilterMCSRate(ieee, pPeerHTCap->MCS, ieee->dot11HTOperationalRateSet);
1181
1182 //
1183 // Config MIMO Power Save setting
1184 //
1185 pHTInfo->PeerMimoPs = pPeerHTCap->MimoPwrSave;
1186 if(pHTInfo->PeerMimoPs == MIMO_PS_STATIC)
1187 pMcsFilter = MCS_FILTER_1SS;
1188 else
1189 pMcsFilter = MCS_FILTER_ALL;
1190 //WB add for MCS8 bug
1191// pMcsFilter = MCS_FILTER_1SS;
1192 ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, pMcsFilter);
1193 ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate;
1194
1195 //
1196 // Config current operation mode.
1197 //
1198 pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
1199
1200
1201
1202}
1203
1204void HTSetConnectBwModeCallback(struct ieee80211_device* ieee);
1205/********************************************************************************************************************
1206 *function: initialize HT info(struct PRT_HIGH_THROUGHPUT)
1207 * input: struct ieee80211_device* ieee
1208 * output: none
1209 * return: none
1210 * notice: This function is called when * (1) MPInitialization Phase * (2) Receiving of Deauthentication from AP
1211********************************************************************************************************************/
1212// TODO: Should this funciton be called when receiving of Disassociation?
1213void HTInitializeHTInfo(struct ieee80211_device* ieee)
1214{
1215 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1216
1217 //
1218 // These parameters will be reset when receiving deauthentication packet
1219 //
1220 IEEE80211_DEBUG(IEEE80211_DL_HT, "===========>%s()\n", __FUNCTION__);
1221 pHTInfo->bCurrentHTSupport = false;
1222
1223 // 40MHz channel support
1224 pHTInfo->bCurBW40MHz = false;
1225 pHTInfo->bCurTxBW40MHz = false;
1226
1227 // Short GI support
1228 pHTInfo->bCurShortGI20MHz = false;
1229 pHTInfo->bCurShortGI40MHz = false;
1230 pHTInfo->bForcedShortGI = false;
1231
1232 // CCK rate support
1233 // This flag is set to true to support CCK rate by default.
1234 // It will be affected by "pHTInfo->bRegSuppCCK" and AP capabilities only when associate to
1235 // 11N BSS.
1236 pHTInfo->bCurSuppCCK = true;
1237
1238 // AMSDU related
1239 pHTInfo->bCurrent_AMSDU_Support = false;
1240 pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
1241
1242 // AMPUD related
1243 pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
1244 pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
1245
1246
1247
1248 // Initialize all of the parameters related to 11n
1249 memset((void*)(&(pHTInfo->SelfHTCap)), 0, sizeof(pHTInfo->SelfHTCap));
1250 memset((void*)(&(pHTInfo->SelfHTInfo)), 0, sizeof(pHTInfo->SelfHTInfo));
1251 memset((void*)(&(pHTInfo->PeerHTCapBuf)), 0, sizeof(pHTInfo->PeerHTCapBuf));
1252 memset((void*)(&(pHTInfo->PeerHTInfoBuf)), 0, sizeof(pHTInfo->PeerHTInfoBuf));
1253
1254 pHTInfo->bSwBwInProgress = false;
1255 pHTInfo->ChnlOp = CHNLOP_NONE;
1256
1257 // Set default IEEE spec for Draft N
1258 pHTInfo->ePeerHTSpecVer = HT_SPEC_VER_IEEE;
1259
1260 // Realtek proprietary aggregation mode
1261 pHTInfo->bCurrentRT2RTAggregation = false;
1262 pHTInfo->bCurrentRT2RTLongSlotTime = false;
1263 pHTInfo->IOTPeer = 0;
1264 pHTInfo->IOTAction = 0;
1265
1266 //MCS rate initialized here
1267 {
1268 u8* RegHTSuppRateSets = &(ieee->RegHTSuppRateSet[0]);
1269 RegHTSuppRateSets[0] = 0xFF; //support MCS 0~7
1270 RegHTSuppRateSets[1] = 0xFF; //support MCS 8~15
1271 RegHTSuppRateSets[4] = 0x01; //support MCS 32
1272 }
1273}
1274/********************************************************************************************************************
1275 *function: initialize Bss HT structure(struct PBSS_HT)
1276 * input: PBSS_HT pBssHT //to be initialized
1277 * output: none
1278 * return: none
1279 * notice: This function is called when initialize network structure
1280********************************************************************************************************************/
1281void HTInitializeBssDesc(PBSS_HT pBssHT)
1282{
1283
1284 pBssHT->bdSupportHT = false;
1285 memset(pBssHT->bdHTCapBuf, 0, sizeof(pBssHT->bdHTCapBuf));
1286 pBssHT->bdHTCapLen = 0;
1287 memset(pBssHT->bdHTInfoBuf, 0, sizeof(pBssHT->bdHTInfoBuf));
1288 pBssHT->bdHTInfoLen = 0;
1289
1290 pBssHT->bdHTSpecVer= HT_SPEC_VER_IEEE;
1291
1292 pBssHT->bdRT2RTAggregation = false;
1293 pBssHT->bdRT2RTLongSlotTime = false;
1294}
1295#if 0
1296//below function has merged into ieee80211_network_init() in ieee80211_rx.c
1297void
1298HTParsingHTCapElement(
1299 IN PADAPTER Adapter,
1300 IN OCTET_STRING HTCapIE,
1301 OUT PRT_WLAN_BSS pBssDesc
1302)
1303{
1304 PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
1305
1306 if( HTCapIE.Length > sizeof(pBssDesc->BssHT.bdHTCapBuf) )
1307 {
1308 RT_TRACE( COMP_HT, DBG_LOUD, ("HTParsingHTCapElement(): HT Capability Element length is too long!\n") );
1309 return;
1310 }
1311
1312 // TODO: Check the correctness of HT Cap
1313 //Print each field in detail. Driver should not print out this message by default
1314 if(!pMgntInfo->mActingAsAp && !pMgntInfo->mAssoc)
1315 HTDebugHTCapability(DBG_TRACE, Adapter, &HTCapIE, (pu8)"HTParsingHTCapElement()");
1316
1317 HTCapIE.Length = HTCapIE.Length > sizeof(pBssDesc->BssHT.bdHTCapBuf)?\
1318 sizeof(pBssDesc->BssHT.bdHTCapBuf):HTCapIE.Length; //prevent from overflow
1319
1320 CopyMem(pBssDesc->BssHT.bdHTCapBuf, HTCapIE.Octet, HTCapIE.Length);
1321 pBssDesc->BssHT.bdHTCapLen = HTCapIE.Length;
1322
1323}
1324
1325
1326void
1327HTParsingHTInfoElement(
1328 PADAPTER Adapter,
1329 OCTET_STRING HTInfoIE,
1330 PRT_WLAN_BSS pBssDesc
1331)
1332{
1333 PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
1334
1335 if( HTInfoIE.Length > sizeof(pBssDesc->BssHT.bdHTInfoBuf))
1336 {
1337 RT_TRACE( COMP_HT, DBG_LOUD, ("HTParsingHTInfoElement(): HT Information Element length is too long!\n") );
1338 return;
1339 }
1340
1341 // TODO: Check the correctness of HT Info
1342 //Print each field in detail. Driver should not print out this message by default
1343 if(!pMgntInfo->mActingAsAp && !pMgntInfo->mAssoc)
1344 HTDebugHTInfo(DBG_TRACE, Adapter, &HTInfoIE, (pu8)"HTParsingHTInfoElement()");
1345
1346 HTInfoIE.Length = HTInfoIE.Length > sizeof(pBssDesc->BssHT.bdHTInfoBuf)?\
1347 sizeof(pBssDesc->BssHT.bdHTInfoBuf):HTInfoIE.Length; //prevent from overflow
1348
1349 CopyMem( pBssDesc->BssHT.bdHTInfoBuf, HTInfoIE.Octet, HTInfoIE.Length);
1350 pBssDesc->BssHT.bdHTInfoLen = HTInfoIE.Length;
1351}
1352
1353/*
1354 * Get HT related information from beacon and save it in BssDesc
1355 *
1356 * (1) Parse HTCap, and HTInfo, and record whether it is 11n AP
1357 * (2) If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT()
1358 * (3) Check whether peer is Realtek AP (for Realtek proprietary aggregation mode).
1359 * Input:
1360 * PADAPTER Adapter
1361 *
1362 * Output:
1363 * PRT_TCB BssDesc
1364 *
1365*/
1366void HTGetValueFromBeaconOrProbeRsp(
1367 PADAPTER Adapter,
1368 POCTET_STRING pSRCmmpdu,
1369 PRT_WLAN_BSS bssDesc
1370)
1371{
1372 PMGNT_INFO pMgntInfo = &Adapter->MgntInfo;
1373 PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo);
1374 OCTET_STRING HTCapIE, HTInfoIE, HTRealtekAgg, mmpdu;
1375 OCTET_STRING BroadcomElement, CiscoElement;
1376
1377 mmpdu.Octet = pSRCmmpdu->Octet;
1378 mmpdu.Length = pSRCmmpdu->Length;
1379
1380 //2Note:
1381 // Mark for IOT testing using Linksys WRT350N, This AP does not contain WMM IE when
1382 // it is configured at pure-N mode.
1383 // if(bssDesc->BssQos.bdQoSMode & QOS_WMM)
1384 //
1385
1386 HTInitializeBssDesc (&bssDesc->BssHT);
1387
1388 //2<1> Parse HTCap, and HTInfo
1389 // Get HT Capability IE: (1) Get IEEE Draft N IE or (2) Get EWC IE
1390 HTCapIE = PacketGetElement(mmpdu, EID_HTCapability, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE);
1391 if(HTCapIE.Length == 0)
1392 {
1393 HTCapIE = PacketGetElement(mmpdu, EID_Vendor, OUI_SUB_11N_EWC_HT_CAP, OUI_SUBTYPE_DONT_CARE);
1394 if(HTCapIE.Length != 0)
1395 bssDesc->BssHT.bdHTSpecVer= HT_SPEC_VER_EWC;
1396 }
1397 if(HTCapIE.Length != 0)
1398 HTParsingHTCapElement(Adapter, HTCapIE, bssDesc);
1399
1400 // Get HT Information IE: (1) Get IEEE Draft N IE or (2) Get EWC IE
1401 HTInfoIE = PacketGetElement(mmpdu, EID_HTInfo, OUI_SUB_DONT_CARE, OUI_SUBTYPE_DONT_CARE);
1402 if(HTInfoIE.Length == 0)
1403 {
1404 HTInfoIE = PacketGetElement(mmpdu, EID_Vendor, OUI_SUB_11N_EWC_HT_INFO, OUI_SUBTYPE_DONT_CARE);
1405 if(HTInfoIE.Length != 0)
1406 bssDesc->BssHT.bdHTSpecVer = HT_SPEC_VER_EWC;
1407 }
1408 if(HTInfoIE.Length != 0)
1409 HTParsingHTInfoElement(Adapter, HTInfoIE, bssDesc);
1410
1411 //2<2>If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT()
1412 if(HTCapIE.Length != 0)
1413 {
1414 bssDesc->BssHT.bdSupportHT = true;
1415 if(bssDesc->BssQos.bdQoSMode == QOS_DISABLE)
1416 QosSetLegacyWMMParamWithHT(Adapter, bssDesc);
1417 }
1418 else
1419 {
1420 bssDesc->BssHT.bdSupportHT = false;
1421 }
1422
1423 //2<3>Check whether the peer is Realtek AP/STA
1424 if(pHTInfo->bRegRT2RTAggregation)
1425 {
1426 if(bssDesc->BssHT.bdSupportHT)
1427 {
1428 HTRealtekAgg = PacketGetElement(mmpdu, EID_Vendor, OUI_SUB_REALTEK_AGG, OUI_SUBTYPE_DONT_CARE);
1429 if(HTRealtekAgg.Length >=5 )
1430 {
1431 bssDesc->BssHT.bdRT2RTAggregation = true;
1432
1433 if((HTRealtekAgg.Octet[4]==1) && (HTRealtekAgg.Octet[5] & 0x02))
1434 bssDesc->BssHT.bdRT2RTLongSlotTime = true;
1435 }
1436 }
1437 }
1438
1439 //
1440 // 2008/01/25 MH Get Broadcom AP IE for manamgent frame CCK rate problem.
1441 // AP can not receive CCK managemtn from from 92E.
1442 //
1443
1444 // Initialize every new bss broadcom cap exist as false..
1445 bssDesc->bBroadcomCapExist= false;
1446
1447 if(HTCapIE.Length != 0 || HTInfoIE.Length != 0)
1448 {
1449 u4Byte Length = 0;
1450
1451 FillOctetString(BroadcomElement, NULL, 0);
1452
1453 BroadcomElement = PacketGetElement( mmpdu, EID_Vendor, OUI_SUB_BROADCOM_IE_1, OUI_SUBTYPE_DONT_CARE);
1454 Length += BroadcomElement.Length;
1455 BroadcomElement = PacketGetElement( mmpdu, EID_Vendor, OUI_SUB_BROADCOM_IE_2, OUI_SUBTYPE_DONT_CARE);
1456 Length += BroadcomElement.Length;
1457 BroadcomElement = PacketGetElement( mmpdu, EID_Vendor, OUI_SUB_BROADCOM_IE_3, OUI_SUBTYPE_DONT_CARE);
1458 Length += BroadcomElement.Length;
1459
1460 if(Length > 0)
1461 bssDesc->bBroadcomCapExist = true;
1462 }
1463
1464
1465 // For Cisco IOT issue
1466 CiscoElement = PacketGetElement( mmpdu, EID_Vendor, OUI_SUB_CISCO_IE, OUI_SUBTYPE_DONT_CARE);
1467 if(CiscoElement.Length != 0){ // 3: 0x00, 0x40, 0x96 ....
1468 bssDesc->bCiscoCapExist = true;
1469 }else{
1470 bssDesc->bCiscoCapExist = false;
1471 }
1472}
1473
1474
1475#endif
1476/********************************************************************************************************************
1477 *function: initialize Bss HT structure(struct PBSS_HT)
1478 * input: struct ieee80211_device *ieee
1479 * struct ieee80211_network *pNetwork //usually current network we are live in
1480 * output: none
1481 * return: none
1482 * notice: This function should ONLY be called before association
1483********************************************************************************************************************/
1484void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork)
1485{
1486 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1487// u16 nMaxAMSDUSize;
1488// PHT_CAPABILITY_ELE pPeerHTCap = (PHT_CAPABILITY_ELE)pNetwork->bssht.bdHTCapBuf;
1489// PHT_INFORMATION_ELE pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf;
1490// u8* pMcsFilter;
1491 u8 bIOTAction = 0;
1492
1493 //
1494 // Save Peer Setting before Association
1495 //
1496 IEEE80211_DEBUG(IEEE80211_DL_HT, "==============>%s()\n", __FUNCTION__);
1497 /*unmark bEnableHT flag here is the same reason why unmarked in function ieee80211_softmac_new_net. WB 2008.09.10*/
1498// if( pHTInfo->bEnableHT && pNetwork->bssht.bdSupportHT)
1499 if (pNetwork->bssht.bdSupportHT)
1500 {
1501 pHTInfo->bCurrentHTSupport = true;
1502 pHTInfo->ePeerHTSpecVer = pNetwork->bssht.bdHTSpecVer;
1503
1504 // Save HTCap and HTInfo information Element
1505 if(pNetwork->bssht.bdHTCapLen > 0 && pNetwork->bssht.bdHTCapLen <= sizeof(pHTInfo->PeerHTCapBuf))
1506 memcpy(pHTInfo->PeerHTCapBuf, pNetwork->bssht.bdHTCapBuf, pNetwork->bssht.bdHTCapLen);
1507
1508 if(pNetwork->bssht.bdHTInfoLen > 0 && pNetwork->bssht.bdHTInfoLen <= sizeof(pHTInfo->PeerHTInfoBuf))
1509 memcpy(pHTInfo->PeerHTInfoBuf, pNetwork->bssht.bdHTInfoBuf, pNetwork->bssht.bdHTInfoLen);
1510
1511 // Check whether RT to RT aggregation mode is enabled
1512 if(pHTInfo->bRegRT2RTAggregation)
1513 {
1514 pHTInfo->bCurrentRT2RTAggregation = pNetwork->bssht.bdRT2RTAggregation;
1515 pHTInfo->bCurrentRT2RTLongSlotTime = pNetwork->bssht.bdRT2RTLongSlotTime;
1516 }
1517 else
1518 {
1519 pHTInfo->bCurrentRT2RTAggregation = false;
1520 pHTInfo->bCurrentRT2RTLongSlotTime = false;
1521 }
1522
1523 // Determine the IOT Peer Vendor.
1524 HTIOTPeerDetermine(ieee);
1525
1526 // Decide IOT Action
1527 // Must be called after the parameter of pHTInfo->bCurrentRT2RTAggregation is decided
1528 pHTInfo->IOTAction = 0;
1529 bIOTAction = HTIOTActIsDisableMCS14(ieee, pNetwork->bssid);
1530 if(bIOTAction)
1531 pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS14;
1532 bIOTAction = HTIOTActIsForcedCTS2Self(ieee, pNetwork);
1533 if(bIOTAction)
1534 pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
1535
1536 bIOTAction = HTIOTActIsDisableMCS15(ieee);
1537 if(bIOTAction)
1538 pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS15;
1539
1540 bIOTAction = HTIOTActIsDisableMCSTwoSpatialStream(ieee, pNetwork->bssid);
1541 if(bIOTAction)
1542 pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_ALL_2SS;
1543
1544
1545 bIOTAction = HTIOTActIsDisableEDCATurbo(ieee, pNetwork->bssid);
1546 if(bIOTAction)
1547 pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_EDCA_TURBO;
1548
1549 bIOTAction = HTIOTActIsMgntUseCCK6M(pNetwork);
1550 if(bIOTAction)
1551 pHTInfo->IOTAction |= HT_IOT_ACT_MGNT_USE_CCK_6M;
1552
1553 bIOTAction = HTIOTActIsCCDFsync(pNetwork->bssid);
1554 if(bIOTAction)
1555 pHTInfo->IOTAction |= HT_IOT_ACT_CDD_FSYNC;
1556
1557 bIOTAction = HTIOTActIsNullDataPowerSaving(ieee, pNetwork);
1558 if(bIOTAction)
1559 pHTInfo->IOTAction |= HT_IOT_ACT_NULL_DATA_POWER_SAVING;
1560
1561 }
1562 else
1563 {
1564 pHTInfo->bCurrentHTSupport = false;
1565 pHTInfo->bCurrentRT2RTAggregation = false;
1566 pHTInfo->bCurrentRT2RTLongSlotTime = false;
1567
1568 pHTInfo->IOTAction = 0;
1569 }
1570
1571}
1572
1573void HTUpdateSelfAndPeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork)
1574{
1575 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1576// PHT_CAPABILITY_ELE pPeerHTCap = (PHT_CAPABILITY_ELE)pNetwork->bssht.bdHTCapBuf;
1577 PHT_INFORMATION_ELE pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf;
1578
1579 if(pHTInfo->bCurrentHTSupport)
1580 {
1581 //
1582 // Config current operation mode.
1583 //
1584 if(pNetwork->bssht.bdHTInfoLen != 0)
1585 pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode;
1586
1587 //
1588 // <TODO: Config according to OBSS non-HT STA present!!>
1589 //
1590 }
1591}
1592
1593void HTUseDefaultSetting(struct ieee80211_device* ieee)
1594{
1595 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1596// u8 regBwOpMode;
1597
1598 if(pHTInfo->bEnableHT)
1599 {
1600 pHTInfo->bCurrentHTSupport = true;
1601
1602 pHTInfo->bCurSuppCCK = pHTInfo->bRegSuppCCK;
1603
1604 pHTInfo->bCurBW40MHz = pHTInfo->bRegBW40MHz;
1605
1606 pHTInfo->bCurShortGI20MHz= pHTInfo->bRegShortGI20MHz;
1607
1608 pHTInfo->bCurShortGI40MHz= pHTInfo->bRegShortGI40MHz;
1609
1610 pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
1611
1612 pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize;
1613
1614 pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable;
1615
1616 pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
1617
1618 pHTInfo->CurrentMPDUDensity = pHTInfo->CurrentMPDUDensity;
1619
1620 // Set BWOpMode register
1621
1622 //update RATR index0
1623 HTFilterMCSRate(ieee, ieee->Regdot11HTOperationalRateSet, ieee->dot11HTOperationalRateSet);
1624 //function below is not implemented at all. WB
1625#ifdef TODO
1626 Adapter->HalFunc.InitHalRATRTableHandler( Adapter, &pMgntInfo->dot11OperationalRateSet, pMgntInfo->dot11HTOperationalRateSet);
1627#endif
1628 ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, MCS_FILTER_ALL);
1629 ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate;
1630
1631 }
1632 else
1633 {
1634 pHTInfo->bCurrentHTSupport = false;
1635 }
1636}
1637/********************************************************************************************************************
1638 *function: check whether HT control field exists
1639 * input: struct ieee80211_device *ieee
1640 * u8* pFrame //coming skb->data
1641 * output: none
1642 * return: return true if HT control field exists(false otherwise)
1643 * notice:
1644********************************************************************************************************************/
1645u8 HTCCheck(struct ieee80211_device* ieee, u8* pFrame)
1646{
1647 if(ieee->pHTInfo->bCurrentHTSupport)
1648 {
1649 if( (IsQoSDataFrame(pFrame) && Frame_Order(pFrame)) == 1)
1650 {
1651 IEEE80211_DEBUG(IEEE80211_DL_HT, "HT CONTROL FILED EXIST!!\n");
1652 return true;
1653 }
1654 }
1655 return false;
1656}
1657
1658//
1659// This function set bandwidth mode in protocol layer.
1660//
1661void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset)
1662{
1663 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1664// u32 flags = 0;
1665
1666 if(pHTInfo->bRegBW40MHz == false)
1667 return;
1668
1669
1670
1671 // To reduce dummy operation
1672// if((pHTInfo->bCurBW40MHz==false && Bandwidth==HT_CHANNEL_WIDTH_20) ||
1673// (pHTInfo->bCurBW40MHz==true && Bandwidth==HT_CHANNEL_WIDTH_20_40 && Offset==pHTInfo->CurSTAExtChnlOffset))
1674// return;
1675
1676// spin_lock_irqsave(&(ieee->bw_spinlock), flags);
1677 if(pHTInfo->bSwBwInProgress) {
1678// spin_unlock_irqrestore(&(ieee->bw_spinlock), flags);
1679 return;
1680 }
1681 //if in half N mode, set to 20M bandwidth please 09.08.2008 WB.
1682 if (Bandwidth==HT_CHANNEL_WIDTH_20_40 && (!ieee->GetHalfNmodeSupportByAPsHandler(ieee)))
1683 {
1684 // Handle Illegal extension channel offset!!
1685 if(ieee->current_network.channel<2 && Offset==HT_EXTCHNL_OFFSET_LOWER)
1686 Offset = HT_EXTCHNL_OFFSET_NO_EXT;
1687 if(Offset==HT_EXTCHNL_OFFSET_UPPER || Offset==HT_EXTCHNL_OFFSET_LOWER) {
1688 pHTInfo->bCurBW40MHz = true;
1689 pHTInfo->CurSTAExtChnlOffset = Offset;
1690 } else {
1691 pHTInfo->bCurBW40MHz = false;
1692 pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
1693 }
1694 } else {
1695 pHTInfo->bCurBW40MHz = false;
1696 pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT;
1697 }
1698
1699 pHTInfo->bSwBwInProgress = true;
1700
1701 // TODO: 2007.7.13 by Emily Wait 2000ms in order to guarantee that switching
1702 // bandwidth is executed after scan is finished. It is a temporal solution
1703 // because software should ganrantee the last operation of switching bandwidth
1704 // is executed properlly.
1705 HTSetConnectBwModeCallback(ieee);
1706
1707// spin_unlock_irqrestore(&(ieee->bw_spinlock), flags);
1708}
1709
1710void HTSetConnectBwModeCallback(struct ieee80211_device* ieee)
1711{
1712 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
1713
1714 IEEE80211_DEBUG(IEEE80211_DL_HT, "======>%s()\n", __FUNCTION__);
1715
1716 if(pHTInfo->bCurBW40MHz)
1717 {
1718 if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_UPPER)
1719 ieee->set_chan(ieee, ieee->current_network.channel+2);
1720 else if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_LOWER)
1721 ieee->set_chan(ieee, ieee->current_network.channel-2);
1722 else
1723 ieee->set_chan(ieee, ieee->current_network.channel);
1724
1725 ieee->SetBWModeHandler(ieee, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset);
1726 } else {
1727 ieee->set_chan(ieee, ieee->current_network.channel);
1728 ieee->SetBWModeHandler(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1729 }
1730
1731 pHTInfo->bSwBwInProgress = false;
1732}
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_Qos.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_Qos.h
new file mode 100644
index 00000000000..d4565ecc7ab
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_Qos.h
@@ -0,0 +1,582 @@
1#ifndef __INC_QOS_TYPE_H
2#define __INC_QOS_TYPE_H
3
4#define BIT0 0x00000001
5#define BIT1 0x00000002
6#define BIT2 0x00000004
7#define BIT3 0x00000008
8#define BIT4 0x00000010
9#define BIT5 0x00000020
10#define BIT6 0x00000040
11#define BIT7 0x00000080
12#define BIT8 0x00000100
13#define BIT9 0x00000200
14#define BIT10 0x00000400
15#define BIT11 0x00000800
16#define BIT12 0x00001000
17#define BIT13 0x00002000
18#define BIT14 0x00004000
19#define BIT15 0x00008000
20#define BIT16 0x00010000
21#define BIT17 0x00020000
22#define BIT18 0x00040000
23#define BIT19 0x00080000
24#define BIT20 0x00100000
25#define BIT21 0x00200000
26#define BIT22 0x00400000
27#define BIT23 0x00800000
28#define BIT24 0x01000000
29#define BIT25 0x02000000
30#define BIT26 0x04000000
31#define BIT27 0x08000000
32#define BIT28 0x10000000
33#define BIT29 0x20000000
34#define BIT30 0x40000000
35#define BIT31 0x80000000
36
37#define MAX_WMMELE_LENGTH 64
38
39//
40// QoS mode.
41// enum 0, 1, 2, 4: since we can use the OR(|) operation.
42//
43// QOS_MODE is redefined for enum can't be ++, | under C++ compiler, 2006.05.17, by rcnjko.
44//typedef enum _QOS_MODE{
45// QOS_DISABLE = 0,
46// QOS_WMM = 1,
47// QOS_EDCA = 2,
48// QOS_HCCA = 4,
49//}QOS_MODE,*PQOS_MODE;
50//
51typedef u32 QOS_MODE, *PQOS_MODE;
52#define QOS_DISABLE 0
53#define QOS_WMM 1
54#define QOS_WMMSA 2
55#define QOS_EDCA 4
56#define QOS_HCCA 8
57#define QOS_WMM_UAPSD 16 //WMM Power Save, 2006-06-14 Isaiah
58
59#define AC_PARAM_SIZE 4
60#define WMM_PARAM_ELE_BODY_LEN 18
61
62//
63// QoS ACK Policy Field Values
64// Ref: WMM spec 2.1.6: QoS Control Field, p.10.
65//
66typedef enum _ACK_POLICY{
67 eAckPlc0_ACK = 0x00,
68 eAckPlc1_NoACK = 0x01,
69}ACK_POLICY,*PACK_POLICY;
70
71#define WMM_PARAM_ELEMENT_SIZE (8+(4*AC_PARAM_SIZE))
72
73//
74// QoS Control Field
75// Ref:
76// 1. WMM spec 2.1.6: QoS Control Field, p.9.
77// 2. 802.11e/D13.0 7.1.3.5, p.26.
78//
79typedef union _QOS_CTRL_FIELD{
80 u8 charData[2];
81 u16 shortData;
82
83 // WMM spec
84 struct
85 {
86 u8 UP:3;
87 u8 usRsvd1:1;
88 u8 EOSP:1;
89 u8 AckPolicy:2;
90 u8 usRsvd2:1;
91 u8 ucRsvdByte;
92 }WMM;
93
94 // 802.11e: QoS data type frame sent by non-AP QSTAs.
95 struct
96 {
97 u8 TID:4;
98 u8 bIsQsize:1;// 0: BIT[8:15] is TXOP Duration Requested, 1: BIT[8:15] is Queue Size.
99 u8 AckPolicy:2;
100 u8 usRsvd:1;
101 u8 TxopOrQsize; // (BIT4=0)TXOP Duration Requested or (BIT4=1)Queue Size.
102 }BySta;
103
104 // 802.11e: QoS data, QoS Null, and QoS Data+CF-Ack frames sent by HC.
105 struct
106 {
107 u8 TID:4;
108 u8 EOSP:1;
109 u8 AckPolicy:2;
110 u8 usRsvd:1;
111 u8 PSBufState; // QAP PS Buffer State.
112 }ByHc_Data;
113
114 // 802.11e: QoS (+) CF-Poll frames sent by HC.
115 struct
116 {
117 u8 TID:4;
118 u8 EOSP:1;
119 u8 AckPolicy:2;
120 u8 usRsvd:1;
121 u8 TxopLimit; // TXOP Limit.
122 }ByHc_CFP;
123
124}QOS_CTRL_FIELD, *PQOS_CTRL_FIELD;
125
126
127//
128// QoS Info Field
129// Ref:
130// 1. WMM spec 2.2.1: WME Information Element, p.11.
131// 2. 8185 QoS code: QOS_INFO [def. in QoS_mp.h]
132//
133typedef union _QOS_INFO_FIELD{
134 u8 charData;
135
136 struct
137 {
138 u8 ucParameterSetCount:4;
139 u8 ucReserved:4;
140 }WMM;
141
142 struct
143 {
144 //Ref WMM_Specification_1-1.pdf, 2006-06-13 Isaiah
145 u8 ucAC_VO_UAPSD:1;
146 u8 ucAC_VI_UAPSD:1;
147 u8 ucAC_BE_UAPSD:1;
148 u8 ucAC_BK_UAPSD:1;
149 u8 ucReserved1:1;
150 u8 ucMaxSPLen:2;
151 u8 ucReserved2:1;
152
153 }ByWmmPsSta;
154
155 struct
156 {
157 //Ref WMM_Specification_1-1.pdf, 2006-06-13 Isaiah
158 u8 ucParameterSetCount:4;
159 u8 ucReserved:3;
160 u8 ucApUapsd:1;
161 }ByWmmPsAp;
162
163 struct
164 {
165 u8 ucAC3_UAPSD:1;
166 u8 ucAC2_UAPSD:1;
167 u8 ucAC1_UAPSD:1;
168 u8 ucAC0_UAPSD:1;
169 u8 ucQAck:1;
170 u8 ucMaxSPLen:2;
171 u8 ucMoreDataAck:1;
172 } By11eSta;
173
174 struct
175 {
176 u8 ucParameterSetCount:4;
177 u8 ucQAck:1;
178 u8 ucQueueReq:1;
179 u8 ucTXOPReq:1;
180 u8 ucReserved:1;
181 } By11eAp;
182
183 struct
184 {
185 u8 ucReserved1:4;
186 u8 ucQAck:1;
187 u8 ucReserved2:2;
188 u8 ucMoreDataAck:1;
189 } ByWmmsaSta;
190
191 struct
192 {
193 u8 ucReserved1:4;
194 u8 ucQAck:1;
195 u8 ucQueueReq:1;
196 u8 ucTXOPReq:1;
197 u8 ucReserved2:1;
198 } ByWmmsaAp;
199
200 struct
201 {
202 u8 ucAC3_UAPSD:1;
203 u8 ucAC2_UAPSD:1;
204 u8 ucAC1_UAPSD:1;
205 u8 ucAC0_UAPSD:1;
206 u8 ucQAck:1;
207 u8 ucMaxSPLen:2;
208 u8 ucMoreDataAck:1;
209 } ByAllSta;
210
211 struct
212 {
213 u8 ucParameterSetCount:4;
214 u8 ucQAck:1;
215 u8 ucQueueReq:1;
216 u8 ucTXOPReq:1;
217 u8 ucApUapsd:1;
218 } ByAllAp;
219
220}QOS_INFO_FIELD, *PQOS_INFO_FIELD;
221
222//
223// ACI to AC coding.
224// Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
225//
226// AC_CODING is redefined for enum can't be ++, | under C++ compiler, 2006.05.17, by rcnjko.
227//typedef enum _AC_CODING{
228// AC0_BE = 0, // ACI: 0x00 // Best Effort
229// AC1_BK = 1, // ACI: 0x01 // Background
230// AC2_VI = 2, // ACI: 0x10 // Video
231// AC3_VO = 3, // ACI: 0x11 // Voice
232// AC_MAX = 4, // Max: define total number; Should not to be used as a real enum.
233//}AC_CODING,*PAC_CODING;
234//
235typedef u32 AC_CODING;
236#define AC0_BE 0 // ACI: 0x00 // Best Effort
237#define AC1_BK 1 // ACI: 0x01 // Background
238#define AC2_VI 2 // ACI: 0x10 // Video
239#define AC3_VO 3 // ACI: 0x11 // Voice
240#define AC_MAX 4 // Max: define total number; Should not to be used as a real enum.
241
242//
243// ACI/AIFSN Field.
244// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
245//
246typedef union _ACI_AIFSN{
247 u8 charData;
248
249 struct
250 {
251 u8 AIFSN:4;
252 u8 ACM:1;
253 u8 ACI:2;
254 u8 Reserved:1;
255 }f; // Field
256}ACI_AIFSN, *PACI_AIFSN;
257
258//
259// ECWmin/ECWmax field.
260// Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
261//
262typedef union _ECW{
263 u8 charData;
264 struct
265 {
266 u8 ECWmin:4;
267 u8 ECWmax:4;
268 }f; // Field
269}ECW, *PECW;
270
271//
272// AC Parameters Record Format.
273// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
274//
275typedef union _AC_PARAM{
276 u32 longData;
277 u8 charData[4];
278
279 struct
280 {
281 ACI_AIFSN AciAifsn;
282 ECW Ecw;
283 u16 TXOPLimit;
284 }f; // Field
285}AC_PARAM, *PAC_PARAM;
286
287
288
289//
290// QoS element subtype
291//
292typedef enum _QOS_ELE_SUBTYPE{
293 QOSELE_TYPE_INFO = 0x00, // 0x00: Information element
294 QOSELE_TYPE_PARAM = 0x01, // 0x01: parameter element
295}QOS_ELE_SUBTYPE,*PQOS_ELE_SUBTYPE;
296
297
298//
299// Direction Field Values.
300// Ref: WMM spec 2.2.11: WME TSPEC Element, p.18.
301//
302typedef enum _DIRECTION_VALUE{
303 DIR_UP = 0, // 0x00 // UpLink
304 DIR_DOWN = 1, // 0x01 // DownLink
305 DIR_DIRECT = 2, // 0x10 // DirectLink
306 DIR_BI_DIR = 3, // 0x11 // Bi-Direction
307}DIRECTION_VALUE,*PDIRECTION_VALUE;
308
309
310//
311// TS Info field in WMM TSPEC Element.
312// Ref:
313// 1. WMM spec 2.2.11: WME TSPEC Element, p.18.
314// 2. 8185 QoS code: QOS_TSINFO [def. in QoS_mp.h]
315//
316typedef union _QOS_TSINFO{
317 u8 charData[3];
318 struct {
319 u8 ucTrafficType:1; //WMM is reserved
320 u8 ucTSID:4;
321 u8 ucDirection:2;
322 u8 ucAccessPolicy:2; //WMM: bit8=0, bit7=1
323 u8 ucAggregation:1; //WMM is reserved
324 u8 ucPSB:1; //WMMSA is APSD
325 u8 ucUP:3;
326 u8 ucTSInfoAckPolicy:2; //WMM is reserved
327 u8 ucSchedule:1; //WMM is reserved
328 u8 ucReserved:7;
329 }field;
330}QOS_TSINFO, *PQOS_TSINFO;
331
332//
333// WMM TSPEC Body.
334// Ref: WMM spec 2.2.11: WME TSPEC Element, p.16.
335//
336typedef union _TSPEC_BODY{
337 u8 charData[55];
338
339 struct
340 {
341 QOS_TSINFO TSInfo; //u8 TSInfo[3];
342 u16 NominalMSDUsize;
343 u16 MaxMSDUsize;
344 u32 MinServiceItv;
345 u32 MaxServiceItv;
346 u32 InactivityItv;
347 u32 SuspenItv;
348 u32 ServiceStartTime;
349 u32 MinDataRate;
350 u32 MeanDataRate;
351 u32 PeakDataRate;
352 u32 MaxBurstSize;
353 u32 DelayBound;
354 u32 MinPhyRate;
355 u16 SurplusBandwidthAllowance;
356 u16 MediumTime;
357 } f; // Field
358}TSPEC_BODY, *PTSPEC_BODY;
359
360
361//
362// WMM TSPEC Element.
363// Ref: WMM spec 2.2.11: WME TSPEC Element, p.16.
364//
365typedef struct _WMM_TSPEC{
366 u8 ID;
367 u8 Length;
368 u8 OUI[3];
369 u8 OUI_Type;
370 u8 OUI_SubType;
371 u8 Version;
372 TSPEC_BODY Body;
373} WMM_TSPEC, *PWMM_TSPEC;
374
375//
376// ACM implementation method.
377// Annie, 2005-12-13.
378//
379typedef enum _ACM_METHOD{
380 eAcmWay0_SwAndHw = 0, // By SW and HW.
381 eAcmWay1_HW = 1, // By HW.
382 eAcmWay2_SW = 2, // By SW.
383}ACM_METHOD,*PACM_METHOD;
384
385
386typedef struct _ACM{
387// u8 RegEnableACM;
388 u64 UsedTime;
389 u64 MediumTime;
390 u8 HwAcmCtl; // TRUE: UsedTime exceed => Do NOT USE this AC. It wll be written to ACM_CONTROL(0xBF BIT 0/1/2 in 8185B).
391}ACM, *PACM;
392
393typedef u8 AC_UAPSD, *PAC_UAPSD;
394
395#define GET_VO_UAPSD(_apsd) ((_apsd) & BIT0)
396#define SET_VO_UAPSD(_apsd) ((_apsd) |= BIT0)
397
398#define GET_VI_UAPSD(_apsd) ((_apsd) & BIT1)
399#define SET_VI_UAPSD(_apsd) ((_apsd) |= BIT1)
400
401#define GET_BK_UAPSD(_apsd) ((_apsd) & BIT2)
402#define SET_BK_UAPSD(_apsd) ((_apsd) |= BIT2)
403
404#define GET_BE_UAPSD(_apsd) ((_apsd) & BIT3)
405#define SET_BE_UAPSD(_apsd) ((_apsd) |= BIT3)
406
407
408//typedef struct _TCLASS{
409// TODO
410//} TCLASS, *PTCLASS;
411typedef union _QOS_TCLAS{
412
413 struct _TYPE_GENERAL{
414 u8 Priority;
415 u8 ClassifierType;
416 u8 Mask;
417 } TYPE_GENERAL;
418
419 struct _TYPE0_ETH{
420 u8 Priority;
421 u8 ClassifierType;
422 u8 Mask;
423 u8 SrcAddr[6];
424 u8 DstAddr[6];
425 u16 Type;
426 } TYPE0_ETH;
427
428 struct _TYPE1_IPV4{
429 u8 Priority;
430 u8 ClassifierType;
431 u8 Mask;
432 u8 Version;
433 u8 SrcIP[4];
434 u8 DstIP[4];
435 u16 SrcPort;
436 u16 DstPort;
437 u8 DSCP;
438 u8 Protocol;
439 u8 Reserved;
440 } TYPE1_IPV4;
441
442 struct _TYPE1_IPV6{
443 u8 Priority;
444 u8 ClassifierType;
445 u8 Mask;
446 u8 Version;
447 u8 SrcIP[16];
448 u8 DstIP[16];
449 u16 SrcPort;
450 u16 DstPort;
451 u8 FlowLabel[3];
452 } TYPE1_IPV6;
453
454 struct _TYPE2_8021Q{
455 u8 Priority;
456 u8 ClassifierType;
457 u8 Mask;
458 u16 TagType;
459 } TYPE2_8021Q;
460} QOS_TCLAS, *PQOS_TCLAS;
461
462//typedef struct _WMM_TSTREAM{
463//
464//- TSPEC
465//- AC (which to mapping)
466//} WMM_TSTREAM, *PWMM_TSTREAM;
467typedef struct _QOS_TSTREAM{
468 u8 AC;
469 WMM_TSPEC TSpec;
470 QOS_TCLAS TClass;
471} QOS_TSTREAM, *PQOS_TSTREAM;
472
473//typedef struct _U_APSD{
474//- TriggerEnable [4]
475//- MaxSPLength
476//- HighestAcBuffered
477//} U_APSD, *PU_APSD;
478
479//joseph TODO:
480// UAPSD function should be implemented by 2 data structure
481// "Qos control field" and "Qos info field"
482//typedef struct _QOS_UAPSD{
483// u8 bTriggerEnable[4];
484// u8 MaxSPLength;
485// u8 HighestBufAC;
486//} QOS_UAPSD, *PQOS_APSD;
487
488//----------------------------------------------------------------------------
489// 802.11 Management frame Status Code field
490//----------------------------------------------------------------------------
491typedef struct _OCTET_STRING{
492 u8 *Octet;
493 u16 Length;
494}OCTET_STRING, *POCTET_STRING;
495
496//
497// STA QoS data.
498// Ref: DOT11_QOS in 8185 code. [def. in QoS_mp.h]
499//
500typedef struct _STA_QOS{
501 //DECLARE_RT_OBJECT(STA_QOS);
502 u8 WMMIEBuf[MAX_WMMELE_LENGTH];
503 u8* WMMIE;
504
505 // Part 1. Self QoS Mode.
506 QOS_MODE QosCapability; //QoS Capability, 2006-06-14 Isaiah
507 QOS_MODE CurrentQosMode;
508
509 // For WMM Power Save Mode :
510 // ACs are trigger/delivery enabled or legacy power save enabled. 2006-06-13 Isaiah
511 AC_UAPSD b4ac_Uapsd; //VoUapsd(bit0), ViUapsd(bit1), BkUapsd(bit2), BeUapsd(bit3),
512 AC_UAPSD Curr4acUapsd;
513 u8 bInServicePeriod;
514 u8 MaxSPLength;
515 int NumBcnBeforeTrigger;
516
517 // Part 2. EDCA Parameter (perAC)
518 u8 * pWMMInfoEle;
519 u8 WMMParamEle[WMM_PARAM_ELEMENT_SIZE];
520 u8 WMMPELength;
521
522 // <Bruce_Note>
523 //2 ToDo: remove the Qos Info Field and replace it by the above WMM Info element.
524 // By Bruce, 2008-01-30.
525 // Part 2. EDCA Parameter (perAC)
526 QOS_INFO_FIELD QosInfoField_STA; // Maintained by STA
527 QOS_INFO_FIELD QosInfoField_AP; // Retrieved from AP
528
529 AC_PARAM CurAcParameters[4];
530
531 // Part 3. ACM
532 ACM acm[4];
533 ACM_METHOD AcmMethod;
534
535 // Part 4. Per TID (Part 5: TCLASS will be described by TStream)
536 QOS_TSTREAM TStream[16];
537 WMM_TSPEC TSpec;
538
539 u32 QBssWirelessMode;
540
541 // No Ack Setting
542 u8 bNoAck;
543
544 // Enable/Disable Rx immediate BA capability.
545 u8 bEnableRxImmBA;
546
547}STA_QOS, *PSTA_QOS;
548
549//
550// BSS QOS data.
551// Ref: BssDscr in 8185 code. [def. in BssDscr.h]
552//
553typedef struct _BSS_QOS{
554 QOS_MODE bdQoSMode;
555
556 u8 bdWMMIEBuf[MAX_WMMELE_LENGTH];
557 u8* bdWMMIE;
558
559 QOS_ELE_SUBTYPE EleSubType;
560
561 u8 * pWMMInfoEle;
562 u8 * pWMMParamEle;
563
564 QOS_INFO_FIELD QosInfoField;
565 AC_PARAM AcParameter[4];
566}BSS_QOS, *PBSS_QOS;
567
568
569//
570// Ref: sQoSCtlLng and QoSCtl definition in 8185 QoS code.
571//#define QoSCtl (( (Adapter->bRegQoS) && (Adapter->dot11QoS.QoSMode &(QOS_EDCA|QOS_HCCA)) ) ?sQoSCtlLng:0)
572//
573#define sQoSCtlLng 2
574#define QOS_CTRL_LEN(_QosMode) ((_QosMode > QOS_DISABLE)? sQoSCtlLng : 0)
575
576
577//Added by joseph
578//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP
579//#define UP2AC(up) ((up<3)?((up==0)?1:0):(up>>1))
580#define IsACValid(ac) ((ac<=7 )?true:false )
581
582#endif // #ifndef __INC_QOS_TYPE_H
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h
new file mode 100644
index 00000000000..e7e26fd9639
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_TS.h
@@ -0,0 +1,56 @@
1#ifndef _TSTYPE_H_
2#define _TSTYPE_H_
3#include "rtl819x_Qos.h"
4#define TS_SETUP_TIMEOUT 60 // In millisecond
5#define TS_INACT_TIMEOUT 60
6#define TS_ADDBA_DELAY 60
7
8#define TOTAL_TS_NUM 16
9#define TCLAS_NUM 4
10
11// This define the Tx/Rx directions
12typedef enum _TR_SELECT {
13 TX_DIR = 0,
14 RX_DIR = 1,
15} TR_SELECT, *PTR_SELECT;
16
17typedef struct _TS_COMMON_INFO{
18 struct list_head List;
19 struct timer_list SetupTimer;
20 struct timer_list InactTimer;
21 u8 Addr[6];
22 TSPEC_BODY TSpec;
23 QOS_TCLAS TClass[TCLAS_NUM];
24 u8 TClasProc;
25 u8 TClasNum;
26} TS_COMMON_INFO, *PTS_COMMON_INFO;
27
28typedef struct _TX_TS_RECORD{
29 TS_COMMON_INFO TsCommonInfo;
30 u16 TxCurSeq;
31 BA_RECORD TxPendingBARecord; // For BA Originator
32 BA_RECORD TxAdmittedBARecord; // For BA Originator
33// QOS_DL_RECORD DLRecord;
34 u8 bAddBaReqInProgress;
35 u8 bAddBaReqDelayed;
36 u8 bUsingBa;
37 struct timer_list TsAddBaTimer;
38 u8 num;
39} TX_TS_RECORD, *PTX_TS_RECORD;
40
41typedef struct _RX_TS_RECORD {
42 TS_COMMON_INFO TsCommonInfo;
43 u16 RxIndicateSeq;
44 u16 RxTimeoutIndicateSeq;
45 struct list_head RxPendingPktList;
46 struct timer_list RxPktPendingTimer;
47 BA_RECORD RxAdmittedBARecord; // For BA Recipient
48 u16 RxLastSeqNum;
49 u8 RxLastFragNum;
50 u8 num;
51// QOS_DL_RECORD DLRecord;
52} RX_TS_RECORD, *PRX_TS_RECORD;
53
54
55#endif
56
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
new file mode 100644
index 00000000000..ad6872dcf1c
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
@@ -0,0 +1,627 @@
1#include "ieee80211.h"
2#include <linux/etherdevice.h>
3#include <linux/slab.h>
4#include "rtl819x_TS.h"
5
6void TsSetupTimeOut(unsigned long data)
7{
8 // Not implement yet
9 // This is used for WMMSA and ACM , that would send ADDTSReq frame.
10}
11
12void TsInactTimeout(unsigned long data)
13{
14 // Not implement yet
15 // This is used for WMMSA and ACM.
16 // This function would be call when TS is no Tx/Rx for some period of time.
17}
18
19/********************************************************************************************************************
20 *function: I still not understand this function, so wait for further implementation
21 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
22 * return: NULL
23 * notice:
24********************************************************************************************************************/
25void RxPktPendingTimeout(unsigned long data)
26{
27 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data;
28 struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
29
30 PRX_REORDER_ENTRY pReorderEntry = NULL;
31
32 //u32 flags = 0;
33 unsigned long flags = 0;
34 struct ieee80211_rxb *stats_IndicateArray[REORDER_WIN_SIZE];
35 u8 index = 0;
36 bool bPktInBuf = false;
37
38
39 spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
40 //PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK);
41 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"==================>%s()\n",__FUNCTION__);
42 if(pRxTs->RxTimeoutIndicateSeq != 0xffff)
43 {
44 // Indicate the pending packets sequentially according to SeqNum until meet the gap.
45 while(!list_empty(&pRxTs->RxPendingPktList))
46 {
47 pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
48 if(index == 0)
49 pRxTs->RxIndicateSeq = pReorderEntry->SeqNum;
50
51 if( SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) ||
52 SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) )
53 {
54 list_del_init(&pReorderEntry->List);
55
56 if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq))
57 pRxTs->RxIndicateSeq = (pRxTs->RxIndicateSeq + 1) % 4096;
58
59 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"RxPktPendingTimeout(): IndicateSeq: %d\n", pReorderEntry->SeqNum);
60 stats_IndicateArray[index] = pReorderEntry->prxb;
61 index++;
62
63 list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
64 }
65 else
66 {
67 bPktInBuf = true;
68 break;
69 }
70 }
71 }
72
73 if(index>0)
74 {
75 // Set RxTimeoutIndicateSeq to 0xffff to indicate no pending packets in buffer now.
76 pRxTs->RxTimeoutIndicateSeq = 0xffff;
77
78 // Indicate packets
79 if(index > REORDER_WIN_SIZE){
80 IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
81 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
82 return;
83 }
84 ieee80211_indicate_packets(ieee, stats_IndicateArray, index);
85 }
86
87 if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff))
88 {
89 pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq;
90 mod_timer(&pRxTs->RxPktPendingTimer, jiffies + MSECS(ieee->pHTInfo->RxReorderPendingTime));
91 }
92 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
93 //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK);
94}
95
96/********************************************************************************************************************
97 *function: Add BA timer function
98 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
99 * return: NULL
100 * notice:
101********************************************************************************************************************/
102void TsAddBaProcess(unsigned long data)
103{
104 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
105 u8 num = pTxTs->num;
106 struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[num]);
107
108 TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
109 IEEE80211_DEBUG(IEEE80211_DL_BA, "TsAddBaProcess(): ADDBA Req is started!! \n");
110}
111
112
113void ResetTsCommonInfo(PTS_COMMON_INFO pTsCommonInfo)
114{
115 memset(pTsCommonInfo->Addr, 0, 6);
116 memset(&pTsCommonInfo->TSpec, 0, sizeof(TSPEC_BODY));
117 memset(&pTsCommonInfo->TClass, 0, sizeof(QOS_TCLAS)*TCLAS_NUM);
118 pTsCommonInfo->TClasProc = 0;
119 pTsCommonInfo->TClasNum = 0;
120}
121
122void ResetTxTsEntry(PTX_TS_RECORD pTS)
123{
124 ResetTsCommonInfo(&pTS->TsCommonInfo);
125 pTS->TxCurSeq = 0;
126 pTS->bAddBaReqInProgress = false;
127 pTS->bAddBaReqDelayed = false;
128 pTS->bUsingBa = false;
129 ResetBaEntry(&pTS->TxAdmittedBARecord); //For BA Originator
130 ResetBaEntry(&pTS->TxPendingBARecord);
131}
132
133void ResetRxTsEntry(PRX_TS_RECORD pTS)
134{
135 ResetTsCommonInfo(&pTS->TsCommonInfo);
136 pTS->RxIndicateSeq = 0xffff; // This indicate the RxIndicateSeq is not used now!!
137 pTS->RxTimeoutIndicateSeq = 0xffff; // This indicate the RxTimeoutIndicateSeq is not used now!!
138 ResetBaEntry(&pTS->RxAdmittedBARecord); // For BA Recipient
139}
140
141void TSInitialize(struct ieee80211_device *ieee)
142{
143 PTX_TS_RECORD pTxTS = ieee->TxTsRecord;
144 PRX_TS_RECORD pRxTS = ieee->RxTsRecord;
145 PRX_REORDER_ENTRY pRxReorderEntry = ieee->RxReorderEntry;
146 u8 count = 0;
147 IEEE80211_DEBUG(IEEE80211_DL_TS, "==========>%s()\n", __FUNCTION__);
148 // Initialize Tx TS related info.
149 INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List);
150 INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
151 INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
152
153 for(count = 0; count < TOTAL_TS_NUM; count++)
154 {
155 //
156 pTxTS->num = count;
157 // The timers for the operation of Traffic Stream and Block Ack.
158 // DLS related timer will be add here in the future!!
159 init_timer(&pTxTS->TsCommonInfo.SetupTimer);
160 pTxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pTxTS;
161 pTxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut;
162
163 init_timer(&pTxTS->TsCommonInfo.InactTimer);
164 pTxTS->TsCommonInfo.InactTimer.data = (unsigned long)pTxTS;
165 pTxTS->TsCommonInfo.InactTimer.function = TsInactTimeout;
166
167 init_timer(&pTxTS->TsAddBaTimer);
168 pTxTS->TsAddBaTimer.data = (unsigned long)pTxTS;
169 pTxTS->TsAddBaTimer.function = TsAddBaProcess;
170
171 init_timer(&pTxTS->TxPendingBARecord.Timer);
172 pTxTS->TxPendingBARecord.Timer.data = (unsigned long)pTxTS;
173 pTxTS->TxPendingBARecord.Timer.function = BaSetupTimeOut;
174
175 init_timer(&pTxTS->TxAdmittedBARecord.Timer);
176 pTxTS->TxAdmittedBARecord.Timer.data = (unsigned long)pTxTS;
177 pTxTS->TxAdmittedBARecord.Timer.function = TxBaInactTimeout;
178
179 ResetTxTsEntry(pTxTS);
180 list_add_tail(&pTxTS->TsCommonInfo.List, &ieee->Tx_TS_Unused_List);
181 pTxTS++;
182 }
183
184 // Initialize Rx TS related info.
185 INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
186 INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
187 INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
188 for(count = 0; count < TOTAL_TS_NUM; count++)
189 {
190 pRxTS->num = count;
191 INIT_LIST_HEAD(&pRxTS->RxPendingPktList);
192
193 init_timer(&pRxTS->TsCommonInfo.SetupTimer);
194 pRxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pRxTS;
195 pRxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut;
196
197 init_timer(&pRxTS->TsCommonInfo.InactTimer);
198 pRxTS->TsCommonInfo.InactTimer.data = (unsigned long)pRxTS;
199 pRxTS->TsCommonInfo.InactTimer.function = TsInactTimeout;
200
201 init_timer(&pRxTS->RxAdmittedBARecord.Timer);
202 pRxTS->RxAdmittedBARecord.Timer.data = (unsigned long)pRxTS;
203 pRxTS->RxAdmittedBARecord.Timer.function = RxBaInactTimeout;
204
205 init_timer(&pRxTS->RxPktPendingTimer);
206 pRxTS->RxPktPendingTimer.data = (unsigned long)pRxTS;
207 pRxTS->RxPktPendingTimer.function = RxPktPendingTimeout;
208
209 ResetRxTsEntry(pRxTS);
210 list_add_tail(&pRxTS->TsCommonInfo.List, &ieee->Rx_TS_Unused_List);
211 pRxTS++;
212 }
213 // Initialize unused Rx Reorder List.
214 INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
215//#ifdef TO_DO_LIST
216 for(count = 0; count < REORDER_ENTRY_NUM; count++)
217 {
218 list_add_tail( &pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
219 if(count == (REORDER_ENTRY_NUM-1))
220 break;
221 pRxReorderEntry = &ieee->RxReorderEntry[count+1];
222 }
223//#endif
224
225}
226
227void AdmitTS(struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, u32 InactTime)
228{
229 del_timer_sync(&pTsCommonInfo->SetupTimer);
230 del_timer_sync(&pTsCommonInfo->InactTimer);
231
232 if(InactTime!=0)
233 mod_timer(&pTsCommonInfo->InactTimer, jiffies + MSECS(InactTime));
234}
235
236
237PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, u8* Addr, u8 TID, TR_SELECT TxRxSelect)
238{
239 //DIRECTION_VALUE dir;
240 u8 dir;
241 bool search_dir[4] = {0, 0, 0, 0};
242 struct list_head* psearch_list; //FIXME
243 PTS_COMMON_INFO pRet = NULL;
244 if(ieee->iw_mode == IW_MODE_MASTER) //ap mode
245 {
246 if(TxRxSelect == TX_DIR)
247 {
248 search_dir[DIR_DOWN] = true;
249 search_dir[DIR_BI_DIR]= true;
250 }
251 else
252 {
253 search_dir[DIR_UP] = true;
254 search_dir[DIR_BI_DIR]= true;
255 }
256 }
257 else if(ieee->iw_mode == IW_MODE_ADHOC)
258 {
259 if(TxRxSelect == TX_DIR)
260 search_dir[DIR_UP] = true;
261 else
262 search_dir[DIR_DOWN] = true;
263 }
264 else
265 {
266 if(TxRxSelect == TX_DIR)
267 {
268 search_dir[DIR_UP] = true;
269 search_dir[DIR_BI_DIR]= true;
270 search_dir[DIR_DIRECT]= true;
271 }
272 else
273 {
274 search_dir[DIR_DOWN] = true;
275 search_dir[DIR_BI_DIR]= true;
276 search_dir[DIR_DIRECT]= true;
277 }
278 }
279
280 if(TxRxSelect == TX_DIR)
281 psearch_list = &ieee->Tx_TS_Admit_List;
282 else
283 psearch_list = &ieee->Rx_TS_Admit_List;
284
285 //for(dir = DIR_UP; dir <= DIR_BI_DIR; dir++)
286 for(dir = 0; dir <= DIR_BI_DIR; dir++)
287 {
288 if(search_dir[dir] ==false )
289 continue;
290 list_for_each_entry(pRet, psearch_list, List){
291 // IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
292 if (memcmp(pRet->Addr, Addr, 6) == 0)
293 if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
294 if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
295 {
296 break;
297 }
298
299 }
300 if(&pRet->List != psearch_list)
301 break;
302 }
303
304 if(&pRet->List != psearch_list){
305 return pRet ;
306 }
307 else
308 return NULL;
309}
310
311void MakeTSEntry(
312 PTS_COMMON_INFO pTsCommonInfo,
313 u8* Addr,
314 PTSPEC_BODY pTSPEC,
315 PQOS_TCLAS pTCLAS,
316 u8 TCLAS_Num,
317 u8 TCLAS_Proc
318 )
319{
320 u8 count;
321
322 if(pTsCommonInfo == NULL)
323 return;
324
325 memcpy(pTsCommonInfo->Addr, Addr, 6);
326
327 if(pTSPEC != NULL)
328 memcpy((u8*)(&(pTsCommonInfo->TSpec)), (u8*)pTSPEC, sizeof(TSPEC_BODY));
329
330 for(count = 0; count < TCLAS_Num; count++)
331 memcpy((u8*)(&(pTsCommonInfo->TClass[count])), (u8*)pTCLAS, sizeof(QOS_TCLAS));
332
333 pTsCommonInfo->TClasProc = TCLAS_Proc;
334 pTsCommonInfo->TClasNum = TCLAS_Num;
335}
336
337
338bool GetTs(
339 struct ieee80211_device* ieee,
340 PTS_COMMON_INFO *ppTS,
341 u8* Addr,
342 u8 TID,
343 TR_SELECT TxRxSelect, //Rx:1, Tx:0
344 bool bAddNewTs
345 )
346{
347 u8 UP = 0;
348 //
349 // We do not build any TS for Broadcast or Multicast stream.
350 // So reject these kinds of search here.
351 //
352 if(is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr))
353 {
354 IEEE80211_DEBUG(IEEE80211_DL_ERR, "get TS for Broadcast or Multicast\n");
355 return false;
356 }
357
358 if (ieee->current_network.qos_data.supported == 0)
359 UP = 0;
360 else
361 {
362 // In WMM case: we use 4 TID only
363 if (!IsACValid(TID))
364 {
365 IEEE80211_DEBUG(IEEE80211_DL_ERR, " in %s(), TID(%d) is not valid\n", __FUNCTION__, TID);
366 return false;
367 }
368
369 switch(TID)
370 {
371 case 0:
372 case 3:
373 UP = 0;
374 break;
375
376 case 1:
377 case 2:
378 UP = 2;
379 break;
380
381 case 4:
382 case 5:
383 UP = 5;
384 break;
385
386 case 6:
387 case 7:
388 UP = 7;
389 break;
390 }
391 }
392
393 *ppTS = SearchAdmitTRStream(
394 ieee,
395 Addr,
396 UP,
397 TxRxSelect);
398 if(*ppTS != NULL)
399 {
400 return true;
401 }
402 else
403 {
404 if(bAddNewTs == false)
405 {
406 IEEE80211_DEBUG(IEEE80211_DL_TS, "add new TS failed(tid:%d)\n", UP);
407 return false;
408 }
409 else
410 {
411 //
412 // Create a new Traffic stream for current Tx/Rx
413 // This is for EDCA and WMM to add a new TS.
414 // For HCCA or WMMSA, TS cannot be addmit without negotiation.
415 //
416 TSPEC_BODY TSpec;
417 PQOS_TSINFO pTSInfo = &TSpec.f.TSInfo;
418 struct list_head* pUnusedList =
419 (TxRxSelect == TX_DIR)?
420 (&ieee->Tx_TS_Unused_List):
421 (&ieee->Rx_TS_Unused_List);
422
423 struct list_head* pAddmitList =
424 (TxRxSelect == TX_DIR)?
425 (&ieee->Tx_TS_Admit_List):
426 (&ieee->Rx_TS_Admit_List);
427
428 DIRECTION_VALUE Dir = (ieee->iw_mode == IW_MODE_MASTER)?
429 ((TxRxSelect==TX_DIR)?DIR_DOWN:DIR_UP):
430 ((TxRxSelect==TX_DIR)?DIR_UP:DIR_DOWN);
431 IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n");
432 if(!list_empty(pUnusedList))
433 {
434 (*ppTS) = list_entry(pUnusedList->next, TS_COMMON_INFO, List);
435 list_del_init(&(*ppTS)->List);
436 if(TxRxSelect==TX_DIR)
437 {
438 PTX_TS_RECORD tmp = container_of(*ppTS, TX_TS_RECORD, TsCommonInfo);
439 ResetTxTsEntry(tmp);
440 }
441 else{
442 PRX_TS_RECORD tmp = container_of(*ppTS, RX_TS_RECORD, TsCommonInfo);
443 ResetRxTsEntry(tmp);
444 }
445
446 IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
447 // Prepare TS Info releated field
448 pTSInfo->field.ucTrafficType = 0; // Traffic type: WMM is reserved in this field
449 pTSInfo->field.ucTSID = UP; // TSID
450 pTSInfo->field.ucDirection = Dir; // Direction: if there is DirectLink, this need additional consideration.
451 pTSInfo->field.ucAccessPolicy = 1; // Access policy
452 pTSInfo->field.ucAggregation = 0; // Aggregation
453 pTSInfo->field.ucPSB = 0; // Aggregation
454 pTSInfo->field.ucUP = UP; // User priority
455 pTSInfo->field.ucTSInfoAckPolicy = 0; // Ack policy
456 pTSInfo->field.ucSchedule = 0; // Schedule
457
458 MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
459 AdmitTS(ieee, *ppTS, 0);
460 list_add_tail(&((*ppTS)->List), pAddmitList);
461 // if there is DirectLink, we need to do additional operation here!!
462
463 return true;
464 }
465 else
466 {
467 IEEE80211_DEBUG(IEEE80211_DL_ERR, "in function %s() There is not enough TS record to be used!!", __FUNCTION__);
468 return false;
469 }
470 }
471 }
472}
473
474void RemoveTsEntry(
475 struct ieee80211_device* ieee,
476 PTS_COMMON_INFO pTs,
477 TR_SELECT TxRxSelect
478 )
479{
480 //u32 flags = 0;
481 unsigned long flags = 0;
482 del_timer_sync(&pTs->SetupTimer);
483 del_timer_sync(&pTs->InactTimer);
484 TsInitDelBA(ieee, pTs, TxRxSelect);
485
486 if(TxRxSelect == RX_DIR)
487 {
488//#ifdef TO_DO_LIST
489 PRX_REORDER_ENTRY pRxReorderEntry;
490 PRX_TS_RECORD pRxTS = (PRX_TS_RECORD)pTs;
491 if(timer_pending(&pRxTS->RxPktPendingTimer))
492 del_timer_sync(&pRxTS->RxPktPendingTimer);
493
494 while(!list_empty(&pRxTS->RxPendingPktList))
495 {
496 // PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK);
497 spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
498 //pRxReorderEntry = list_entry(&pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
499 pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
500 list_del_init(&pRxReorderEntry->List);
501 {
502 int i = 0;
503 struct ieee80211_rxb * prxb = pRxReorderEntry->prxb;
504 if (unlikely(!prxb))
505 {
506 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
507 return;
508 }
509 for(i =0; i < prxb->nr_subframes; i++) {
510 dev_kfree_skb(prxb->subframes[i]);
511 }
512 kfree(prxb);
513 prxb = NULL;
514 }
515 list_add_tail(&pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
516 //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK);
517 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
518 }
519
520//#endif
521 }
522 else
523 {
524 PTX_TS_RECORD pTxTS = (PTX_TS_RECORD)pTs;
525 del_timer_sync(&pTxTS->TsAddBaTimer);
526 }
527}
528
529void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr)
530{
531 PTS_COMMON_INFO pTS, pTmpTS;
532
533 printk("===========>RemovePeerTS,%pM\n", Addr);
534 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
535 {
536 if (memcmp(pTS->Addr, Addr, 6) == 0)
537 {
538 RemoveTsEntry(ieee, pTS, TX_DIR);
539 list_del_init(&pTS->List);
540 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
541 }
542 }
543
544 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
545 {
546 if (memcmp(pTS->Addr, Addr, 6) == 0)
547 {
548 printk("====>remove Tx_TS_admin_list\n");
549 RemoveTsEntry(ieee, pTS, TX_DIR);
550 list_del_init(&pTS->List);
551 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
552 }
553 }
554
555 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
556 {
557 if (memcmp(pTS->Addr, Addr, 6) == 0)
558 {
559 RemoveTsEntry(ieee, pTS, RX_DIR);
560 list_del_init(&pTS->List);
561 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
562 }
563 }
564
565 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
566 {
567 if (memcmp(pTS->Addr, Addr, 6) == 0)
568 {
569 RemoveTsEntry(ieee, pTS, RX_DIR);
570 list_del_init(&pTS->List);
571 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
572 }
573 }
574}
575
576void RemoveAllTS(struct ieee80211_device* ieee)
577{
578 PTS_COMMON_INFO pTS, pTmpTS;
579
580 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
581 {
582 RemoveTsEntry(ieee, pTS, TX_DIR);
583 list_del_init(&pTS->List);
584 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
585 }
586
587 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
588 {
589 RemoveTsEntry(ieee, pTS, TX_DIR);
590 list_del_init(&pTS->List);
591 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
592 }
593
594 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
595 {
596 RemoveTsEntry(ieee, pTS, RX_DIR);
597 list_del_init(&pTS->List);
598 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
599 }
600
601 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
602 {
603 RemoveTsEntry(ieee, pTS, RX_DIR);
604 list_del_init(&pTS->List);
605 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
606 }
607}
608
609void TsStartAddBaProcess(struct ieee80211_device* ieee, PTX_TS_RECORD pTxTS)
610{
611 if(pTxTS->bAddBaReqInProgress == false)
612 {
613 pTxTS->bAddBaReqInProgress = true;
614 if(pTxTS->bAddBaReqDelayed)
615 {
616 IEEE80211_DEBUG(IEEE80211_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n");
617 mod_timer(&pTxTS->TsAddBaTimer, jiffies + MSECS(TS_ADDBA_DELAY));
618 }
619 else
620 {
621 IEEE80211_DEBUG(IEEE80211_DL_BA,"TsStartAddBaProcess(): Immediately Start ADDBA now!!\n");
622 mod_timer(&pTxTS->TsAddBaTimer, jiffies+10); //set 10 ticks
623 }
624 }
625 else
626 IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __FUNCTION__);
627}
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl_crypto.h b/drivers/staging/rtl8192e/ieee80211/rtl_crypto.h
new file mode 100644
index 00000000000..ccf6ae76357
--- /dev/null
+++ b/drivers/staging/rtl8192e/ieee80211/rtl_crypto.h
@@ -0,0 +1,399 @@
1/*
2 * Scatterlist Cryptographic API.
3 *
4 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
5 * Copyright (c) 2002 David S. Miller (davem@redhat.com)
6 *
7 * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
8 * and Nettle, by Niels Mé°ˆler.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
13 * any later version.
14 *
15 */
16#ifndef _LINUX_CRYPTO_H
17#define _LINUX_CRYPTO_H
18
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/types.h>
22#include <linux/list.h>
23#include <linux/string.h>
24#include <asm/page.h>
25#include <asm/errno.h>
26
27#define crypto_register_alg crypto_register_alg_rsl
28#define crypto_unregister_alg crypto_unregister_alg_rsl
29#define crypto_alloc_tfm crypto_alloc_tfm_rsl
30#define crypto_free_tfm crypto_free_tfm_rsl
31#define crypto_alg_available crypto_alg_available_rsl
32
33/*
34 * Algorithm masks and types.
35 */
36#define CRYPTO_ALG_TYPE_MASK 0x000000ff
37#define CRYPTO_ALG_TYPE_CIPHER 0x00000001
38#define CRYPTO_ALG_TYPE_DIGEST 0x00000002
39#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004
40
41/*
42 * Transform masks and values (for crt_flags).
43 */
44#define CRYPTO_TFM_MODE_MASK 0x000000ff
45#define CRYPTO_TFM_REQ_MASK 0x000fff00
46#define CRYPTO_TFM_RES_MASK 0xfff00000
47
48#define CRYPTO_TFM_MODE_ECB 0x00000001
49#define CRYPTO_TFM_MODE_CBC 0x00000002
50#define CRYPTO_TFM_MODE_CFB 0x00000004
51#define CRYPTO_TFM_MODE_CTR 0x00000008
52
53#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100
54#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000
55#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000
56#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000
57#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000
58#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000
59
60/*
61 * Miscellaneous stuff.
62 */
63#define CRYPTO_UNSPEC 0
64#define CRYPTO_MAX_ALG_NAME 64
65
66struct scatterlist;
67
68/*
69 * Algorithms: modular crypto algorithm implementations, managed
70 * via crypto_register_alg() and crypto_unregister_alg().
71 */
72struct cipher_alg {
73 unsigned int cia_min_keysize;
74 unsigned int cia_max_keysize;
75 int (*cia_setkey)(void *ctx, const u8 *key,
76 unsigned int keylen, u32 *flags);
77 void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src);
78 void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src);
79};
80
81struct digest_alg {
82 unsigned int dia_digestsize;
83 void (*dia_init)(void *ctx);
84 void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
85 void (*dia_final)(void *ctx, u8 *out);
86 int (*dia_setkey)(void *ctx, const u8 *key,
87 unsigned int keylen, u32 *flags);
88};
89
90struct compress_alg {
91 int (*coa_init)(void *ctx);
92 void (*coa_exit)(void *ctx);
93 int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen,
94 u8 *dst, unsigned int *dlen);
95 int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen,
96 u8 *dst, unsigned int *dlen);
97};
98
99#define cra_cipher cra_u.cipher
100#define cra_digest cra_u.digest
101#define cra_compress cra_u.compress
102
103struct crypto_alg {
104 struct list_head cra_list;
105 u32 cra_flags;
106 unsigned int cra_blocksize;
107 unsigned int cra_ctxsize;
108 const char cra_name[CRYPTO_MAX_ALG_NAME];
109
110 union {
111 struct cipher_alg cipher;
112 struct digest_alg digest;
113 struct compress_alg compress;
114 } cra_u;
115
116 struct module *cra_module;
117};
118
119/*
120 * Algorithm registration interface.
121 */
122int crypto_register_alg(struct crypto_alg *alg);
123int crypto_unregister_alg(struct crypto_alg *alg);
124
125/*
126 * Algorithm query interface.
127 */
128int crypto_alg_available(const char *name, u32 flags);
129
130/*
131 * Transforms: user-instantiated objects which encapsulate algorithms
132 * and core processing logic. Managed via crypto_alloc_tfm() and
133 * crypto_free_tfm(), as well as the various helpers below.
134 */
135struct crypto_tfm;
136
137struct cipher_tfm {
138 void *cit_iv;
139 unsigned int cit_ivsize;
140 u32 cit_mode;
141 int (*cit_setkey)(struct crypto_tfm *tfm,
142 const u8 *key, unsigned int keylen);
143 int (*cit_encrypt)(struct crypto_tfm *tfm,
144 struct scatterlist *dst,
145 struct scatterlist *src,
146 unsigned int nbytes);
147 int (*cit_encrypt_iv)(struct crypto_tfm *tfm,
148 struct scatterlist *dst,
149 struct scatterlist *src,
150 unsigned int nbytes, u8 *iv);
151 int (*cit_decrypt)(struct crypto_tfm *tfm,
152 struct scatterlist *dst,
153 struct scatterlist *src,
154 unsigned int nbytes);
155 int (*cit_decrypt_iv)(struct crypto_tfm *tfm,
156 struct scatterlist *dst,
157 struct scatterlist *src,
158 unsigned int nbytes, u8 *iv);
159 void (*cit_xor_block)(u8 *dst, const u8 *src);
160};
161
162struct digest_tfm {
163 void (*dit_init)(struct crypto_tfm *tfm);
164 void (*dit_update)(struct crypto_tfm *tfm,
165 struct scatterlist *sg, unsigned int nsg);
166 void (*dit_final)(struct crypto_tfm *tfm, u8 *out);
167 void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg,
168 unsigned int nsg, u8 *out);
169 int (*dit_setkey)(struct crypto_tfm *tfm,
170 const u8 *key, unsigned int keylen);
171#ifdef CONFIG_CRYPTO_HMAC
172 void *dit_hmac_block;
173#endif
174};
175
176struct compress_tfm {
177 int (*cot_compress)(struct crypto_tfm *tfm,
178 const u8 *src, unsigned int slen,
179 u8 *dst, unsigned int *dlen);
180 int (*cot_decompress)(struct crypto_tfm *tfm,
181 const u8 *src, unsigned int slen,
182 u8 *dst, unsigned int *dlen);
183};
184
185#define crt_cipher crt_u.cipher
186#define crt_digest crt_u.digest
187#define crt_compress crt_u.compress
188
189struct crypto_tfm {
190
191 u32 crt_flags;
192
193 union {
194 struct cipher_tfm cipher;
195 struct digest_tfm digest;
196 struct compress_tfm compress;
197 } crt_u;
198
199 struct crypto_alg *__crt_alg;
200};
201
202/*
203 * Transform user interface.
204 */
205
206/*
207 * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm.
208 * If that fails and the kernel supports dynamically loadable modules, it
209 * will then attempt to load a module of the same name or alias. A refcount
210 * is grabbed on the algorithm which is then associated with the new transform.
211 *
212 * crypto_free_tfm() frees up the transform and any associated resources,
213 * then drops the refcount on the associated algorithm.
214 */
215struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags);
216void crypto_free_tfm(struct crypto_tfm *tfm);
217
218/*
219 * Transform helpers which query the underlying algorithm.
220 */
221static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm)
222{
223 return tfm->__crt_alg->cra_name;
224}
225
226static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm)
227{
228 struct crypto_alg *alg = tfm->__crt_alg;
229
230 if (alg->cra_module)
231 return alg->cra_module->name;
232 else
233 return NULL;
234}
235
236static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm)
237{
238 return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK;
239}
240
241static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm)
242{
243 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
244 return tfm->__crt_alg->cra_cipher.cia_min_keysize;
245}
246
247static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm)
248{
249 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
250 return tfm->__crt_alg->cra_cipher.cia_max_keysize;
251}
252
253static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm)
254{
255 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
256 return tfm->crt_cipher.cit_ivsize;
257}
258
259static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm)
260{
261 return tfm->__crt_alg->cra_blocksize;
262}
263
264static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm)
265{
266 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
267 return tfm->__crt_alg->cra_digest.dia_digestsize;
268}
269
270/*
271 * API wrappers.
272 */
273static inline void crypto_digest_init(struct crypto_tfm *tfm)
274{
275 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
276 tfm->crt_digest.dit_init(tfm);
277}
278
279static inline void crypto_digest_update(struct crypto_tfm *tfm,
280 struct scatterlist *sg,
281 unsigned int nsg)
282{
283 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
284 tfm->crt_digest.dit_update(tfm, sg, nsg);
285}
286
287static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
288{
289 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
290 tfm->crt_digest.dit_final(tfm, out);
291}
292
293static inline void crypto_digest_digest(struct crypto_tfm *tfm,
294 struct scatterlist *sg,
295 unsigned int nsg, u8 *out)
296{
297 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
298 tfm->crt_digest.dit_digest(tfm, sg, nsg, out);
299}
300
301static inline int crypto_digest_setkey(struct crypto_tfm *tfm,
302 const u8 *key, unsigned int keylen)
303{
304 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST);
305 if (tfm->crt_digest.dit_setkey == NULL)
306 return -ENOSYS;
307 return tfm->crt_digest.dit_setkey(tfm, key, keylen);
308}
309
310static inline int crypto_cipher_setkey(struct crypto_tfm *tfm,
311 const u8 *key, unsigned int keylen)
312{
313 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
314 return tfm->crt_cipher.cit_setkey(tfm, key, keylen);
315}
316
317static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm,
318 struct scatterlist *dst,
319 struct scatterlist *src,
320 unsigned int nbytes)
321{
322 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
323 return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes);
324}
325
326static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm,
327 struct scatterlist *dst,
328 struct scatterlist *src,
329 unsigned int nbytes, u8 *iv)
330{
331 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
332 BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
333 return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv);
334}
335
336static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm,
337 struct scatterlist *dst,
338 struct scatterlist *src,
339 unsigned int nbytes)
340{
341 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
342 return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes);
343}
344
345static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm,
346 struct scatterlist *dst,
347 struct scatterlist *src,
348 unsigned int nbytes, u8 *iv)
349{
350 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
351 BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB);
352 return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv);
353}
354
355static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm,
356 const u8 *src, unsigned int len)
357{
358 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
359 memcpy(tfm->crt_cipher.cit_iv, src, len);
360}
361
362static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm,
363 u8 *dst, unsigned int len)
364{
365 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
366 memcpy(dst, tfm->crt_cipher.cit_iv, len);
367}
368
369static inline int crypto_comp_compress(struct crypto_tfm *tfm,
370 const u8 *src, unsigned int slen,
371 u8 *dst, unsigned int *dlen)
372{
373 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
374 return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen);
375}
376
377static inline int crypto_comp_decompress(struct crypto_tfm *tfm,
378 const u8 *src, unsigned int slen,
379 u8 *dst, unsigned int *dlen)
380{
381 BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS);
382 return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen);
383}
384
385/*
386 * HMAC support.
387 */
388#ifdef CONFIG_CRYPTO_HMAC
389void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen);
390void crypto_hmac_update(struct crypto_tfm *tfm,
391 struct scatterlist *sg, unsigned int nsg);
392void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key,
393 unsigned int *keylen, u8 *out);
394void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen,
395 struct scatterlist *sg, unsigned int nsg, u8 *out);
396#endif /* CONFIG_CRYPTO_HMAC */
397
398#endif /* _LINUX_CRYPTO_H */
399
diff --git a/drivers/staging/rtl8192e/r8180_93cx6.c b/drivers/staging/rtl8192e/r8180_93cx6.c
new file mode 100644
index 00000000000..55d4f56dc42
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8180_93cx6.c
@@ -0,0 +1,141 @@
1/*
2 This files contains card eeprom (93c46 or 93c56) programming routines,
3 memory is addressed by 16 bits words.
4
5 This is part of rtl8180 OpenSource driver.
6 Copyright (C) Andrea Merello 2004 <andreamrl@tiscali.it>
7 Released under the terms of GPL (General Public Licence)
8
9 Parts of this driver are based on the GPL part of the
10 official realtek driver.
11
12 Parts of this driver are based on the rtl8180 driver skeleton
13 from Patric Schenke & Andres Salomon.
14
15 Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
16
17 We want to tanks the Authors of those projects and the Ndiswrapper
18 project Authors.
19*/
20
21#include "r8180_93cx6.h"
22
23static void eprom_cs(struct r8192_priv *priv, short bit)
24{
25 if (bit)
26 write_nic_byte(priv, EPROM_CMD,
27 (1<<EPROM_CS_SHIFT) |
28 read_nic_byte(priv, EPROM_CMD)); //enable EPROM
29 else
30 write_nic_byte(priv, EPROM_CMD, read_nic_byte(priv, EPROM_CMD)
31 &~(1<<EPROM_CS_SHIFT)); //disable EPROM
32
33 udelay(EPROM_DELAY);
34}
35
36
37static void eprom_ck_cycle(struct r8192_priv *priv)
38{
39 write_nic_byte(priv, EPROM_CMD,
40 (1<<EPROM_CK_SHIFT) | read_nic_byte(priv, EPROM_CMD));
41 udelay(EPROM_DELAY);
42 write_nic_byte(priv, EPROM_CMD,
43 read_nic_byte(priv, EPROM_CMD) & ~(1<<EPROM_CK_SHIFT));
44 udelay(EPROM_DELAY);
45}
46
47
48static void eprom_w(struct r8192_priv *priv, short bit)
49{
50 if (bit)
51 write_nic_byte(priv, EPROM_CMD, (1<<EPROM_W_SHIFT) |
52 read_nic_byte(priv, EPROM_CMD));
53 else
54 write_nic_byte(priv, EPROM_CMD, read_nic_byte(priv, EPROM_CMD)
55 &~(1<<EPROM_W_SHIFT));
56
57 udelay(EPROM_DELAY);
58}
59
60
61static short eprom_r(struct r8192_priv *priv)
62{
63 short bit;
64
65 bit = (read_nic_byte(priv, EPROM_CMD) & (1<<EPROM_R_SHIFT));
66 udelay(EPROM_DELAY);
67
68 if (bit)
69 return 1;
70 return 0;
71}
72
73
74static void eprom_send_bits_string(struct r8192_priv *priv, short b[], int len)
75{
76 int i;
77
78 for (i = 0; i < len; i++) {
79 eprom_w(priv, b[i]);
80 eprom_ck_cycle(priv);
81 }
82}
83
84
85u32 eprom_read(struct r8192_priv *priv, u32 addr)
86{
87 short read_cmd[] = {1, 1, 0};
88 short addr_str[8];
89 int i;
90 int addr_len;
91 u32 ret;
92
93 ret = 0;
94 //enable EPROM programming
95 write_nic_byte(priv, EPROM_CMD,
96 (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT));
97 udelay(EPROM_DELAY);
98
99 if (priv->epromtype == EPROM_93c56) {
100 addr_str[7] = addr & 1;
101 addr_str[6] = addr & (1<<1);
102 addr_str[5] = addr & (1<<2);
103 addr_str[4] = addr & (1<<3);
104 addr_str[3] = addr & (1<<4);
105 addr_str[2] = addr & (1<<5);
106 addr_str[1] = addr & (1<<6);
107 addr_str[0] = addr & (1<<7);
108 addr_len = 8;
109 } else {
110 addr_str[5] = addr & 1;
111 addr_str[4] = addr & (1<<1);
112 addr_str[3] = addr & (1<<2);
113 addr_str[2] = addr & (1<<3);
114 addr_str[1] = addr & (1<<4);
115 addr_str[0] = addr & (1<<5);
116 addr_len = 6;
117 }
118 eprom_cs(priv, 1);
119 eprom_ck_cycle(priv);
120 eprom_send_bits_string(priv, read_cmd, 3);
121 eprom_send_bits_string(priv, addr_str, addr_len);
122
123 //keep chip pin D to low state while reading.
124 //I'm unsure if it is necessary, but anyway shouldn't hurt
125 eprom_w(priv, 0);
126
127 for (i = 0; i < 16; i++) {
128 //eeprom needs a clk cycle between writing opcode&adr
129 //and reading data. (eeprom outs a dummy 0)
130 eprom_ck_cycle(priv);
131 ret |= (eprom_r(priv)<<(15-i));
132 }
133
134 eprom_cs(priv, 0);
135 eprom_ck_cycle(priv);
136
137 //disable EPROM programming
138 write_nic_byte(priv, EPROM_CMD,
139 (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
140 return ret;
141}
diff --git a/drivers/staging/rtl8192e/r8180_93cx6.h b/drivers/staging/rtl8192e/r8180_93cx6.h
new file mode 100644
index 00000000000..55d20544a9c
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8180_93cx6.h
@@ -0,0 +1,41 @@
1/* r8180_93cx6.h - 93c46 or 93c56 eeprom card programming routines
2 *
3 * This is part of rtl8187 OpenSource driver
4 * Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it>
5 * Released under the terms of GPL (General Public Licence)
6 * Parts of this driver are based on the GPL part of the official realtek driver
7 *
8 * Parts of this driver are based on the rtl8180 driver skeleton from
9 * Patric Schenke & Andres Salomon.
10 *
11 * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
12 *
13 * We want to thank the authors of the above mentioned projects and to
14 * the authors of the Ndiswrapper project.
15 */
16
17#include "r8192E.h"
18#include "r8192E_hw.h"
19
20#define EPROM_DELAY 10
21
22#define EPROM_ANAPARAM_ADDRLWORD 0xd
23#define EPROM_ANAPARAM_ADDRHWORD 0xe
24
25#define EPROM_RFCHIPID 0x6
26#define EPROM_TXPW_BASE 0x05
27#define EPROM_RFCHIPID_RTL8225U 5
28#define EPROM_RF_PARAM 0x4
29#define EPROM_CONFIG2 0xc
30
31#define EPROM_VERSION 0x1E
32#define MAC_ADR 0x7
33
34#define CIS 0x18
35
36#define EPROM_TXPW0 0x16
37#define EPROM_TXPW2 0x1b
38#define EPROM_TXPW1 0x3d
39
40/* Reads a 16 bits word. */
41u32 eprom_read(struct r8192_priv *priv, u32 addr);
diff --git a/drivers/staging/rtl8192e/r8190_rtl8256.c b/drivers/staging/rtl8192e/r8190_rtl8256.c
new file mode 100644
index 00000000000..286462cc819
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8190_rtl8256.c
@@ -0,0 +1,677 @@
1/*
2 This is part of the rtl8192 driver
3 released under the GPL (See file COPYING for details).
4
5 This files contains programming code for the rtl8256
6 radio frontend.
7
8 *Many* thanks to Realtek Corp. for their great support!
9
10*/
11
12#include "r8192E.h"
13#include "r8192E_hw.h"
14#include "r819xE_phyreg.h"
15#include "r819xE_phy.h"
16#include "r8190_rtl8256.h"
17
18/*--------------------------------------------------------------------------
19 * Overview: set RF band width (20M or 40M)
20 * Input: struct net_device* dev
21 * WIRELESS_BANDWIDTH_E Bandwidth //20M or 40M
22 * Output: NONE
23 * Return: NONE
24 * Note: 8226 support both 20M and 40 MHz
25 *---------------------------------------------------------------------------*/
26void PHY_SetRF8256Bandwidth(struct r8192_priv *priv, HT_CHANNEL_WIDTH Bandwidth) //20M or 40M
27{
28 u8 eRFPath;
29
30 //for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
31 for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
32 {
33 if (!rtl8192_phy_CheckIsLegalRFPath(priv, eRFPath))
34 continue;
35
36 switch(Bandwidth)
37 {
38 case HT_CHANNEL_WIDTH_20:
39 if(priv->card_8192_version == VERSION_8190_BD || priv->card_8192_version == VERSION_8190_BE)// 8256 D-cut, E-cut, xiong: consider it later!
40 {
41 rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x100); //phy para:1ba
42 rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3d7);
43 rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x021);
44
45 //cosa add for sd3's request 01/23/2008
46 //rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab);
47 }
48 else
49 {
50 RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
51 }
52
53 break;
54 case HT_CHANNEL_WIDTH_20_40:
55 if(priv->card_8192_version == VERSION_8190_BD ||priv->card_8192_version == VERSION_8190_BE)// 8256 D-cut, E-cut, xiong: consider it later!
56 {
57 rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x300); //phy para:3ba
58 rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3ff);
59 rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x0e1);
60
61 }
62 else
63 {
64 RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown hardware version\n");
65 }
66
67
68 break;
69 default:
70 RT_TRACE(COMP_ERR, "PHY_SetRF8256Bandwidth(): unknown Bandwidth: %#X\n",Bandwidth );
71 break;
72
73 }
74 }
75}
76/*--------------------------------------------------------------------------
77 * Overview: Interface to config 8256
78 * Input: struct net_device* dev
79 * Output: NONE
80 * Return: NONE
81 *---------------------------------------------------------------------------*/
82RT_STATUS PHY_RF8256_Config(struct r8192_priv *priv)
83{
84 // Initialize general global value
85 //
86 RT_STATUS rtStatus = RT_STATUS_SUCCESS;
87 // TODO: Extend RF_PATH_C and RF_PATH_D in the future
88 priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
89 // Config BB and RF
90 rtStatus = phy_RF8256_Config_ParaFile(priv);
91
92 return rtStatus;
93}
94
95/*--------------------------------------------------------------------------
96 * Overview: Interface to config 8256
97 * Input: struct net_device* dev
98 * Output: NONE
99 * Return: NONE
100 *---------------------------------------------------------------------------*/
101RT_STATUS phy_RF8256_Config_ParaFile(struct r8192_priv *priv)
102{
103 u32 u4RegValue = 0;
104 u8 eRFPath;
105 RT_STATUS rtStatus = RT_STATUS_SUCCESS;
106 BB_REGISTER_DEFINITION_T *pPhyReg;
107 u32 RegOffSetToBeCheck = 0x3;
108 u32 RegValueToBeCheck = 0x7f1;
109 u32 RF3_Final_Value = 0;
110 u8 ConstRetryTimes = 5, RetryTimes = 5;
111 u8 ret = 0;
112
113 //3//-----------------------------------------------------------------
114 //3// <2> Initialize RF
115 //3//-----------------------------------------------------------------
116 for(eRFPath = (RF90_RADIO_PATH_E)RF90_PATH_A; eRFPath <priv->NumTotalRFPath; eRFPath++)
117 {
118 if (!rtl8192_phy_CheckIsLegalRFPath(priv, eRFPath))
119 continue;
120
121 pPhyReg = &priv->PHYRegDef[eRFPath];
122
123 /*----Store original RFENV control type----*/
124 switch(eRFPath)
125 {
126 case RF90_PATH_A:
127 case RF90_PATH_C:
128 u4RegValue = rtl8192_QueryBBReg(priv, pPhyReg->rfintfs, bRFSI_RFENV);
129 break;
130 case RF90_PATH_B :
131 case RF90_PATH_D:
132 u4RegValue = rtl8192_QueryBBReg(priv, pPhyReg->rfintfs, bRFSI_RFENV<<16);
133 break;
134 }
135
136 /*----Set RF_ENV enable----*/
137 rtl8192_setBBreg(priv, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
138
139 /*----Set RF_ENV output high----*/
140 rtl8192_setBBreg(priv, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
141
142 /* Set bit number of Address and Data for RF register */
143 rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); // Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258
144 rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); // Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ???
145
146 rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E) eRFPath, 0x0, bMask12Bits, 0xbf);
147
148 /*----Check RF block (for FPGA platform only)----*/
149 // TODO: this function should be removed on ASIC , Emily 2007.2.2
150 rtStatus = rtl8192_phy_checkBBAndRF(priv, HW90_BLOCK_RF, (RF90_RADIO_PATH_E)eRFPath);
151 if(rtStatus!= RT_STATUS_SUCCESS)
152 {
153 RT_TRACE(COMP_ERR, "PHY_RF8256_Config():Check Radio[%d] Fail!!\n", eRFPath);
154 goto phy_RF8256_Config_ParaFile_Fail;
155 }
156
157 RetryTimes = ConstRetryTimes;
158 RF3_Final_Value = 0;
159 /*----Initialize RF fom connfiguration file----*/
160 switch(eRFPath)
161 {
162 case RF90_PATH_A:
163 while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
164 {
165 ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
166 RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
167 RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
168 RetryTimes--;
169 }
170 break;
171 case RF90_PATH_B:
172 while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
173 {
174 ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
175 RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
176 RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
177 RetryTimes--;
178 }
179 break;
180 case RF90_PATH_C:
181 while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
182 {
183 ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
184 RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
185 RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
186 RetryTimes--;
187 }
188 break;
189 case RF90_PATH_D:
190 while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
191 {
192 ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
193 RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
194 RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
195 RetryTimes--;
196 }
197 break;
198 }
199
200 /*----Restore RFENV control type----*/;
201 switch(eRFPath)
202 {
203 case RF90_PATH_A:
204 case RF90_PATH_C:
205 rtl8192_setBBreg(priv, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
206 break;
207 case RF90_PATH_B :
208 case RF90_PATH_D:
209 rtl8192_setBBreg(priv, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
210 break;
211 }
212
213 if(ret){
214 RT_TRACE(COMP_ERR, "phy_RF8256_Config_ParaFile():Radio[%d] Fail!!", eRFPath);
215 goto phy_RF8256_Config_ParaFile_Fail;
216 }
217
218 }
219
220 RT_TRACE(COMP_PHY, "PHY Initialization Success\n") ;
221 return RT_STATUS_SUCCESS;
222
223phy_RF8256_Config_ParaFile_Fail:
224 RT_TRACE(COMP_ERR, "PHY Initialization failed\n") ;
225 return RT_STATUS_FAILURE;
226}
227
228
229void PHY_SetRF8256CCKTxPower(struct r8192_priv *priv, u8 powerlevel)
230{
231 u32 TxAGC=0;
232
233 TxAGC = powerlevel;
234 if(priv->bDynamicTxLowPower == true)//cosa 04282008 for cck long range
235 {
236 if(priv->CustomerID == RT_CID_819x_Netcore)
237 TxAGC = 0x22;
238 else
239 TxAGC += priv->CckPwEnl;
240 }
241 if(TxAGC > 0x24)
242 TxAGC = 0x24;
243 rtl8192_setBBreg(priv, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
244}
245
246
247void PHY_SetRF8256OFDMTxPower(struct r8192_priv *priv, u8 powerlevel)
248{
249
250 u32 writeVal, powerBase0, powerBase1, writeVal_tmp;
251 u8 index = 0;
252 u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
253 u8 byte0, byte1, byte2, byte3;
254
255 powerBase0 = powerlevel + priv->LegacyHTTxPowerDiff; //OFDM rates
256 powerBase0 = (powerBase0<<24) | (powerBase0<<16) |(powerBase0<<8) |powerBase0;
257 powerBase1 = powerlevel; //MCS rates
258 powerBase1 = (powerBase1<<24) | (powerBase1<<16) |(powerBase1<<8) |powerBase1;
259
260 for(index=0; index<6; index++)
261 {
262 writeVal = priv->MCSTxPowerLevelOriginalOffset[index] + ((index<2)?powerBase0:powerBase1);
263 byte0 = (u8)(writeVal & 0x7f);
264 byte1 = (u8)((writeVal & 0x7f00)>>8);
265 byte2 = (u8)((writeVal & 0x7f0000)>>16);
266 byte3 = (u8)((writeVal & 0x7f000000)>>24);
267 if(byte0 > 0x24) // Max power index = 0x24
268 byte0 = 0x24;
269 if(byte1 > 0x24)
270 byte1 = 0x24;
271 if(byte2 > 0x24)
272 byte2 = 0x24;
273 if(byte3 > 0x24)
274 byte3 = 0x24;
275
276 if(index == 3)
277 {
278 writeVal_tmp = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0;
279 priv->Pwr_Track = writeVal_tmp;
280 }
281
282 if(priv->bDynamicTxHighPower == true) //Add by Jacken 2008/03/06 //when DM implement, add this
283 {
284 writeVal = 0x03030303;
285 }
286 else
287 {
288 writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0;
289 }
290 rtl8192_setBBreg(priv, RegOffset[index], 0x7f7f7f7f, writeVal);
291 }
292}
293
294#define MAX_DOZE_WAITING_TIMES_9x 64
295static void r8192e_drain_tx_queues(struct r8192_priv *priv)
296{
297 u8 i, QueueID;
298
299 for (QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
300 {
301 struct rtl8192_tx_ring *ring = &priv->tx_ring[QueueID];
302
303 if(skb_queue_len(&ring->queue) == 0)
304 {
305 QueueID++;
306 continue;
307 }
308
309 udelay(10);
310 i++;
311
312 if (i >= MAX_DOZE_WAITING_TIMES_9x)
313 {
314 RT_TRACE(COMP_POWER, "r8192e_drain_tx_queues() timeout queue %d\n", QueueID);
315 break;
316 }
317 }
318}
319
320static bool SetRFPowerState8190(struct r8192_priv *priv,
321 RT_RF_POWER_STATE eRFPowerState)
322{
323 PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
324 bool bResult = true;
325
326 if (eRFPowerState == priv->eRFPowerState &&
327 priv->bHwRfOffAction == 0) {
328 bResult = false;
329 goto out;
330 }
331
332 switch( eRFPowerState )
333 {
334 case eRfOn:
335
336 // turn on RF
337 if ((priv->eRFPowerState == eRfOff) &&
338 RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
339 {
340 /*
341 * The current RF state is OFF and the RF OFF level
342 * is halting the NIC, re-initialize the NIC.
343 */
344 if (!NicIFEnableNIC(priv)) {
345 RT_TRACE(COMP_ERR, "%s(): NicIFEnableNIC failed\n",__FUNCTION__);
346 bResult = false;
347 goto out;
348 }
349
350 RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
351 } else {
352 write_nic_byte(priv, ANAPAR, 0x37);//160MHz
353 mdelay(1);
354 //enable clock 80/88 MHz
355 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x4, 0x1); // 0x880[2]
356 priv->bHwRfOffAction = 0;
357
358 //RF-A, RF-B
359 //enable RF-Chip A/B
360 rtl8192_setBBreg(priv, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1); // 0x860[4]
361 //analog to digital on
362 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
363 //digital to analog on
364 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x18, 0x3); // 0x880[4:3]
365 //rx antenna on
366 rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
367 //rx antenna on
368 rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
369 //analog to digital part2 on
370 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x60, 0x3); // 0x880[6:5]
371
372 }
373
374 break;
375
376 //
377 // In current solution, RFSleep=RFOff in order to save power under 802.11 power save.
378 // By Bruce, 2008-01-16.
379 //
380 case eRfSleep:
381
382 // HW setting had been configured with deeper mode.
383 if(priv->eRFPowerState == eRfOff)
384 break;
385
386 r8192e_drain_tx_queues(priv);
387
388 PHY_SetRtl8192eRfOff(priv);
389
390 break;
391
392 case eRfOff:
393
394 //
395 // Disconnect with Any AP or STA.
396 //
397 r8192e_drain_tx_queues(priv);
398
399
400 if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
401 {
402 /* Disable all components. */
403 NicIFDisableNIC(priv);
404 RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
405 }
406 else if (!(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC))
407 {
408 /* Normal case - IPS should go to this. */
409 PHY_SetRtl8192eRfOff(priv);
410 }
411 break;
412
413 default:
414 bResult = false;
415 RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknow state to set: 0x%X!!!\n", eRFPowerState);
416 break;
417 }
418
419 if(bResult)
420 {
421 // Update current RF state variable.
422 priv->eRFPowerState = eRFPowerState;
423 }
424
425out:
426 return bResult;
427}
428
429
430
431
432
433static void MgntDisconnectIBSS(struct r8192_priv *priv)
434{
435 u8 i;
436 bool bFilterOutNonAssociatedBSSID = false;
437
438 priv->ieee80211->state = IEEE80211_NOLINK;
439
440 for(i=0;i<6;i++) priv->ieee80211->current_network.bssid[i]= 0x55;
441 priv->OpMode = RT_OP_MODE_NO_LINK;
442 write_nic_word(priv, BSSIDR, ((u16*)priv->ieee80211->current_network.bssid)[0]);
443 write_nic_dword(priv, BSSIDR+2, ((u32*)(priv->ieee80211->current_network.bssid+2))[0]);
444 {
445 RT_OP_MODE OpMode = priv->OpMode;
446 u8 btMsr = read_nic_byte(priv, MSR);
447
448 btMsr &= 0xfc;
449
450 switch(OpMode)
451 {
452 case RT_OP_MODE_INFRASTRUCTURE:
453 btMsr |= MSR_LINK_MANAGED;
454 break;
455
456 case RT_OP_MODE_IBSS:
457 btMsr |= MSR_LINK_ADHOC;
458 // led link set separate
459 break;
460
461 case RT_OP_MODE_AP:
462 btMsr |= MSR_LINK_MASTER;
463 break;
464
465 default:
466 btMsr |= MSR_LINK_NONE;
467 break;
468 }
469
470 write_nic_byte(priv, MSR, btMsr);
471 }
472 ieee80211_stop_send_beacons(priv->ieee80211);
473
474 // If disconnect, clear RCR CBSSID bit
475 bFilterOutNonAssociatedBSSID = false;
476 {
477 u32 RegRCR, Type;
478 Type = bFilterOutNonAssociatedBSSID;
479 RegRCR = read_nic_dword(priv, RCR);
480 priv->ReceiveConfig = RegRCR;
481 if (Type == true)
482 RegRCR |= (RCR_CBSSID);
483 else if (Type == false)
484 RegRCR &= (~RCR_CBSSID);
485
486 {
487 write_nic_dword(priv, RCR, RegRCR);
488 priv->ReceiveConfig = RegRCR;
489 }
490
491 }
492 notify_wx_assoc_event(priv->ieee80211);
493
494}
495
496static void MlmeDisassociateRequest(struct r8192_priv *priv, u8 *asSta,
497 u8 asRsn)
498{
499 u8 i;
500
501 RemovePeerTS(priv->ieee80211, asSta);
502
503 SendDisassociation( priv->ieee80211, asSta, asRsn );
504
505 if(memcpy(priv->ieee80211->current_network.bssid,asSta,6) == NULL)
506 {
507 //ShuChen TODO: change media status.
508 //ShuChen TODO: What to do when disassociate.
509 priv->ieee80211->state = IEEE80211_NOLINK;
510 for(i=0;i<6;i++) priv->ieee80211->current_network.bssid[i] = 0x22;
511 priv->OpMode = RT_OP_MODE_NO_LINK;
512 {
513 RT_OP_MODE OpMode = priv->OpMode;
514 u8 btMsr = read_nic_byte(priv, MSR);
515
516 btMsr &= 0xfc;
517
518 switch(OpMode)
519 {
520 case RT_OP_MODE_INFRASTRUCTURE:
521 btMsr |= MSR_LINK_MANAGED;
522 break;
523
524 case RT_OP_MODE_IBSS:
525 btMsr |= MSR_LINK_ADHOC;
526 // led link set separate
527 break;
528
529 case RT_OP_MODE_AP:
530 btMsr |= MSR_LINK_MASTER;
531 break;
532
533 default:
534 btMsr |= MSR_LINK_NONE;
535 break;
536 }
537
538 write_nic_byte(priv, MSR, btMsr);
539 }
540 ieee80211_disassociate(priv->ieee80211);
541
542 write_nic_word(priv, BSSIDR, ((u16*)priv->ieee80211->current_network.bssid)[0]);
543 write_nic_dword(priv, BSSIDR+2, ((u32*)(priv->ieee80211->current_network.bssid+2))[0]);
544
545 }
546
547}
548
549
550static void MgntDisconnectAP(struct r8192_priv *priv, u8 asRsn)
551{
552 bool bFilterOutNonAssociatedBSSID = false;
553 u32 RegRCR, Type;
554
555 /* If disconnect, clear RCR CBSSID bit */
556 bFilterOutNonAssociatedBSSID = false;
557
558 Type = bFilterOutNonAssociatedBSSID;
559 RegRCR = read_nic_dword(priv, RCR);
560 priv->ReceiveConfig = RegRCR;
561
562 if (Type == true)
563 RegRCR |= (RCR_CBSSID);
564 else if (Type == false)
565 RegRCR &= (~RCR_CBSSID);
566
567 write_nic_dword(priv, RCR, RegRCR);
568 priv->ReceiveConfig = RegRCR;
569
570 MlmeDisassociateRequest(priv, priv->ieee80211->current_network.bssid, asRsn);
571
572 priv->ieee80211->state = IEEE80211_NOLINK;
573}
574
575
576static bool MgntDisconnect(struct r8192_priv *priv, u8 asRsn)
577{
578 // In adhoc mode, update beacon frame.
579 if( priv->ieee80211->state == IEEE80211_LINKED )
580 {
581 if( priv->ieee80211->iw_mode == IW_MODE_ADHOC )
582 {
583 MgntDisconnectIBSS(priv);
584 }
585 if( priv->ieee80211->iw_mode == IW_MODE_INFRA )
586 {
587 // We clear key here instead of MgntDisconnectAP() because that
588 // MgntActSet_802_11_DISASSOCIATE() is an interface called by OS,
589 // e.g. OID_802_11_DISASSOCIATE in Windows while as MgntDisconnectAP() is
590 // used to handle disassociation related things to AP, e.g. send Disassoc
591 // frame to AP. 2005.01.27, by rcnjko.
592 MgntDisconnectAP(priv, asRsn);
593 }
594 }
595
596 return true;
597}
598
599//
600// Description:
601// Chang RF Power State.
602// Note that, only MgntActSet_RF_State() is allowed to set HW_VAR_RF_STATE.
603//
604// Assumption:
605// PASSIVE LEVEL.
606//
607bool MgntActSet_RF_State(struct r8192_priv *priv, RT_RF_POWER_STATE StateToSet,
608 RT_RF_CHANGE_SOURCE ChangeSource)
609{
610 bool bActionAllowed = false;
611 bool bConnectBySSID = false;
612 RT_RF_POWER_STATE rtState;
613
614 RT_TRACE(COMP_POWER, "===>MgntActSet_RF_State(): StateToSet(%d)\n",StateToSet);
615
616 spin_lock(&priv->rf_ps_lock);
617
618 rtState = priv->eRFPowerState;
619
620 switch(StateToSet)
621 {
622 case eRfOn:
623 priv->RfOffReason &= (~ChangeSource);
624
625 if (!priv->RfOffReason)
626 {
627 priv->RfOffReason = 0;
628 bActionAllowed = true;
629
630
631 if(rtState == eRfOff && ChangeSource >=RF_CHANGE_BY_HW )
632 {
633 bConnectBySSID = true;
634 }
635 }
636 else
637 RT_TRACE(COMP_POWER, "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", priv->RfOffReason, ChangeSource);
638
639 break;
640
641 case eRfOff:
642
643 if (priv->RfOffReason > RF_CHANGE_BY_IPS)
644 {
645 // Disconnect to current BSS when radio off. Asked by QuanTa.
646 MgntDisconnect(priv, disas_lv_ss);
647 }
648
649 priv->RfOffReason |= ChangeSource;
650 bActionAllowed = true;
651 break;
652
653 case eRfSleep:
654 priv->RfOffReason |= ChangeSource;
655 bActionAllowed = true;
656 break;
657 }
658
659 if (bActionAllowed)
660 {
661 RT_TRACE(COMP_POWER, "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, priv->RfOffReason);
662 // Config HW to the specified mode.
663 SetRFPowerState8190(priv, StateToSet);
664 }
665 else
666 {
667 RT_TRACE(COMP_POWER, "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", StateToSet, ChangeSource, priv->RfOffReason);
668 }
669
670 // Release RF spinlock
671 spin_unlock(&priv->rf_ps_lock);
672
673 RT_TRACE(COMP_POWER, "<===MgntActSet_RF_State()\n");
674 return bActionAllowed;
675}
676
677
diff --git a/drivers/staging/rtl8192e/r8190_rtl8256.h b/drivers/staging/rtl8192e/r8190_rtl8256.h
new file mode 100644
index 00000000000..58f92903fca
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8190_rtl8256.h
@@ -0,0 +1,29 @@
1/* r8190_rtl8256.h - rtl8256 radio frontend
2 *
3 * This is part of the rtl8180-sa2400 driver
4 * released under the GPL (See file COPYING for details).
5 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
6 *
7 * Many thanks to Realtek Corp. for their great support!
8 */
9
10#ifndef RTL8225_H
11#define RTL8225_H
12
13#define RTL819X_TOTAL_RF_PATH 2 /* for 8192E */
14
15void PHY_SetRF8256Bandwidth(struct r8192_priv *priv,
16 HT_CHANNEL_WIDTH Bandwidth);
17
18RT_STATUS PHY_RF8256_Config(struct r8192_priv *priv);
19
20RT_STATUS phy_RF8256_Config_ParaFile(struct r8192_priv *priv);
21
22void PHY_SetRF8256CCKTxPower(struct r8192_priv *priv, u8 powerlevel);
23void PHY_SetRF8256OFDMTxPower(struct r8192_priv *priv, u8 powerlevel);
24
25bool MgntActSet_RF_State(struct r8192_priv *priv,
26 RT_RF_POWER_STATE StateToSet,
27 RT_RF_CHANGE_SOURCE ChangeSource);
28
29#endif /* RTL8225_H */
diff --git a/drivers/staging/rtl8192e/r8192E.h b/drivers/staging/rtl8192e/r8192E.h
new file mode 100644
index 00000000000..137f66b034b
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8192E.h
@@ -0,0 +1,1148 @@
1/*
2 This is part of rtl8187 OpenSource driver.
3 Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it>
4 Released under the terms of GPL (General Public Licence)
5
6 Parts of this driver are based on the GPL part of the
7 official realtek driver
8
9 Parts of this driver are based on the rtl8192 driver skeleton
10 from Patric Schenke & Andres Salomon
11
12 Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
13
14 We want to tanks the Authors of those projects and the Ndiswrapper
15 project Authors.
16*/
17
18#ifndef R819xU_H
19#define R819xU_H
20
21#include <linux/module.h>
22#include <linux/kernel.h>
23#include <linux/init.h>
24#include <linux/ioport.h>
25#include <linux/sched.h>
26#include <linux/types.h>
27#include <linux/slab.h>
28#include <linux/netdevice.h>
29#include <linux/pci.h>
30#include <linux/etherdevice.h>
31#include <linux/delay.h>
32#include <linux/rtnetlink.h> //for rtnl_lock()
33#include <linux/wireless.h>
34#include <linux/timer.h>
35#include <linux/proc_fs.h> // Necessary because we use the proc fs
36#include <linux/if_arp.h>
37#include <linux/random.h>
38#include <linux/interrupt.h>
39#include <asm/io.h>
40#include "ieee80211/rtl819x_HT.h"
41#include "ieee80211/ieee80211.h"
42
43
44
45
46#define RTL819xE_MODULE_NAME "rtl819xE"
47
48#define FALSE 0
49#define TRUE 1
50#define MAX_KEY_LEN 61
51#define KEY_BUF_SIZE 5
52
53#define BIT0 0x00000001
54#define BIT1 0x00000002
55#define BIT2 0x00000004
56#define BIT3 0x00000008
57#define BIT4 0x00000010
58#define BIT5 0x00000020
59#define BIT6 0x00000040
60#define BIT7 0x00000080
61#define BIT8 0x00000100
62#define BIT9 0x00000200
63#define BIT10 0x00000400
64#define BIT11 0x00000800
65#define BIT12 0x00001000
66#define BIT13 0x00002000
67#define BIT14 0x00004000
68#define BIT15 0x00008000
69#define BIT16 0x00010000
70#define BIT17 0x00020000
71#define BIT18 0x00040000
72#define BIT19 0x00080000
73#define BIT20 0x00100000
74#define BIT21 0x00200000
75#define BIT22 0x00400000
76#define BIT23 0x00800000
77#define BIT24 0x01000000
78#define BIT25 0x02000000
79#define BIT26 0x04000000
80#define BIT27 0x08000000
81#define BIT28 0x10000000
82#define BIT29 0x20000000
83#define BIT30 0x40000000
84#define BIT31 0x80000000
85// Rx smooth factor
86#define Rx_Smooth_Factor 20
87/* 2007/06/04 MH Define sliding window for RSSI history. */
88#define PHY_RSSI_SLID_WIN_MAX 100
89#define PHY_Beacon_RSSI_SLID_WIN_MAX 10
90
91#define IC_VersionCut_D 0x3
92#define IC_VersionCut_E 0x4
93
94#if 0 //we need to use RT_TRACE instead DMESG as RT_TRACE will clearly show debug level wb.
95#define DMESG(x,a...) printk(KERN_INFO RTL819xE_MODULE_NAME ": " x "\n", ## a)
96#else
97#define DMESG(x,a...)
98extern u32 rt_global_debug_component;
99#define RT_TRACE(component, x, args...) \
100do { if(rt_global_debug_component & component) \
101 printk(KERN_DEBUG RTL819xE_MODULE_NAME ":" x , \
102 ##args);\
103}while(0);
104
105#define COMP_TRACE BIT0 // For function call tracing.
106#define COMP_DBG BIT1 // Only for temporary debug message.
107#define COMP_INIT BIT2 // during driver initialization / halt / reset.
108
109
110#define COMP_RECV BIT3 // Reveive part data path.
111#define COMP_SEND BIT4 // Send part path.
112#define COMP_IO BIT5 // I/O Related. Added by Annie, 2006-03-02.
113#define COMP_POWER BIT6 // 802.11 Power Save mode or System/Device Power state related.
114#define COMP_EPROM BIT7 // 802.11 link related: join/start BSS, leave BSS.
115#define COMP_SWBW BIT8 // For bandwidth switch.
116#define COMP_SEC BIT9// For Security.
117
118
119#define COMP_TURBO BIT10 // For Turbo Mode related. By Annie, 2005-10-21.
120#define COMP_QOS BIT11 // For QoS.
121
122#define COMP_RATE BIT12 // For Rate Adaptive mechanism, 2006.07.02, by rcnjko. #define COMP_EVENTS 0x00000080 // Event handling
123#define COMP_RXDESC BIT13 // Show Rx desc information for SD3 debug. Added by Annie, 2006-07-15.
124#define COMP_PHY BIT14
125#define COMP_DIG BIT15 // For DIG, 2006.09.25, by rcnjko.
126#define COMP_TXAGC BIT16 // For Tx power, 060928, by rcnjko.
127#define COMP_HALDM BIT17 // For HW Dynamic Mechanism, 061010, by rcnjko.
128#define COMP_POWER_TRACKING BIT18 //FOR 8190 TX POWER TRACKING
129#define COMP_EVENTS BIT19 // Event handling
130
131#define COMP_RF BIT20 // For RF.
132
133/* 11n or 8190 specific code should be put below this line */
134
135
136#define COMP_FIRMWARE BIT21 //for firmware downloading
137#define COMP_HT BIT22 // For 802.11n HT related information. by Emily 2006-8-11
138
139#define COMP_RESET BIT23
140#define COMP_CMDPKT BIT24
141#define COMP_SCAN BIT25
142#define COMP_IPS BIT26
143#define COMP_DOWN BIT27 // for rm driver module
144#define COMP_INTR BIT28 // for interrupt
145#define COMP_ERR BIT31 // for error out, always on
146#endif
147
148
149//
150// Queue Select Value in TxDesc
151//
152#define QSLT_BK 0x1
153#define QSLT_BE 0x0
154#define QSLT_VI 0x4
155#define QSLT_VO 0x6
156#define QSLT_BEACON 0x10
157#define QSLT_HIGH 0x11
158#define QSLT_MGNT 0x12
159#define QSLT_CMD 0x13
160
161#define DESC90_RATE1M 0x00
162#define DESC90_RATE2M 0x01
163#define DESC90_RATE5_5M 0x02
164#define DESC90_RATE11M 0x03
165#define DESC90_RATE6M 0x04
166#define DESC90_RATE9M 0x05
167#define DESC90_RATE12M 0x06
168#define DESC90_RATE18M 0x07
169#define DESC90_RATE24M 0x08
170#define DESC90_RATE36M 0x09
171#define DESC90_RATE48M 0x0a
172#define DESC90_RATE54M 0x0b
173#define DESC90_RATEMCS0 0x00
174#define DESC90_RATEMCS1 0x01
175#define DESC90_RATEMCS2 0x02
176#define DESC90_RATEMCS3 0x03
177#define DESC90_RATEMCS4 0x04
178#define DESC90_RATEMCS5 0x05
179#define DESC90_RATEMCS6 0x06
180#define DESC90_RATEMCS7 0x07
181#define DESC90_RATEMCS8 0x08
182#define DESC90_RATEMCS9 0x09
183#define DESC90_RATEMCS10 0x0a
184#define DESC90_RATEMCS11 0x0b
185#define DESC90_RATEMCS12 0x0c
186#define DESC90_RATEMCS13 0x0d
187#define DESC90_RATEMCS14 0x0e
188#define DESC90_RATEMCS15 0x0f
189#define DESC90_RATEMCS32 0x20
190
191#define RTL819X_DEFAULT_RF_TYPE RF_1T2R
192#define EEPROM_Default_LegacyHTTxPowerDiff 0x4
193#define IEEE80211_WATCH_DOG_TIME 2000
194
195typedef u32 RT_RF_CHANGE_SOURCE;
196#define RF_CHANGE_BY_SW BIT31
197#define RF_CHANGE_BY_HW BIT30
198#define RF_CHANGE_BY_PS BIT29
199#define RF_CHANGE_BY_IPS BIT28
200#define RF_CHANGE_BY_INIT 0 // Do not change the RFOff reason. Defined by Bruce, 2008-01-17.
201
202// RF state.
203typedef enum _RT_RF_POWER_STATE {
204 eRfOn,
205 eRfSleep,
206 eRfOff
207} RT_RF_POWER_STATE;
208
209typedef enum _RT_JOIN_ACTION {
210 RT_JOIN_INFRA = 1,
211 RT_JOIN_IBSS = 2,
212 RT_START_IBSS = 3,
213 RT_NO_ACTION = 4,
214} RT_JOIN_ACTION;
215
216typedef enum _IPS_CALLBACK_FUNCION {
217 IPS_CALLBACK_NONE = 0,
218 IPS_CALLBACK_MGNT_LINK_REQUEST = 1,
219 IPS_CALLBACK_JOIN_REQUEST = 2,
220} IPS_CALLBACK_FUNCION;
221
222typedef struct _RT_POWER_SAVE_CONTROL {
223 /* Inactive Power Save(IPS) : Disable RF when disconnected */
224 bool bInactivePs;
225 bool bIPSModeBackup;
226 bool bSwRfProcessing;
227 RT_RF_POWER_STATE eInactivePowerState;
228 struct work_struct InactivePsWorkItem;
229 struct timer_list InactivePsTimer;
230
231 /* Return point for join action */
232 IPS_CALLBACK_FUNCION ReturnPoint;
233
234 /* Recored Parameters for rescheduled JoinRequest */
235 bool bTmpBssDesc;
236 RT_JOIN_ACTION tmpJoinAction;
237 struct ieee80211_network tmpBssDesc;
238
239 /* Recored Parameters for rescheduled MgntLinkRequest */
240 bool bTmpScanOnly;
241 bool bTmpActiveScan;
242 bool bTmpFilterHiddenAP;
243 bool bTmpUpdateParms;
244 u8 tmpSsidBuf[33];
245 OCTET_STRING tmpSsid2Scan;
246 bool bTmpSsid2Scan;
247 u8 tmpNetworkType;
248 u8 tmpChannelNumber;
249 u16 tmpBcnPeriod;
250 u8 tmpDtimPeriod;
251 u16 tmpmCap;
252 OCTET_STRING tmpSuppRateSet;
253 u8 tmpSuppRateBuf[MAX_NUM_RATES];
254 bool bTmpSuppRate;
255 IbssParms tmpIbpm;
256 bool bTmpIbpm;
257
258 /*
259 * Leisure Power Save:
260 * Disable RF if connected but traffic is not busy
261 */
262 bool bLeisurePs;
263 u32 PowerProfile;
264 u8 LpsIdleCount;
265
266 u32 CurPsLevel;
267 u32 RegRfPsLevel;
268
269 bool bFwCtrlLPS;
270 u8 FWCtrlPSMode;
271
272 bool LinkReqInIPSRFOffPgs;
273 bool BufConnectinfoBefore;
274} RT_POWER_SAVE_CONTROL, *PRT_POWER_SAVE_CONTROL;
275
276/* For rtl819x */
277typedef struct _tx_desc_819x_pci {
278 //DWORD 0
279 u16 PktSize;
280 u8 Offset;
281 u8 Reserved1:3;
282 u8 CmdInit:1;
283 u8 LastSeg:1;
284 u8 FirstSeg:1;
285 u8 LINIP:1;
286 u8 OWN:1;
287
288 //DWORD 1
289 u8 TxFWInfoSize;
290 u8 RATid:3;
291 u8 DISFB:1;
292 u8 USERATE:1;
293 u8 MOREFRAG:1;
294 u8 NoEnc:1;
295 u8 PIFS:1;
296 u8 QueueSelect:5;
297 u8 NoACM:1;
298 u8 Resv:2;
299 u8 SecCAMID:5;
300 u8 SecDescAssign:1;
301 u8 SecType:2;
302
303 //DWORD 2
304 u16 TxBufferSize;
305 u8 PktId:7;
306 u8 Resv1:1;
307 u8 Reserved2;
308
309 //DWORD 3
310 u32 TxBuffAddr;
311
312 //DWORD 4
313 u32 NextDescAddress;
314
315 //DWORD 5,6,7
316 u32 Reserved5;
317 u32 Reserved6;
318 u32 Reserved7;
319}tx_desc_819x_pci, *ptx_desc_819x_pci;
320
321
322typedef struct _tx_desc_cmd_819x_pci {
323 //DWORD 0
324 u16 PktSize;
325 u8 Reserved1;
326 u8 CmdType:3;
327 u8 CmdInit:1;
328 u8 LastSeg:1;
329 u8 FirstSeg:1;
330 u8 LINIP:1;
331 u8 OWN:1;
332
333 //DOWRD 1
334 u16 ElementReport;
335 u16 Reserved2;
336
337 //DOWRD 2
338 u16 TxBufferSize;
339 u16 Reserved3;
340
341 //DWORD 3,4,5
342 u32 TxBufferAddr;
343 u32 NextDescAddress;
344 u32 Reserved4;
345 u32 Reserved5;
346 u32 Reserved6;
347}tx_desc_cmd_819x_pci, *ptx_desc_cmd_819x_pci;
348
349
350typedef struct _tx_fwinfo_819x_pci {
351 //DOWRD 0
352 u8 TxRate:7;
353 u8 CtsEnable:1;
354 u8 RtsRate:7;
355 u8 RtsEnable:1;
356 u8 TxHT:1;
357 u8 Short:1; //Short PLCP for CCK, or short GI for 11n MCS
358 u8 TxBandwidth:1; // This is used for HT MCS rate only.
359 u8 TxSubCarrier:2; // This is used for legacy OFDM rate only.
360 u8 STBC:2;
361 u8 AllowAggregation:1;
362 u8 RtsHT:1; //Interpre RtsRate field as high throughput data rate
363 u8 RtsShort:1; //Short PLCP for CCK, or short GI for 11n MCS
364 u8 RtsBandwidth:1; // This is used for HT MCS rate only.
365 u8 RtsSubcarrier:2; // This is used for legacy OFDM rate only.
366 u8 RtsSTBC:2;
367 u8 EnableCPUDur:1; //Enable firmware to recalculate and assign packet duration
368
369 //DWORD 1
370 u8 RxMF:2;
371 u8 RxAMD:3;
372 u8 Reserved1:3;
373 u8 Reserved2;
374 u8 Reserved3;
375 u8 Reserved4;
376
377 //u32 Reserved;
378}tx_fwinfo_819x_pci, *ptx_fwinfo_819x_pci;
379
380typedef struct _rx_desc_819x_pci{
381 //DOWRD 0
382 u16 Length:14;
383 u16 CRC32:1;
384 u16 ICV:1;
385 u8 RxDrvInfoSize;
386 u8 Shift:2;
387 u8 PHYStatus:1;
388 u8 SWDec:1;
389 u8 LastSeg:1;
390 u8 FirstSeg:1;
391 u8 EOR:1;
392 u8 OWN:1;
393
394 //DWORD 1
395 u32 Reserved2;
396
397 //DWORD 2
398 u32 Reserved3;
399
400 //DWORD 3
401 u32 BufferAddress;
402
403}rx_desc_819x_pci, *prx_desc_819x_pci;
404
405typedef struct _rx_fwinfo_819x_pci{
406 //DWORD 0
407 u16 Reserved1:12;
408 u16 PartAggr:1;
409 u16 FirstAGGR:1;
410 u16 Reserved2:2;
411
412 u8 RxRate:7;
413 u8 RxHT:1;
414
415 u8 BW:1;
416 u8 SPLCP:1;
417 u8 Reserved3:2;
418 u8 PAM:1;
419 u8 Mcast:1;
420 u8 Bcast:1;
421 u8 Reserved4:1;
422
423 //DWORD 1
424 u32 TSFL;
425
426}rx_fwinfo_819x_pci, *prx_fwinfo_819x_pci;
427
428#define MAX_DEV_ADDR_SIZE 8 /* support till 64 bit bus width OS */
429#define MAX_FIRMWARE_INFORMATION_SIZE 32 /*2006/04/30 by Emily forRTL8190*/
430#define MAX_802_11_HEADER_LENGTH (40 + MAX_FIRMWARE_INFORMATION_SIZE)
431#define ENCRYPTION_MAX_OVERHEAD 128
432#define MAX_FRAGMENT_COUNT 8
433#define MAX_TRANSMIT_BUFFER_SIZE (1600+(MAX_802_11_HEADER_LENGTH+ENCRYPTION_MAX_OVERHEAD)*MAX_FRAGMENT_COUNT)
434
435#define scrclng 4 // octets for crc32 (FCS, ICV)
436/* 8190 Loopback Mode definition */
437typedef enum _rtl819x_loopback{
438 RTL819X_NO_LOOPBACK = 0,
439 RTL819X_MAC_LOOPBACK = 1,
440 RTL819X_DMA_LOOPBACK = 2,
441 RTL819X_CCK_LOOPBACK = 3,
442}rtl819x_loopback_e;
443
444/* due to rtl8192 firmware */
445typedef enum _desc_packet_type_e{
446 DESC_PACKET_TYPE_INIT = 0,
447 DESC_PACKET_TYPE_NORMAL = 1,
448}desc_packet_type_e;
449
450typedef enum _firmware_status{
451 FW_STATUS_0_INIT = 0,
452 FW_STATUS_1_MOVE_BOOT_CODE = 1,
453 FW_STATUS_2_MOVE_MAIN_CODE = 2,
454 FW_STATUS_3_TURNON_CPU = 3,
455 FW_STATUS_4_MOVE_DATA_CODE = 4,
456 FW_STATUS_5_READY = 5,
457}firmware_status_e;
458
459typedef struct _rt_firmware{
460 firmware_status_e firmware_status;
461 u16 cmdpacket_frag_thresold;
462#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000 //64k
463#define MAX_FW_INIT_STEP 3
464 u8 firmware_buf[MAX_FW_INIT_STEP][RTL8190_MAX_FIRMWARE_CODE_SIZE];
465 u16 firmware_buf_size[MAX_FW_INIT_STEP];
466}rt_firmware, *prt_firmware;
467
468#define MAX_RECEIVE_BUFFER_SIZE 9100 // Add this to 9100 bytes to receive A-MSDU from RT-AP
469
470/* Firmware Queue Layout */
471#define NUM_OF_FIRMWARE_QUEUE 10
472#define NUM_OF_PAGES_IN_FW 0x100
473#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x0aa
474#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x007
475#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x024
476#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x007
477#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0
478#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x2
479#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x10
480#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0
481#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x4
482#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xd
483#define APPLIED_RESERVED_QUEUE_IN_FW 0x80000000
484#define RSVD_FW_QUEUE_PAGE_BK_SHIFT 0x00
485#define RSVD_FW_QUEUE_PAGE_BE_SHIFT 0x08
486#define RSVD_FW_QUEUE_PAGE_VI_SHIFT 0x10
487#define RSVD_FW_QUEUE_PAGE_VO_SHIFT 0x18
488#define RSVD_FW_QUEUE_PAGE_MGNT_SHIFT 0x10
489#define RSVD_FW_QUEUE_PAGE_CMD_SHIFT 0x08
490#define RSVD_FW_QUEUE_PAGE_BCN_SHIFT 0x00
491#define RSVD_FW_QUEUE_PAGE_PUB_SHIFT 0x08
492
493#define DCAM 0xAC // Debug CAM Interface
494#define AESMSK_FC 0xB2 // AES Mask register for frame control (0xB2~0xB3). Added by Annie, 2006-03-06.
495
496
497#define CAM_CONTENT_COUNT 8
498#define CFG_VALID BIT15
499#define EPROM_93c46 0
500#define EPROM_93c56 1
501
502#define DEFAULT_FRAG_THRESHOLD 2342U
503#define MIN_FRAG_THRESHOLD 256U
504#define DEFAULT_BEACONINTERVAL 0x64U
505
506#define DEFAULT_RETRY_RTS 7
507#define DEFAULT_RETRY_DATA 7
508
509#define PHY_RSSI_SLID_WIN_MAX 100
510
511
512typedef enum _WIRELESS_MODE {
513 WIRELESS_MODE_UNKNOWN = 0x00,
514 WIRELESS_MODE_A = 0x01,
515 WIRELESS_MODE_B = 0x02,
516 WIRELESS_MODE_G = 0x04,
517 WIRELESS_MODE_AUTO = 0x08,
518 WIRELESS_MODE_N_24G = 0x10,
519 WIRELESS_MODE_N_5G = 0x20
520} WIRELESS_MODE;
521
522#define RTL_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30
523
524typedef struct buffer
525{
526 struct buffer *next;
527 u32 *buf;
528 dma_addr_t dma;
529
530} buffer;
531
532typedef struct _rt_9x_tx_rate_history {
533 u32 cck[4];
534 u32 ofdm[8];
535 // HT_MCS[0][]: BW=0 SG=0
536 // HT_MCS[1][]: BW=1 SG=0
537 // HT_MCS[2][]: BW=0 SG=1
538 // HT_MCS[3][]: BW=1 SG=1
539 u32 ht_mcs[4][16];
540}rt_tx_rahis_t, *prt_tx_rahis_t;
541
542typedef struct _RT_SMOOTH_DATA_4RF {
543 char elements[4][100];//array to store values
544 u32 index; //index to current array to store
545 u32 TotalNum; //num of valid elements
546 u32 TotalVal[4]; //sum of valid elements
547}RT_SMOOTH_DATA_4RF, *PRT_SMOOTH_DATA_4RF;
548
549typedef enum _tag_TxCmd_Config_Index{
550 TXCMD_TXRA_HISTORY_CTRL = 0xFF900000,
551 TXCMD_RESET_TX_PKT_BUFF = 0xFF900001,
552 TXCMD_RESET_RX_PKT_BUFF = 0xFF900002,
553 TXCMD_SET_TX_DURATION = 0xFF900003,
554 TXCMD_SET_RX_RSSI = 0xFF900004,
555 TXCMD_SET_TX_PWR_TRACKING = 0xFF900005,
556 TXCMD_XXXX_CTRL,
557}DCMD_TXCMD_OP;
558
559typedef struct Stats
560{
561 unsigned long rxrdu;
562 unsigned long rxok;
563 unsigned long received_rate_histogram[4][32]; //0: Total, 1:OK, 2:CRC, 3:ICV
564 unsigned long rxoverflow;
565 unsigned long rxint;
566 unsigned long txoverflow;
567 unsigned long txbeokint;
568 unsigned long txbkokint;
569 unsigned long txviokint;
570 unsigned long txvookint;
571 unsigned long txbeaconokint;
572 unsigned long txbeaconerr;
573 unsigned long txmanageokint;
574 unsigned long txcmdpktokint;
575 unsigned long txfeedback;
576 unsigned long txfeedbackok;
577 unsigned long txoktotal;
578 unsigned long txbytesunicast;
579 unsigned long rxbytesunicast;
580
581 unsigned long slide_signal_strength[100];
582 unsigned long slide_evm[100];
583 unsigned long slide_rssi_total; // For recording sliding window's RSSI value
584 unsigned long slide_evm_total; // For recording sliding window's EVM value
585 long signal_strength; // Transformed, in dbm. Beautified signal strength for UI, not correct.
586 u8 rx_rssi_percentage[4];
587 u8 rx_evm_percentage[2];
588 u32 Slide_Beacon_pwdb[100];
589 u32 Slide_Beacon_Total;
590 RT_SMOOTH_DATA_4RF cck_adc_pwdb;
591} Stats;
592
593
594// Bandwidth Offset
595#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0
596#define HAL_PRIME_CHNL_OFFSET_LOWER 1
597#define HAL_PRIME_CHNL_OFFSET_UPPER 2
598
599typedef struct ChnlAccessSetting {
600 u16 SIFS_Timer;
601 u16 DIFS_Timer;
602 u16 SlotTimeTimer;
603 u16 EIFS_Timer;
604 u16 CWminIndex;
605 u16 CWmaxIndex;
606}*PCHANNEL_ACCESS_SETTING,CHANNEL_ACCESS_SETTING;
607
608typedef struct _BB_REGISTER_DEFINITION{
609 u32 rfintfs; // set software control: // 0x870~0x877[8 bytes]
610 u32 rfintfi; // readback data: // 0x8e0~0x8e7[8 bytes]
611 u32 rfintfo; // output data: // 0x860~0x86f [16 bytes]
612 u32 rfintfe; // output enable: // 0x860~0x86f [16 bytes]
613 u32 rf3wireOffset; // LSSI data: // 0x840~0x84f [16 bytes]
614 u32 rfLSSI_Select; // BB Band Select: // 0x878~0x87f [8 bytes]
615 u32 rfTxGainStage; // Tx gain stage: // 0x80c~0x80f [4 bytes]
616 u32 rfHSSIPara1; // wire parameter control1 : // 0x820~0x823,0x828~0x82b, 0x830~0x833, 0x838~0x83b [16 bytes]
617 u32 rfHSSIPara2; // wire parameter control2 : // 0x824~0x827,0x82c~0x82f, 0x834~0x837, 0x83c~0x83f [16 bytes]
618 u32 rfSwitchControl; //Tx Rx antenna control : // 0x858~0x85f [16 bytes]
619 u32 rfAGCControl1; //AGC parameter control1 : // 0xc50~0xc53,0xc58~0xc5b, 0xc60~0xc63, 0xc68~0xc6b [16 bytes]
620 u32 rfAGCControl2; //AGC parameter control2 : // 0xc54~0xc57,0xc5c~0xc5f, 0xc64~0xc67, 0xc6c~0xc6f [16 bytes]
621 u32 rfRxIQImbalance; //OFDM Rx IQ imbalance matrix : // 0xc14~0xc17,0xc1c~0xc1f, 0xc24~0xc27, 0xc2c~0xc2f [16 bytes]
622 u32 rfRxAFE; //Rx IQ DC ofset and Rx digital filter, Rx DC notch filter : // 0xc10~0xc13,0xc18~0xc1b, 0xc20~0xc23, 0xc28~0xc2b [16 bytes]
623 u32 rfTxIQImbalance; //OFDM Tx IQ imbalance matrix // 0xc80~0xc83,0xc88~0xc8b, 0xc90~0xc93, 0xc98~0xc9b [16 bytes]
624 u32 rfTxAFE; //Tx IQ DC Offset and Tx DFIR type // 0xc84~0xc87,0xc8c~0xc8f, 0xc94~0xc97, 0xc9c~0xc9f [16 bytes]
625 u32 rfLSSIReadBack; //LSSI RF readback data // 0x8a0~0x8af [16 bytes]
626}BB_REGISTER_DEFINITION_T, *PBB_REGISTER_DEFINITION_T;
627
628typedef struct _rate_adaptive
629{
630 u8 rate_adaptive_disabled;
631 u8 ratr_state;
632 u16 reserve;
633
634 u32 high_rssi_thresh_for_ra;
635 u32 high2low_rssi_thresh_for_ra;
636 u8 low2high_rssi_thresh_for_ra40M;
637 u32 low_rssi_thresh_for_ra40M;
638 u8 low2high_rssi_thresh_for_ra20M;
639 u32 low_rssi_thresh_for_ra20M;
640 u32 upper_rssi_threshold_ratr;
641 u32 middle_rssi_threshold_ratr;
642 u32 low_rssi_threshold_ratr;
643 u32 low_rssi_threshold_ratr_40M;
644 u32 low_rssi_threshold_ratr_20M;
645 u8 ping_rssi_enable; //cosa add for test
646 u32 ping_rssi_ratr; //cosa add for test
647 u32 ping_rssi_thresh_for_ra;//cosa add for test
648 u32 last_ratr;
649
650} rate_adaptive, *prate_adaptive;
651#define TxBBGainTableLength 37
652#define CCKTxBBGainTableLength 23
653typedef struct _txbbgain_struct
654{
655 long txbb_iq_amplifygain;
656 u32 txbbgain_value;
657} txbbgain_struct, *ptxbbgain_struct;
658
659typedef struct _ccktxbbgain_struct
660{
661 //The Value is from a22 to a29 one Byte one time is much Safer
662 u8 ccktxbb_valuearray[8];
663} ccktxbbgain_struct,*pccktxbbgain_struct;
664
665
666typedef struct _init_gain
667{
668 u8 xaagccore1;
669 u8 xbagccore1;
670 u8 xcagccore1;
671 u8 xdagccore1;
672 u8 cca;
673
674} init_gain, *pinit_gain;
675
676/* 2007/11/02 MH Define RF mode temporarily for test. */
677typedef enum tag_Rf_Operatetion_State
678{
679 RF_STEP_INIT = 0,
680 RF_STEP_NORMAL,
681 RF_STEP_MAX
682}RF_STEP_E;
683
684typedef enum _RT_STATUS{
685 RT_STATUS_SUCCESS,
686 RT_STATUS_FAILURE,
687 RT_STATUS_PENDING,
688 RT_STATUS_RESOURCE
689}RT_STATUS,*PRT_STATUS;
690
691typedef enum _RT_CUSTOMER_ID
692{
693 RT_CID_DEFAULT = 0,
694 RT_CID_8187_ALPHA0 = 1,
695 RT_CID_8187_SERCOMM_PS = 2,
696 RT_CID_8187_HW_LED = 3,
697 RT_CID_8187_NETGEAR = 4,
698 RT_CID_WHQL = 5,
699 RT_CID_819x_CAMEO = 6,
700 RT_CID_819x_RUNTOP = 7,
701 RT_CID_819x_Senao = 8,
702 RT_CID_TOSHIBA = 9, // Merge by Jacken, 2008/01/31.
703 RT_CID_819x_Netcore = 10,
704 RT_CID_Nettronix = 11,
705 RT_CID_DLINK = 12,
706 RT_CID_PRONET = 13,
707 RT_CID_COREGA = 14,
708}RT_CUSTOMER_ID, *PRT_CUSTOMER_ID;
709
710/* LED customization. */
711
712typedef enum _LED_STRATEGY_8190{
713 SW_LED_MODE0, // SW control 1 LED via GPIO0. It is default option.
714 SW_LED_MODE1, // SW control for PCI Express
715 SW_LED_MODE2, // SW control for Cameo.
716 SW_LED_MODE3, // SW contorl for RunTop.
717 SW_LED_MODE4, // SW control for Netcore
718 SW_LED_MODE5, //added by vivi, for led new mode, DLINK
719 SW_LED_MODE6, //added by vivi, for led new mode, PRONET
720 HW_LED, // HW control 2 LEDs, LED0 and LED1 (there are 4 different control modes)
721}LED_STRATEGY_8190, *PLED_STRATEGY_8190;
722
723#define CHANNEL_PLAN_LEN 10
724
725#define sCrcLng 4
726
727typedef struct _TX_FWINFO_STRUCUTRE{
728 //DOWRD 0
729 u8 TxRate:7;
730 u8 CtsEnable:1;
731 u8 RtsRate:7;
732 u8 RtsEnable:1;
733 u8 TxHT:1;
734 u8 Short:1;
735 u8 TxBandwidth:1;
736 u8 TxSubCarrier:2;
737 u8 STBC:2;
738 u8 AllowAggregation:1;
739 u8 RtsHT:1;
740 u8 RtsShort:1;
741 u8 RtsBandwidth:1;
742 u8 RtsSubcarrier:2;
743 u8 RtsSTBC:2;
744 u8 EnableCPUDur:1;
745
746 //DWORD 1
747 u32 RxMF:2;
748 u32 RxAMD:3;
749 u32 Reserved1:3;
750 u32 TxAGCOffset:4;
751 u32 TxAGCSign:1;
752 u32 Tx_INFO_RSVD:6;
753 u32 PacketID:13;
754}TX_FWINFO_T;
755
756
757typedef struct _TX_FWINFO_8190PCI{
758 //DOWRD 0
759 u8 TxRate:7;
760 u8 CtsEnable:1;
761 u8 RtsRate:7;
762 u8 RtsEnable:1;
763 u8 TxHT:1;
764 u8 Short:1; //Short PLCP for CCK, or short GI for 11n MCS
765 u8 TxBandwidth:1; // This is used for HT MCS rate only.
766 u8 TxSubCarrier:2; // This is used for legacy OFDM rate only.
767 u8 STBC:2;
768 u8 AllowAggregation:1;
769 u8 RtsHT:1; //Interpre RtsRate field as high throughput data rate
770 u8 RtsShort:1; //Short PLCP for CCK, or short GI for 11n MCS
771 u8 RtsBandwidth:1; // This is used for HT MCS rate only.
772 u8 RtsSubcarrier:2; // This is used for legacy OFDM rate only.
773 u8 RtsSTBC:2;
774 u8 EnableCPUDur:1; //Enable firmware to recalculate and assign packet duration
775
776 //DWORD 1
777 u32 RxMF:2;
778 u32 RxAMD:3;
779 u32 TxPerPktInfoFeedback:1; // 1: indicate that the transimission info of this packet should be gathered by Firmware and retured by Rx Cmd.
780 u32 Reserved1:2;
781 u32 TxAGCOffset:4; // Only 90 support
782 u32 TxAGCSign:1; // Only 90 support
783 u32 RAW_TXD:1; // MAC will send data in txpktbuffer without any processing,such as CRC check
784 u32 Retry_Limit:4; // CCX Support relative retry limit FW page only support 4 bits now.
785 u32 Reserved2:1;
786 u32 PacketID:13;
787
788 // DW 2
789
790}TX_FWINFO_8190PCI, *PTX_FWINFO_8190PCI;
791
792typedef struct _phy_ofdm_rx_status_report_819xpci
793{
794 u8 trsw_gain_X[4];
795 u8 pwdb_all;
796 u8 cfosho_X[4];
797 u8 cfotail_X[4];
798 u8 rxevm_X[2];
799 u8 rxsnr_X[4];
800 u8 pdsnr_X[2];
801 u8 csi_current_X[2];
802 u8 csi_target_X[2];
803 u8 sigevm;
804 u8 max_ex_pwr;
805 u8 sgi_en;
806 u8 rxsc_sgien_exflg;
807}phy_sts_ofdm_819xpci_t;
808
809typedef struct _phy_cck_rx_status_report_819xpci
810{
811 /* For CCK rate descriptor. This is a unsigned 8:1 variable. LSB bit presend
812 0.5. And MSB 7 bts presend a signed value. Range from -64~+63.5. */
813 u8 adc_pwdb_X[4];
814 u8 sq_rpt;
815 u8 cck_agc_rpt;
816}phy_sts_cck_819xpci_t;
817
818typedef struct _phy_ofdm_rx_status_rxsc_sgien_exintfflag{
819 u8 reserved:4;
820 u8 rxsc:2;
821 u8 sgi_en:1;
822 u8 ex_intf_flag:1;
823}phy_ofdm_rx_status_rxsc_sgien_exintfflag;
824
825typedef enum _RT_OP_MODE{
826 RT_OP_MODE_AP,
827 RT_OP_MODE_INFRASTRUCTURE,
828 RT_OP_MODE_IBSS,
829 RT_OP_MODE_NO_LINK,
830}RT_OP_MODE, *PRT_OP_MODE;
831
832
833/* 2007/11/02 MH Define RF mode temporarily for test. */
834typedef enum tag_Rf_OpType
835{
836 RF_OP_By_SW_3wire = 0,
837 RF_OP_By_FW,
838 RF_OP_MAX
839}RF_OpType_E;
840
841typedef enum _RESET_TYPE {
842 RESET_TYPE_NORESET = 0x00,
843 RESET_TYPE_NORMAL = 0x01,
844 RESET_TYPE_SILENT = 0x02
845} RESET_TYPE;
846
847typedef struct _tx_ring{
848 u32 * desc;
849 u8 nStuckCount;
850 struct _tx_ring * next;
851}__attribute__ ((packed)) tx_ring, * ptx_ring;
852
853struct rtl8192_tx_ring {
854 tx_desc_819x_pci *desc;
855 dma_addr_t dma;
856 unsigned int idx;
857 unsigned int entries;
858 struct sk_buff_head queue;
859};
860
861#define NIC_SEND_HANG_THRESHOLD_NORMAL 4
862#define NIC_SEND_HANG_THRESHOLD_POWERSAVE 8
863#define MAX_TX_QUEUE 9 // BK, BE, VI, VO, HCCA, MANAGEMENT, COMMAND, HIGH, BEACON.
864
865#define MAX_RX_COUNT 64
866#define MAX_TX_QUEUE_COUNT 9
867
868typedef struct r8192_priv
869{
870 struct pci_dev *pdev;
871 u8 *mem_start;
872
873 /* maintain info from eeprom */
874 short epromtype;
875 u16 eeprom_vid;
876 u16 eeprom_did;
877 u8 eeprom_CustomerID;
878 u16 eeprom_ChannelPlan;
879 RT_CUSTOMER_ID CustomerID;
880 u8 IC_Cut;
881 int irq;
882 struct ieee80211_device *ieee80211;
883#ifdef ENABLE_LPS
884 bool ps_force;
885 bool force_lps;
886 bool bdisable_nic;
887#endif
888 bool being_init_adapter;
889 u8 Rf_Mode;
890 u8 card_8192_version; /* if TCR reports card V B/C this discriminates */
891 spinlock_t irq_th_lock;
892 spinlock_t rf_ps_lock;
893 struct mutex mutex;
894
895 short chan;
896 short sens;
897 /* RX stuff */
898 rx_desc_819x_pci *rx_ring;
899 dma_addr_t rx_ring_dma;
900 unsigned int rx_idx;
901 struct sk_buff *rx_buf[MAX_RX_COUNT];
902 int rxringcount;
903 u16 rxbuffersize;
904
905 /* TX stuff */
906 struct rtl8192_tx_ring tx_ring[MAX_TX_QUEUE_COUNT];
907 int txringcount;
908
909 struct tasklet_struct irq_rx_tasklet;
910 struct tasklet_struct irq_tx_tasklet;
911 struct tasklet_struct irq_prepare_beacon_tasklet;
912
913 short up;
914 short crcmon; //if 1 allow bad crc frame reception in monitor mode
915 struct semaphore wx_sem;
916 struct semaphore rf_sem; //used to lock rf write operation added by wb, modified by david
917 u8 rf_type; /* 0 means 1T2R, 1 means 2T4R */
918
919 short (*rf_set_sens)(struct net_device *dev, short sens);
920 u8 (*rf_set_chan)(struct ieee80211_device *ieee80211, u8 ch);
921 short promisc;
922 /* stats */
923 struct Stats stats;
924 struct iw_statistics wstats;
925 struct proc_dir_entry *dir_dev;
926 struct ieee80211_rx_stats previous_stats;
927
928 /* RX stuff */
929 struct sk_buff_head skb_queue;
930 struct work_struct qos_activate;
931
932 //2 Tx Related variables
933 u16 ShortRetryLimit;
934 u16 LongRetryLimit;
935
936 u32 LastRxDescTSFHigh;
937 u32 LastRxDescTSFLow;
938
939
940 //2 Rx Related variables
941 u32 ReceiveConfig;
942
943 u8 retry_data;
944 u8 retry_rts;
945
946 struct work_struct reset_wq;
947 u8 rx_chk_cnt;
948
949//for rtl819xPci
950 // Data Rate Config. Added by Annie, 2006-04-13.
951 u16 basic_rate;
952 u8 short_preamble;
953 u8 slot_time;
954 u16 SifsTime;
955/* WirelessMode*/
956 u8 RegWirelessMode;
957/*Firmware*/
958 prt_firmware pFirmware;
959 rtl819x_loopback_e LoopbackMode;
960 bool AutoloadFailFlag;
961 u16 EEPROMAntPwDiff; // Antenna gain offset from B/C/D to A
962 u8 EEPROMThermalMeter;
963 u8 EEPROMCrystalCap;
964 u8 EEPROMTxPowerLevelCCK[14];// CCK channel 1~14
965 // The following definition is for eeprom 93c56
966 u8 EEPROMRfACCKChnl1TxPwLevel[3]; //RF-A CCK Tx Power Level at channel 7
967 u8 EEPROMRfAOfdmChnlTxPwLevel[3];//RF-A CCK Tx Power Level at [0],[1],[2] = channel 1,7,13
968 u8 EEPROMRfCCCKChnl1TxPwLevel[3]; //RF-C CCK Tx Power Level at channel 7
969 u8 EEPROMRfCOfdmChnlTxPwLevel[3];//RF-C CCK Tx Power Level at [0],[1],[2] = channel 1,7,13
970 u8 EEPROMTxPowerLevelOFDM24G[14]; // OFDM 2.4G channel 1~14
971 u8 EEPROMLegacyHTTxPowerDiff; // Legacy to HT rate power diff
972 bool bTXPowerDataReadFromEEPORM;
973/*channel plan*/
974 u16 RegChannelPlan; // Channel Plan specifed by user, 15: following setting of EEPROM, 0-14: default channel plan index specified by user.
975 u16 ChannelPlan;
976/*PS related*/
977 // Rf off action for power save
978 u8 bHwRfOffAction; //0:No action, 1:By GPIO, 2:By Disable
979/*PHY related*/
980 BB_REGISTER_DEFINITION_T PHYRegDef[4]; //Radio A/B/C/D
981 // Read/write are allow for following hardware information variables
982 u32 MCSTxPowerLevelOriginalOffset[6];
983 u32 CCKTxPowerLevelOriginalOffset;
984 u8 TxPowerLevelCCK[14]; // CCK channel 1~14
985 u8 TxPowerLevelCCK_A[14]; // RF-A, CCK channel 1~14
986 u8 TxPowerLevelCCK_C[14];
987 u8 TxPowerLevelOFDM24G[14]; // OFDM 2.4G channel 1~14
988 u8 TxPowerLevelOFDM5G[14]; // OFDM 5G
989 u8 TxPowerLevelOFDM24G_A[14]; // RF-A, OFDM 2.4G channel 1~14
990 u8 TxPowerLevelOFDM24G_C[14]; // RF-C, OFDM 2.4G channel 1~14
991 u8 LegacyHTTxPowerDiff; // Legacy to HT rate power diff
992 u8 AntennaTxPwDiff[3]; // Antenna gain offset, index 0 for B, 1 for C, and 2 for D
993 u8 CrystalCap; // CrystalCap.
994 u8 ThermalMeter[2]; // ThermalMeter, index 0 for RFIC0, and 1 for RFIC1
995 //05/27/2008 cck power enlarge
996 u8 CckPwEnl;
997 u16 TSSI_13dBm;
998 u32 Pwr_Track;
999 u8 CCKPresentAttentuation_20Mdefault;
1000 u8 CCKPresentAttentuation_40Mdefault;
1001 char CCKPresentAttentuation_difference;
1002 char CCKPresentAttentuation;
1003 // Use to calculate PWBD.
1004 RT_RF_POWER_STATE eRFPowerState;
1005 RT_RF_CHANGE_SOURCE RfOffReason;
1006 RT_POWER_SAVE_CONTROL PowerSaveControl;
1007 u8 bCckHighPower;
1008 long undecorated_smoothed_pwdb;
1009 long undecorated_smoothed_cck_adc_pwdb[4];
1010 //for set channel
1011 u8 SwChnlInProgress;
1012 u8 SwChnlStage;
1013 u8 SwChnlStep;
1014 u8 SetBWModeInProgress;
1015 HT_CHANNEL_WIDTH CurrentChannelBW;
1016
1017 // 8190 40MHz mode
1018 //
1019 u8 nCur40MhzPrimeSC; // Control channel sub-carrier
1020 // Joseph test for shorten RF configuration time.
1021 // We save RF reg0 in this variable to reduce RF reading.
1022 //
1023 u32 RfReg0Value[4];
1024 u8 NumTotalRFPath;
1025 bool brfpath_rxenable[4];
1026//+by amy 080507
1027 struct timer_list watch_dog_timer;
1028 u8 watchdog_last_time;
1029 u8 watchdog_check_reset_cnt;
1030
1031//+by amy 080515 for dynamic mechenism
1032 //Add by amy Tx Power Control for Near/Far Range 2008/05/15
1033 bool bDynamicTxHighPower; // Tx high power state
1034 bool bDynamicTxLowPower; // Tx low power state
1035 bool bLastDTPFlag_High;
1036 bool bLastDTPFlag_Low;
1037
1038 /* OFDM RSSI. For high power or not */
1039 u8 phy_check_reg824;
1040 u32 phy_reg824_bit9;
1041
1042 //Add by amy for Rate Adaptive
1043 rate_adaptive rate_adaptive;
1044 //Add by amy for TX power tracking
1045 //2008/05/15 Mars OPEN/CLOSE TX POWER TRACKING
1046 const txbbgain_struct * txbbgain_table;
1047 u8 txpower_count;//For 6 sec do tracking again
1048 bool btxpower_trackingInit;
1049 u8 OFDM_index;
1050 u8 CCK_index;
1051 u8 Record_CCK_20Mindex;
1052 u8 Record_CCK_40Mindex;
1053 //2007/09/10 Mars Add CCK TX Power Tracking
1054 const ccktxbbgain_struct *cck_txbbgain_table;
1055 const ccktxbbgain_struct *cck_txbbgain_ch14_table;
1056 u8 rfa_txpowertrackingindex;
1057 u8 rfa_txpowertrackingindex_real;
1058 u8 rfa_txpowertracking_default;
1059 u8 rfc_txpowertrackingindex;
1060 u8 rfc_txpowertrackingindex_real;
1061 u8 rfc_txpowertracking_default;
1062 bool btxpower_tracking;
1063 bool bcck_in_ch14;
1064
1065 //For Backup Initial Gain
1066 init_gain initgain_backup;
1067 u8 DefaultInitialGain[4];
1068 // For EDCA Turbo mode, Added by amy 080515.
1069 bool bis_any_nonbepkts;
1070 bool bcurrent_turbo_EDCA;
1071
1072 bool bis_cur_rdlstate;
1073 struct timer_list fsync_timer;
1074 u32 rate_record;
1075 u32 rateCountDiffRecord;
1076 u32 ContiuneDiffCount;
1077 bool bswitch_fsync;
1078
1079 u8 framesync;
1080 u32 framesyncC34;
1081 u8 framesyncMonitor;
1082
1083 //by amy for gpio
1084 bool bHwRadioOff;
1085 //by amy for ps
1086 RT_OP_MODE OpMode;
1087 //by amy for reset_count
1088 u32 reset_count;
1089
1090 //by amy for silent reset
1091 RESET_TYPE ResetProgress;
1092 bool bForcedSilentReset;
1093 bool bDisableNormalResetCheck;
1094 u16 TxCounter;
1095 u16 RxCounter;
1096 int IrpPendingCount;
1097 bool bResetInProgress;
1098 bool force_reset;
1099 u8 InitialGainOperateType;
1100
1101 //define work item by amy 080526
1102 struct delayed_work update_beacon_wq;
1103 struct delayed_work watch_dog_wq;
1104 struct delayed_work txpower_tracking_wq;
1105 struct delayed_work rfpath_check_wq;
1106 struct delayed_work gpio_change_rf_wq;
1107 struct delayed_work initialgain_operate_wq;
1108 struct workqueue_struct *priv_wq;
1109}r8192_priv;
1110
1111bool init_firmware(struct r8192_priv *priv);
1112u32 read_cam(struct r8192_priv *priv, u8 addr);
1113void write_cam(struct r8192_priv *priv, u8 addr, u32 data);
1114u8 read_nic_byte(struct r8192_priv *priv, int x);
1115u32 read_nic_dword(struct r8192_priv *priv, int x);
1116u16 read_nic_word(struct r8192_priv *priv, int x) ;
1117void write_nic_byte(struct r8192_priv *priv, int x,u8 y);
1118void write_nic_word(struct r8192_priv *priv, int x,u16 y);
1119void write_nic_dword(struct r8192_priv *priv, int x,u32 y);
1120
1121int rtl8192_down(struct net_device *dev);
1122int rtl8192_up(struct net_device *dev);
1123void rtl8192_commit(struct r8192_priv *priv);
1124void write_phy(struct net_device *dev, u8 adr, u8 data);
1125void CamResetAllEntry(struct r8192_priv *priv);
1126void EnableHWSecurityConfig8192(struct r8192_priv *priv);
1127void setKey(struct r8192_priv *priv, u8 EntryNo, u8 KeyIndex, u16 KeyType,
1128 const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent);
1129void firmware_init_param(struct r8192_priv *priv);
1130RT_STATUS cmpk_message_handle_tx(struct r8192_priv *priv, u8 *codevirtualaddress, u32 packettype, u32 buffer_len);
1131
1132#ifdef ENABLE_IPS
1133void IPSEnter(struct r8192_priv *priv);
1134void IPSLeave(struct r8192_priv *priv);
1135void IPSLeave_wq(struct work_struct *work);
1136void ieee80211_ips_leave_wq(struct ieee80211_device *ieee80211);
1137void ieee80211_ips_leave(struct ieee80211_device *ieee80211);
1138#endif
1139#ifdef ENABLE_LPS
1140void LeisurePSEnter(struct ieee80211_device *ieee80211);
1141void LeisurePSLeave(struct ieee80211_device *ieee80211);
1142#endif
1143
1144bool NicIFEnableNIC(struct r8192_priv *priv);
1145bool NicIFDisableNIC(struct r8192_priv *priv);
1146
1147void PHY_SetRtl8192eRfOff(struct r8192_priv *priv);
1148#endif
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c
new file mode 100644
index 00000000000..94d9c8d5d09
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8192E_core.c
@@ -0,0 +1,5039 @@
1/******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3 * Linux device driver for RTL8192E
4 *
5 * Based on the r8180 driver, which is:
6 * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 * The full GNU General Public License is included in this distribution in the
21 * file called LICENSE.
22 *
23 * Contact Information:
24 * Jerry chuang <wlanfae@realtek.com>
25 */
26
27
28#include <linux/vmalloc.h>
29#include <linux/slab.h>
30#include <linux/interrupt.h>
31#include <linux/hardirq.h>
32#include <asm/uaccess.h>
33#include "r8192E_hw.h"
34#include "r8192E.h"
35#include "r8190_rtl8256.h" /* RTL8225 Radio frontend */
36#include "r8180_93cx6.h" /* Card EEPROM */
37#include "r8192E_wx.h"
38#include "r819xE_phy.h" //added by WB 4.30.2008
39#include "r819xE_phyreg.h"
40#include "r819xE_cmdpkt.h"
41#include "r8192E_dm.h"
42
43#ifdef CONFIG_PM
44#include "r8192_pm.h"
45#endif
46
47#ifdef ENABLE_DOT11D
48#include "ieee80211/dot11d.h"
49#endif
50
51//set here to open your trace code. //WB
52u32 rt_global_debug_component = COMP_ERR ; //always open err flags on
53
54static DEFINE_PCI_DEVICE_TABLE(rtl8192_pci_id_tbl) = {
55 /* Realtek */
56 { PCI_DEVICE(0x10ec, 0x8192) },
57
58 /* Corega */
59 { PCI_DEVICE(0x07aa, 0x0044) },
60 { PCI_DEVICE(0x07aa, 0x0047) },
61 {}
62};
63
64static char ifname[IFNAMSIZ] = "wlan%d";
65static int hwwep = 1; //default use hw. set 0 to use software security
66static int channels = 0x3fff;
67
68MODULE_LICENSE("GPL");
69MODULE_VERSION("V 1.1");
70MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl);
71//MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
72MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards");
73
74
75module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR);
76module_param(hwwep,int, S_IRUGO|S_IWUSR);
77module_param(channels,int, S_IRUGO|S_IWUSR);
78
79MODULE_PARM_DESC(ifname," Net interface name, wlan%d=default");
80MODULE_PARM_DESC(hwwep," Try to use hardware WEP support. Still broken and not available on all cards");
81MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI");
82
83static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
84 const struct pci_device_id *id);
85static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev);
86
87static struct pci_driver rtl8192_pci_driver = {
88 .name = RTL819xE_MODULE_NAME, /* Driver name */
89 .id_table = rtl8192_pci_id_tbl, /* PCI_ID table */
90 .probe = rtl8192_pci_probe, /* probe fn */
91 .remove = __devexit_p(rtl8192_pci_disconnect), /* remove fn */
92#ifdef CONFIG_PM
93 .suspend = rtl8192E_suspend, /* PM suspend fn */
94 .resume = rtl8192E_resume, /* PM resume fn */
95#else
96 .suspend = NULL, /* PM suspend fn */
97 .resume = NULL, /* PM resume fn */
98#endif
99};
100
101static void rtl8192_start_beacon(struct ieee80211_device *ieee80211);
102static void rtl8192_stop_beacon(struct ieee80211_device *ieee80211);
103static void rtl819x_watchdog_wqcallback(struct work_struct *work);
104static void rtl8192_irq_rx_tasklet(unsigned long arg);
105static void rtl8192_irq_tx_tasklet(unsigned long arg);
106static void rtl8192_prepare_beacon(unsigned long arg);
107static irqreturn_t rtl8192_interrupt(int irq, void *param);
108static void rtl819xE_tx_cmd(struct r8192_priv *priv, struct sk_buff *skb);
109static void rtl8192_update_ratr_table(struct r8192_priv *priv);
110static void rtl8192_restart(struct work_struct *work);
111static void watch_dog_timer_callback(unsigned long data);
112static int _rtl8192_up(struct r8192_priv *priv);
113static void rtl8192_cancel_deferred_work(struct r8192_priv* priv);
114static short rtl8192_tx(struct r8192_priv *priv, struct sk_buff* skb);
115
116#ifdef ENABLE_DOT11D
117
118typedef struct _CHANNEL_LIST
119{
120 u8 Channel[32];
121 u8 Len;
122}CHANNEL_LIST, *PCHANNEL_LIST;
123
124static const CHANNEL_LIST ChannelPlan[] = {
125 {{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}, //FCC
126 {{1,2,3,4,5,6,7,8,9,10,11},11}, //IC
127 {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, //ETSI
128 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Spain. Change to ETSI.
129 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //France. Change to ETSI.
130 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, //MKK //MKK
131 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22},//MKK1
132 {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, //Israel.
133 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, // For 11a , TELEC
134 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64}, 22}, //MIC
135 {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14} //For Global Domain. 1-11:active scan, 12-14 passive scan. //+YJ, 080626
136};
137
138static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv* priv)
139{
140 int i, max_chan=-1, min_chan=-1;
141 struct ieee80211_device* ieee = priv->ieee80211;
142 switch (channel_plan)
143 {
144 case COUNTRY_CODE_FCC:
145 case COUNTRY_CODE_IC:
146 case COUNTRY_CODE_ETSI:
147 case COUNTRY_CODE_SPAIN:
148 case COUNTRY_CODE_FRANCE:
149 case COUNTRY_CODE_MKK:
150 case COUNTRY_CODE_MKK1:
151 case COUNTRY_CODE_ISRAEL:
152 case COUNTRY_CODE_TELEC:
153 case COUNTRY_CODE_MIC:
154 {
155 Dot11d_Init(ieee);
156 ieee->bGlobalDomain = false;
157 //acturally 8225 & 8256 rf chip only support B,G,24N mode
158 min_chan = 1;
159 max_chan = 14;
160
161 if (ChannelPlan[channel_plan].Len != 0){
162 // Clear old channel map
163 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
164 // Set new channel map
165 for (i=0;i<ChannelPlan[channel_plan].Len;i++)
166 {
167 if (ChannelPlan[channel_plan].Channel[i] < min_chan || ChannelPlan[channel_plan].Channel[i] > max_chan)
168 break;
169 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1;
170 }
171 }
172 break;
173 }
174 case COUNTRY_CODE_GLOBAL_DOMAIN:
175 {
176 GET_DOT11D_INFO(ieee)->bEnabled = 0; //this flag enabled to follow 11d country IE setting, otherwise, it shall follow global domain setting
177 Dot11d_Reset(ieee);
178 ieee->bGlobalDomain = true;
179 break;
180 }
181 default:
182 break;
183 }
184}
185#endif
186
187static inline bool rx_hal_is_cck_rate(prx_fwinfo_819x_pci pdrvinfo)
188{
189 return (pdrvinfo->RxRate == DESC90_RATE1M ||
190 pdrvinfo->RxRate == DESC90_RATE2M ||
191 pdrvinfo->RxRate == DESC90_RATE5_5M ||
192 pdrvinfo->RxRate == DESC90_RATE11M) &&
193 !pdrvinfo->RxHT;
194}
195
196void CamResetAllEntry(struct r8192_priv* priv)
197{
198 write_nic_dword(priv, RWCAM, BIT31|BIT30);
199}
200
201void write_cam(struct r8192_priv *priv, u8 addr, u32 data)
202{
203 write_nic_dword(priv, WCAMI, data);
204 write_nic_dword(priv, RWCAM, BIT31|BIT16|(addr&0xff) );
205}
206
207u32 read_cam(struct r8192_priv *priv, u8 addr)
208{
209 write_nic_dword(priv, RWCAM, 0x80000000|(addr&0xff) );
210 return read_nic_dword(priv, 0xa8);
211}
212
213u8 read_nic_byte(struct r8192_priv *priv, int x)
214{
215 return 0xff & readb(priv->mem_start + x);
216}
217
218u32 read_nic_dword(struct r8192_priv *priv, int x)
219{
220 return readl(priv->mem_start + x);
221}
222
223u16 read_nic_word(struct r8192_priv *priv, int x)
224{
225 return readw(priv->mem_start + x);
226}
227
228void write_nic_byte(struct r8192_priv *priv, int x,u8 y)
229{
230 writeb(y, priv->mem_start + x);
231 udelay(20);
232}
233
234void write_nic_dword(struct r8192_priv *priv, int x,u32 y)
235{
236 writel(y, priv->mem_start + x);
237 udelay(20);
238}
239
240void write_nic_word(struct r8192_priv *priv, int x,u16 y)
241{
242 writew(y, priv->mem_start + x);
243 udelay(20);
244}
245
246u8 rtl8192e_ap_sec_type(struct ieee80211_device *ieee)
247{
248 static const u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
249 static const u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
250 int wpa_ie_len= ieee->wpa_ie_len;
251 struct ieee80211_crypt_data* crypt;
252 int encrypt;
253
254 crypt = ieee->crypt[ieee->tx_keyidx];
255
256 encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY) ||
257 (ieee->host_encrypt && crypt && crypt->ops &&
258 (0 == strcmp(crypt->ops->name,"WEP")));
259
260 /* simply judge */
261 if(encrypt && (wpa_ie_len == 0)) {
262 // wep encryption, no N mode setting */
263 return SEC_ALG_WEP;
264 } else if((wpa_ie_len != 0)) {
265 // parse pairwise key type */
266 if (((ieee->wpa_ie[0] == 0xdd) && (!memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) ||
267 ((ieee->wpa_ie[0] == 0x30) && (!memcmp(&ieee->wpa_ie[10],ccmp_rsn_ie, 4))))
268 return SEC_ALG_CCMP;
269 else
270 return SEC_ALG_TKIP;
271 } else {
272 return SEC_ALG_NONE;
273 }
274}
275
276void rtl8192e_SetHwReg(struct ieee80211_device *ieee80211, u8 variable, u8 *val)
277{
278 struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
279
280 switch(variable)
281 {
282
283 case HW_VAR_BSSID:
284 write_nic_dword(priv, BSSIDR, ((u32*)(val))[0]);
285 write_nic_word(priv, BSSIDR+2, ((u16*)(val+2))[0]);
286 break;
287
288 case HW_VAR_MEDIA_STATUS:
289 {
290 RT_OP_MODE OpMode = *((RT_OP_MODE *)(val));
291 u8 btMsr = read_nic_byte(priv, MSR);
292
293 btMsr &= 0xfc;
294
295 switch(OpMode)
296 {
297 case RT_OP_MODE_INFRASTRUCTURE:
298 btMsr |= MSR_INFRA;
299 break;
300
301 case RT_OP_MODE_IBSS:
302 btMsr |= MSR_ADHOC;
303 break;
304
305 case RT_OP_MODE_AP:
306 btMsr |= MSR_AP;
307 break;
308
309 default:
310 btMsr |= MSR_NOLINK;
311 break;
312 }
313
314 write_nic_byte(priv, MSR, btMsr);
315 }
316 break;
317
318 case HW_VAR_CHECK_BSSID:
319 {
320 u32 RegRCR, Type;
321
322 Type = ((u8*)(val))[0];
323 RegRCR = read_nic_dword(priv, RCR);
324 priv->ReceiveConfig = RegRCR;
325
326 if (Type == true)
327 RegRCR |= (RCR_CBSSID);
328 else if (Type == false)
329 RegRCR &= (~RCR_CBSSID);
330
331 write_nic_dword(priv, RCR,RegRCR);
332 priv->ReceiveConfig = RegRCR;
333
334 }
335 break;
336
337 case HW_VAR_SLOT_TIME:
338 {
339 priv->slot_time = val[0];
340 write_nic_byte(priv, SLOT_TIME, val[0]);
341
342 }
343 break;
344
345 case HW_VAR_ACK_PREAMBLE:
346 {
347 u32 regTmp = 0;
348 priv->short_preamble = (bool)(*(u8*)val );
349 regTmp = priv->basic_rate;
350 if (priv->short_preamble)
351 regTmp |= BRSR_AckShortPmb;
352 write_nic_dword(priv, RRSR, regTmp);
353 }
354 break;
355
356 case HW_VAR_CPU_RST:
357 write_nic_dword(priv, CPU_GEN, ((u32*)(val))[0]);
358 break;
359
360 default:
361 break;
362 }
363
364}
365
366static struct proc_dir_entry *rtl8192_proc = NULL;
367
368static int proc_get_stats_ap(char *page, char **start,
369 off_t offset, int count,
370 int *eof, void *data)
371{
372 struct r8192_priv *priv = data;
373 struct ieee80211_device *ieee = priv->ieee80211;
374 struct ieee80211_network *target;
375 int len = 0;
376
377 list_for_each_entry(target, &ieee->network_list, list) {
378
379 len += snprintf(page + len, count - len,
380 "%s ", target->ssid);
381
382 if(target->wpa_ie_len>0 || target->rsn_ie_len>0){
383 len += snprintf(page + len, count - len,
384 "WPA\n");
385 }
386 else{
387 len += snprintf(page + len, count - len,
388 "non_WPA\n");
389 }
390
391 }
392
393 *eof = 1;
394 return len;
395}
396
397static int proc_get_registers(char *page, char **start,
398 off_t offset, int count,
399 int *eof, void *data)
400{
401 struct r8192_priv *priv = data;
402 int len = 0;
403 int i,n;
404 int max=0xff;
405
406 /* This dump the current register page */
407 len += snprintf(page + len, count - len,
408 "\n####################page 0##################\n ");
409
410 for(n=0;n<=max;)
411 {
412 len += snprintf(page + len, count - len,
413 "\nD: %2x > ",n);
414
415 for(i=0;i<16 && n<=max;i++,n++)
416 len += snprintf(page + len, count - len,
417 "%2x ",read_nic_byte(priv,n));
418 }
419 len += snprintf(page + len, count - len,"\n");
420 len += snprintf(page + len, count - len,
421 "\n####################page 1##################\n ");
422 for(n=0;n<=max;)
423 {
424 len += snprintf(page + len, count - len,
425 "\nD: %2x > ",n);
426
427 for(i=0;i<16 && n<=max;i++,n++)
428 len += snprintf(page + len, count - len,
429 "%2x ",read_nic_byte(priv,0x100|n));
430 }
431
432 len += snprintf(page + len, count - len,
433 "\n####################page 3##################\n ");
434 for(n=0;n<=max;)
435 {
436 len += snprintf(page + len, count - len,
437 "\nD: %2x > ",n);
438
439 for(i=0;i<16 && n<=max;i++,n++)
440 len += snprintf(page + len, count - len,
441 "%2x ",read_nic_byte(priv,0x300|n));
442 }
443
444 *eof = 1;
445 return len;
446
447}
448
449static int proc_get_stats_tx(char *page, char **start,
450 off_t offset, int count,
451 int *eof, void *data)
452{
453 struct r8192_priv *priv = data;
454
455 int len = 0;
456
457 len += snprintf(page + len, count - len,
458 "TX VI priority ok int: %lu\n"
459 "TX VO priority ok int: %lu\n"
460 "TX BE priority ok int: %lu\n"
461 "TX BK priority ok int: %lu\n"
462 "TX MANAGE priority ok int: %lu\n"
463 "TX BEACON priority ok int: %lu\n"
464 "TX BEACON priority error int: %lu\n"
465 "TX CMDPKT priority ok int: %lu\n"
466 "TX queue stopped?: %d\n"
467 "TX fifo overflow: %lu\n"
468 "TX total data packets %lu\n"
469 "TX total data bytes :%lu\n",
470 priv->stats.txviokint,
471 priv->stats.txvookint,
472 priv->stats.txbeokint,
473 priv->stats.txbkokint,
474 priv->stats.txmanageokint,
475 priv->stats.txbeaconokint,
476 priv->stats.txbeaconerr,
477 priv->stats.txcmdpktokint,
478 netif_queue_stopped(priv->ieee80211->dev),
479 priv->stats.txoverflow,
480 priv->ieee80211->stats.tx_packets,
481 priv->ieee80211->stats.tx_bytes);
482
483 *eof = 1;
484 return len;
485}
486
487
488
489static int proc_get_stats_rx(char *page, char **start,
490 off_t offset, int count,
491 int *eof, void *data)
492{
493 struct r8192_priv *priv = data;
494 int len = 0;
495
496 len += snprintf(page + len, count - len,
497 "RX packets: %lu\n"
498 "RX desc err: %lu\n"
499 "RX rx overflow error: %lu\n",
500 priv->stats.rxint,
501 priv->stats.rxrdu,
502 priv->stats.rxoverflow);
503
504 *eof = 1;
505 return len;
506}
507
508static void rtl8192_proc_module_init(void)
509{
510 RT_TRACE(COMP_INIT, "Initializing proc filesystem\n");
511 rtl8192_proc = proc_mkdir(RTL819xE_MODULE_NAME, init_net.proc_net);
512}
513
514
515static void rtl8192_proc_module_remove(void)
516{
517 remove_proc_entry(RTL819xE_MODULE_NAME, init_net.proc_net);
518}
519
520
521static void rtl8192_proc_remove_one(struct r8192_priv *priv)
522{
523 struct net_device *dev = priv->ieee80211->dev;
524
525 printk("dev name=======> %s\n",dev->name);
526
527 if (priv->dir_dev) {
528 remove_proc_entry("stats-tx", priv->dir_dev);
529 remove_proc_entry("stats-rx", priv->dir_dev);
530 remove_proc_entry("stats-ap", priv->dir_dev);
531 remove_proc_entry("registers", priv->dir_dev);
532 remove_proc_entry("wlan0", rtl8192_proc);
533 priv->dir_dev = NULL;
534 }
535}
536
537
538static void rtl8192_proc_init_one(struct r8192_priv *priv)
539{
540 struct net_device *dev = priv->ieee80211->dev;
541 struct proc_dir_entry *e;
542
543 priv->dir_dev = proc_mkdir(dev->name, rtl8192_proc);
544 if (!priv->dir_dev) {
545 RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n",
546 dev->name);
547 return;
548 }
549 e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
550 priv->dir_dev, proc_get_stats_rx, priv);
551
552 if (!e) {
553 RT_TRACE(COMP_ERR,"Unable to initialize "
554 "/proc/net/rtl8192/%s/stats-rx\n",
555 dev->name);
556 }
557
558
559 e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
560 priv->dir_dev, proc_get_stats_tx, priv);
561
562 if (!e) {
563 RT_TRACE(COMP_ERR, "Unable to initialize "
564 "/proc/net/rtl8192/%s/stats-tx\n",
565 dev->name);
566 }
567
568 e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO,
569 priv->dir_dev, proc_get_stats_ap, priv);
570
571 if (!e) {
572 RT_TRACE(COMP_ERR, "Unable to initialize "
573 "/proc/net/rtl8192/%s/stats-ap\n",
574 dev->name);
575 }
576
577 e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
578 priv->dir_dev, proc_get_registers, priv);
579 if (!e) {
580 RT_TRACE(COMP_ERR, "Unable to initialize "
581 "/proc/net/rtl8192/%s/registers\n",
582 dev->name);
583 }
584}
585
586static short check_nic_enough_desc(struct ieee80211_device *ieee, int prio)
587{
588 struct r8192_priv *priv = ieee80211_priv(ieee->dev);
589 struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
590
591 /* for now we reserve two free descriptor as a safety boundary
592 * between the tail and the head
593 */
594 return (ring->entries - skb_queue_len(&ring->queue) >= 2);
595}
596
597static void tx_timeout(struct net_device *dev)
598{
599 struct r8192_priv *priv = ieee80211_priv(dev);
600
601 schedule_work(&priv->reset_wq);
602 printk("TXTIMEOUT");
603}
604
605static void rtl8192_irq_enable(struct r8192_priv *priv)
606{
607 u32 mask;
608
609 mask = IMR_ROK | IMR_VODOK | IMR_VIDOK | IMR_BEDOK | IMR_BKDOK |
610 IMR_HCCADOK | IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK |
611 IMR_BDOK | IMR_RXCMDOK | IMR_TIMEOUT0 | IMR_RDU | IMR_RXFOVW |
612 IMR_TXFOVW | IMR_BcnInt | IMR_TBDOK | IMR_TBDER;
613
614 write_nic_dword(priv, INTA_MASK, mask);
615}
616
617static void rtl8192_irq_disable(struct r8192_priv *priv)
618{
619 write_nic_dword(priv, INTA_MASK, 0);
620 synchronize_irq(priv->irq);
621}
622
623static void rtl8192_update_msr(struct r8192_priv *priv)
624{
625 u8 msr;
626
627 msr = read_nic_byte(priv, MSR);
628 msr &= ~ MSR_LINK_MASK;
629
630 /* do not change in link_state != WLAN_LINK_ASSOCIATED.
631 * msr must be updated if the state is ASSOCIATING.
632 * this is intentional and make sense for ad-hoc and
633 * master (see the create BSS/IBSS func)
634 */
635 if (priv->ieee80211->state == IEEE80211_LINKED){
636
637 if (priv->ieee80211->iw_mode == IW_MODE_INFRA)
638 msr |= (MSR_LINK_MANAGED<<MSR_LINK_SHIFT);
639 else if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
640 msr |= (MSR_LINK_ADHOC<<MSR_LINK_SHIFT);
641 else if (priv->ieee80211->iw_mode == IW_MODE_MASTER)
642 msr |= (MSR_LINK_MASTER<<MSR_LINK_SHIFT);
643
644 }else
645 msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
646
647 write_nic_byte(priv, MSR, msr);
648}
649
650static void rtl8192_set_chan(struct ieee80211_device *ieee80211, short ch)
651{
652 struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
653
654 priv->chan = ch;
655
656 /* need to implement rf set channel here WB */
657
658 if (priv->rf_set_chan)
659 priv->rf_set_chan(ieee80211, priv->chan);
660}
661
662static void rtl8192_rx_enable(struct r8192_priv *priv)
663{
664 write_nic_dword(priv, RDQDA, priv->rx_ring_dma);
665}
666
667/* the TX_DESC_BASE setting is according to the following queue index
668 * BK_QUEUE ===> 0
669 * BE_QUEUE ===> 1
670 * VI_QUEUE ===> 2
671 * VO_QUEUE ===> 3
672 * HCCA_QUEUE ===> 4
673 * TXCMD_QUEUE ===> 5
674 * MGNT_QUEUE ===> 6
675 * HIGH_QUEUE ===> 7
676 * BEACON_QUEUE ===> 8
677 * */
678static const u32 TX_DESC_BASE[] = {BKQDA, BEQDA, VIQDA, VOQDA, HCCAQDA, CQDA, MQDA, HQDA, BQDA};
679static void rtl8192_tx_enable(struct r8192_priv *priv)
680{
681 u32 i;
682
683 for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
684 write_nic_dword(priv, TX_DESC_BASE[i], priv->tx_ring[i].dma);
685
686 ieee80211_reset_queue(priv->ieee80211);
687}
688
689
690static void rtl8192_free_rx_ring(struct r8192_priv *priv)
691{
692 int i;
693
694 for (i = 0; i < priv->rxringcount; i++) {
695 struct sk_buff *skb = priv->rx_buf[i];
696 if (!skb)
697 continue;
698
699 pci_unmap_single(priv->pdev,
700 *((dma_addr_t *)skb->cb),
701 priv->rxbuffersize, PCI_DMA_FROMDEVICE);
702 kfree_skb(skb);
703 }
704
705 pci_free_consistent(priv->pdev, sizeof(*priv->rx_ring) * priv->rxringcount,
706 priv->rx_ring, priv->rx_ring_dma);
707 priv->rx_ring = NULL;
708}
709
710static void rtl8192_free_tx_ring(struct r8192_priv *priv, unsigned int prio)
711{
712 struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
713
714 while (skb_queue_len(&ring->queue)) {
715 tx_desc_819x_pci *entry = &ring->desc[ring->idx];
716 struct sk_buff *skb = __skb_dequeue(&ring->queue);
717
718 pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr),
719 skb->len, PCI_DMA_TODEVICE);
720 kfree_skb(skb);
721 ring->idx = (ring->idx + 1) % ring->entries;
722 }
723
724 pci_free_consistent(priv->pdev, sizeof(*ring->desc)*ring->entries,
725 ring->desc, ring->dma);
726 ring->desc = NULL;
727}
728
729void PHY_SetRtl8192eRfOff(struct r8192_priv *priv)
730{
731 //disable RF-Chip A/B
732 rtl8192_setBBreg(priv, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
733 //analog to digital off, for power save
734 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0x300, 0x0);
735 //digital to analog off, for power save
736 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x18, 0x0);
737 //rx antenna off
738 rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0xf, 0x0);
739 //rx antenna off
740 rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0xf, 0x0);
741 //analog to digital part2 off, for power save
742 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x60, 0x0);
743 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x4, 0x0);
744 // Analog parameter!!Change bias and Lbus control.
745 write_nic_byte(priv, ANAPAR_FOR_8192PciE, 0x07);
746}
747
748static void rtl8192_halt_adapter(struct r8192_priv *priv, bool reset)
749{
750 int i;
751 u8 OpMode;
752 u32 ulRegRead;
753
754 OpMode = RT_OP_MODE_NO_LINK;
755 priv->ieee80211->SetHwRegHandler(priv->ieee80211, HW_VAR_MEDIA_STATUS, &OpMode);
756
757 if (!priv->ieee80211->bSupportRemoteWakeUp) {
758 /*
759 * disable tx/rx. In 8185 we write 0x10 (Reset bit),
760 * but here we make reference to WMAC and wirte 0x0
761 */
762 write_nic_byte(priv, CMDR, 0);
763 }
764
765 mdelay(20);
766
767 if (!reset) {
768 mdelay(150);
769
770 priv->bHwRfOffAction = 2;
771
772 /*
773 * Call MgntActSet_RF_State instead to
774 * prevent RF config race condition.
775 */
776 if (!priv->ieee80211->bSupportRemoteWakeUp) {
777 PHY_SetRtl8192eRfOff(priv);
778 ulRegRead = read_nic_dword(priv, CPU_GEN);
779 ulRegRead |= CPU_GEN_SYSTEM_RESET;
780 write_nic_dword(priv,CPU_GEN, ulRegRead);
781 } else {
782 /* for WOL */
783 write_nic_dword(priv, WFCRC0, 0xffffffff);
784 write_nic_dword(priv, WFCRC1, 0xffffffff);
785 write_nic_dword(priv, WFCRC2, 0xffffffff);
786
787 /* Write PMR register */
788 write_nic_byte(priv, PMR, 0x5);
789 /* Disable tx, enanble rx */
790 write_nic_byte(priv, MacBlkCtrl, 0xa);
791 }
792 }
793
794 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
795 skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
796 }
797 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
798 skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
799 }
800
801 skb_queue_purge(&priv->skb_queue);
802}
803
804static void rtl8192_data_hard_stop(struct ieee80211_device *ieee80211)
805{
806}
807
808static void rtl8192_data_hard_resume(struct ieee80211_device *ieee80211)
809{
810}
811
812/*
813 * this function TX data frames when the ieee80211 stack requires this.
814 * It checks also if we need to stop the ieee tx queue, eventually do it
815 */
816static void rtl8192_hard_data_xmit(struct sk_buff *skb,
817 struct ieee80211_device *ieee80211, int rate)
818{
819 struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
820 int ret;
821 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
822 u8 queue_index = tcb_desc->queue_index;
823
824 /* shall not be referred by command packet */
825 BUG_ON(queue_index == TXCMD_QUEUE);
826
827 if (priv->bHwRadioOff || (!priv->up))
828 {
829 kfree_skb(skb);
830 return;
831 }
832
833 skb_push(skb, priv->ieee80211->tx_headroom);
834 ret = rtl8192_tx(priv, skb);
835 if (ret != 0) {
836 kfree_skb(skb);
837 }
838
839 if (queue_index != MGNT_QUEUE) {
840 priv->ieee80211->stats.tx_bytes += (skb->len - priv->ieee80211->tx_headroom);
841 priv->ieee80211->stats.tx_packets++;
842 }
843}
844
845/*
846 * This is a rough attempt to TX a frame
847 * This is called by the ieee 80211 stack to TX management frames.
848 * If the ring is full packet are dropped (for data frame the queue
849 * is stopped before this can happen).
850 */
851static int rtl8192_hard_start_xmit(struct sk_buff *skb, struct ieee80211_device *ieee80211)
852{
853 struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
854 int ret;
855 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
856 u8 queue_index = tcb_desc->queue_index;
857
858 if (queue_index != TXCMD_QUEUE) {
859 if (priv->bHwRadioOff || (!priv->up))
860 {
861 kfree_skb(skb);
862 return 0;
863 }
864 }
865
866 if (queue_index == TXCMD_QUEUE) {
867 rtl819xE_tx_cmd(priv, skb);
868 ret = 0;
869 return ret;
870 } else {
871 tcb_desc->RATRIndex = 7;
872 tcb_desc->bTxDisableRateFallBack = 1;
873 tcb_desc->bTxUseDriverAssingedRate = 1;
874 tcb_desc->bTxEnableFwCalcDur = 1;
875 skb_push(skb, ieee80211->tx_headroom);
876 ret = rtl8192_tx(priv, skb);
877 if (ret != 0) {
878 kfree_skb(skb);
879 }
880 }
881
882 return ret;
883}
884
885
886static void rtl8192_tx_isr(struct r8192_priv *priv, int prio)
887{
888 struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
889
890 while (skb_queue_len(&ring->queue)) {
891 tx_desc_819x_pci *entry = &ring->desc[ring->idx];
892 struct sk_buff *skb;
893
894 /*
895 * beacon packet will only use the first descriptor defaultly,
896 * and the OWN may not be cleared by the hardware
897 */
898 if (prio != BEACON_QUEUE) {
899 if (entry->OWN)
900 return;
901 ring->idx = (ring->idx + 1) % ring->entries;
902 }
903
904 skb = __skb_dequeue(&ring->queue);
905 pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr),
906 skb->len, PCI_DMA_TODEVICE);
907
908 kfree_skb(skb);
909 }
910
911 if (prio != BEACON_QUEUE) {
912 /* try to deal with the pending packets */
913 tasklet_schedule(&priv->irq_tx_tasklet);
914 }
915}
916
917static void rtl8192_stop_beacon(struct ieee80211_device *ieee80211)
918{
919}
920
921static void rtl8192_config_rate(struct r8192_priv *priv, u16* rate_config)
922{
923 struct ieee80211_network *net;
924 u8 i=0, basic_rate = 0;
925 net = & priv->ieee80211->current_network;
926
927 for (i=0; i<net->rates_len; i++)
928 {
929 basic_rate = net->rates[i]&0x7f;
930 switch(basic_rate)
931 {
932 case MGN_1M: *rate_config |= RRSR_1M; break;
933 case MGN_2M: *rate_config |= RRSR_2M; break;
934 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
935 case MGN_11M: *rate_config |= RRSR_11M; break;
936 case MGN_6M: *rate_config |= RRSR_6M; break;
937 case MGN_9M: *rate_config |= RRSR_9M; break;
938 case MGN_12M: *rate_config |= RRSR_12M; break;
939 case MGN_18M: *rate_config |= RRSR_18M; break;
940 case MGN_24M: *rate_config |= RRSR_24M; break;
941 case MGN_36M: *rate_config |= RRSR_36M; break;
942 case MGN_48M: *rate_config |= RRSR_48M; break;
943 case MGN_54M: *rate_config |= RRSR_54M; break;
944 }
945 }
946 for (i=0; i<net->rates_ex_len; i++)
947 {
948 basic_rate = net->rates_ex[i]&0x7f;
949 switch(basic_rate)
950 {
951 case MGN_1M: *rate_config |= RRSR_1M; break;
952 case MGN_2M: *rate_config |= RRSR_2M; break;
953 case MGN_5_5M: *rate_config |= RRSR_5_5M; break;
954 case MGN_11M: *rate_config |= RRSR_11M; break;
955 case MGN_6M: *rate_config |= RRSR_6M; break;
956 case MGN_9M: *rate_config |= RRSR_9M; break;
957 case MGN_12M: *rate_config |= RRSR_12M; break;
958 case MGN_18M: *rate_config |= RRSR_18M; break;
959 case MGN_24M: *rate_config |= RRSR_24M; break;
960 case MGN_36M: *rate_config |= RRSR_36M; break;
961 case MGN_48M: *rate_config |= RRSR_48M; break;
962 case MGN_54M: *rate_config |= RRSR_54M; break;
963 }
964 }
965}
966
967
968#define SHORT_SLOT_TIME 9
969#define NON_SHORT_SLOT_TIME 20
970
971static void rtl8192_update_cap(struct r8192_priv *priv, u16 cap)
972{
973 u32 tmp = 0;
974 struct ieee80211_network *net = &priv->ieee80211->current_network;
975
976 priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
977 tmp = priv->basic_rate;
978 if (priv->short_preamble)
979 tmp |= BRSR_AckShortPmb;
980 write_nic_dword(priv, RRSR, tmp);
981
982 if (net->mode & (IEEE_G|IEEE_N_24G))
983 {
984 u8 slot_time = 0;
985 if ((cap & WLAN_CAPABILITY_SHORT_SLOT)&&(!priv->ieee80211->pHTInfo->bCurrentRT2RTLongSlotTime))
986 {//short slot time
987 slot_time = SHORT_SLOT_TIME;
988 }
989 else //long slot time
990 slot_time = NON_SHORT_SLOT_TIME;
991 priv->slot_time = slot_time;
992 write_nic_byte(priv, SLOT_TIME, slot_time);
993 }
994
995}
996
997static void rtl8192_net_update(struct r8192_priv *priv)
998{
999 struct ieee80211_network *net;
1000 u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
1001 u16 rate_config = 0;
1002 net = &priv->ieee80211->current_network;
1003
1004 /* update Basic rate: RR, BRSR */
1005 rtl8192_config_rate(priv, &rate_config);
1006
1007 /*
1008 * Select RRSR (in Legacy-OFDM and CCK)
1009 * For 8190, we select only 24M, 12M, 6M, 11M, 5.5M,
1010 * 2M, and 1M from the Basic rate.
1011 * We do not use other rates.
1012 */
1013 priv->basic_rate = rate_config &= 0x15f;
1014
1015 /* BSSID */
1016 write_nic_dword(priv, BSSIDR, ((u32 *)net->bssid)[0]);
1017 write_nic_word(priv, BSSIDR+4, ((u16 *)net->bssid)[2]);
1018
1019 if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
1020 {
1021 write_nic_word(priv, ATIMWND, 2);
1022 write_nic_word(priv, BCN_DMATIME, 256);
1023 write_nic_word(priv, BCN_INTERVAL, net->beacon_interval);
1024 /*
1025 * BIT15 of BCN_DRV_EARLY_INT will indicate
1026 * whether software beacon or hw beacon is applied.
1027 */
1028 write_nic_word(priv, BCN_DRV_EARLY_INT, 10);
1029 write_nic_byte(priv, BCN_ERR_THRESH, 100);
1030
1031 BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
1032 /* TODO: BcnIFS may required to be changed on ASIC */
1033 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
1034 write_nic_word(priv, BCN_TCFG, BcnTimeCfg);
1035 }
1036}
1037
1038static void rtl819xE_tx_cmd(struct r8192_priv *priv, struct sk_buff *skb)
1039{
1040 struct rtl8192_tx_ring *ring;
1041 tx_desc_819x_pci *entry;
1042 unsigned int idx;
1043 dma_addr_t mapping;
1044 cb_desc *tcb_desc;
1045 unsigned long flags;
1046
1047 ring = &priv->tx_ring[TXCMD_QUEUE];
1048 mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
1049
1050 spin_lock_irqsave(&priv->irq_th_lock,flags);
1051 idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
1052 entry = &ring->desc[idx];
1053
1054 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1055 memset(entry,0,12);
1056 entry->LINIP = tcb_desc->bLastIniPkt;
1057 entry->FirstSeg = 1;//first segment
1058 entry->LastSeg = 1; //last segment
1059 if(tcb_desc->bCmdOrInit == DESC_PACKET_TYPE_INIT) {
1060 entry->CmdInit = DESC_PACKET_TYPE_INIT;
1061 } else {
1062 entry->CmdInit = DESC_PACKET_TYPE_NORMAL;
1063 entry->Offset = sizeof(TX_FWINFO_8190PCI) + 8;
1064 entry->PktSize = (u16)(tcb_desc->pkt_size + entry->Offset);
1065 entry->QueueSelect = QSLT_CMD;
1066 entry->TxFWInfoSize = 0x08;
1067 entry->RATid = (u8)DESC_PACKET_TYPE_INIT;
1068 }
1069 entry->TxBufferSize = skb->len;
1070 entry->TxBuffAddr = cpu_to_le32(mapping);
1071 entry->OWN = 1;
1072
1073 __skb_queue_tail(&ring->queue, skb);
1074 spin_unlock_irqrestore(&priv->irq_th_lock,flags);
1075
1076 write_nic_byte(priv, TPPoll, TPPoll_CQ);
1077
1078 return;
1079}
1080
1081/*
1082 * Mapping Software/Hardware descriptor queue id to "Queue Select Field"
1083 * in TxFwInfo data structure
1084 */
1085static u8 MapHwQueueToFirmwareQueue(u8 QueueID)
1086{
1087 u8 QueueSelect = 0;
1088
1089 switch (QueueID) {
1090 case BE_QUEUE:
1091 QueueSelect = QSLT_BE;
1092 break;
1093
1094 case BK_QUEUE:
1095 QueueSelect = QSLT_BK;
1096 break;
1097
1098 case VO_QUEUE:
1099 QueueSelect = QSLT_VO;
1100 break;
1101
1102 case VI_QUEUE:
1103 QueueSelect = QSLT_VI;
1104 break;
1105
1106 case MGNT_QUEUE:
1107 QueueSelect = QSLT_MGNT;
1108 break;
1109
1110 case BEACON_QUEUE:
1111 QueueSelect = QSLT_BEACON;
1112 break;
1113
1114 case TXCMD_QUEUE:
1115 QueueSelect = QSLT_CMD;
1116 break;
1117
1118 case HIGH_QUEUE:
1119 default:
1120 RT_TRACE(COMP_ERR, "Impossible Queue Selection: %d\n", QueueID);
1121 break;
1122 }
1123 return QueueSelect;
1124}
1125
1126static u8 MRateToHwRate8190Pci(u8 rate)
1127{
1128 u8 ret = DESC90_RATE1M;
1129
1130 switch(rate) {
1131 case MGN_1M: ret = DESC90_RATE1M; break;
1132 case MGN_2M: ret = DESC90_RATE2M; break;
1133 case MGN_5_5M: ret = DESC90_RATE5_5M; break;
1134 case MGN_11M: ret = DESC90_RATE11M; break;
1135 case MGN_6M: ret = DESC90_RATE6M; break;
1136 case MGN_9M: ret = DESC90_RATE9M; break;
1137 case MGN_12M: ret = DESC90_RATE12M; break;
1138 case MGN_18M: ret = DESC90_RATE18M; break;
1139 case MGN_24M: ret = DESC90_RATE24M; break;
1140 case MGN_36M: ret = DESC90_RATE36M; break;
1141 case MGN_48M: ret = DESC90_RATE48M; break;
1142 case MGN_54M: ret = DESC90_RATE54M; break;
1143
1144 // HT rate since here
1145 case MGN_MCS0: ret = DESC90_RATEMCS0; break;
1146 case MGN_MCS1: ret = DESC90_RATEMCS1; break;
1147 case MGN_MCS2: ret = DESC90_RATEMCS2; break;
1148 case MGN_MCS3: ret = DESC90_RATEMCS3; break;
1149 case MGN_MCS4: ret = DESC90_RATEMCS4; break;
1150 case MGN_MCS5: ret = DESC90_RATEMCS5; break;
1151 case MGN_MCS6: ret = DESC90_RATEMCS6; break;
1152 case MGN_MCS7: ret = DESC90_RATEMCS7; break;
1153 case MGN_MCS8: ret = DESC90_RATEMCS8; break;
1154 case MGN_MCS9: ret = DESC90_RATEMCS9; break;
1155 case MGN_MCS10: ret = DESC90_RATEMCS10; break;
1156 case MGN_MCS11: ret = DESC90_RATEMCS11; break;
1157 case MGN_MCS12: ret = DESC90_RATEMCS12; break;
1158 case MGN_MCS13: ret = DESC90_RATEMCS13; break;
1159 case MGN_MCS14: ret = DESC90_RATEMCS14; break;
1160 case MGN_MCS15: ret = DESC90_RATEMCS15; break;
1161 case (0x80|0x20): ret = DESC90_RATEMCS32; break;
1162
1163 default: break;
1164 }
1165 return ret;
1166}
1167
1168
1169static u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
1170{
1171 u8 tmp_Short;
1172
1173 tmp_Short = (TxHT==1)?((tcb_desc->bUseShortGI)?1:0):((tcb_desc->bUseShortPreamble)?1:0);
1174
1175 if(TxHT==1 && TxRate != DESC90_RATEMCS15)
1176 tmp_Short = 0;
1177
1178 return tmp_Short;
1179}
1180
1181/*
1182 * The tx procedure is just as following,
1183 * skb->cb will contain all the following information,
1184 * priority, morefrag, rate, &dev.
1185 */
1186static short rtl8192_tx(struct r8192_priv *priv, struct sk_buff* skb)
1187{
1188 struct rtl8192_tx_ring *ring;
1189 unsigned long flags;
1190 cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
1191 tx_desc_819x_pci *pdesc = NULL;
1192 TX_FWINFO_8190PCI *pTxFwInfo = NULL;
1193 dma_addr_t mapping;
1194 bool multi_addr = false, broad_addr = false, uni_addr = false;
1195 u8 *pda_addr = NULL;
1196 int idx;
1197
1198 if (priv->bdisable_nic) {
1199 RT_TRACE(COMP_ERR, "Nic is disabled! Can't tx packet len=%d qidx=%d!!!\n",
1200 skb->len, tcb_desc->queue_index);
1201 return skb->len;
1202 }
1203
1204#ifdef ENABLE_LPS
1205 priv->ieee80211->bAwakePktSent = true;
1206#endif
1207
1208 mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
1209
1210 /* collect the tx packets statitcs */
1211 pda_addr = ((u8 *)skb->data) + sizeof(TX_FWINFO_8190PCI);
1212 if (is_multicast_ether_addr(pda_addr))
1213 multi_addr = true;
1214 else if (is_broadcast_ether_addr(pda_addr))
1215 broad_addr = true;
1216 else
1217 uni_addr = true;
1218
1219 if (uni_addr)
1220 priv->stats.txbytesunicast += (u8)(skb->len) - sizeof(TX_FWINFO_8190PCI);
1221
1222 /* fill tx firmware */
1223 pTxFwInfo = (PTX_FWINFO_8190PCI)skb->data;
1224 memset(pTxFwInfo, 0, sizeof(TX_FWINFO_8190PCI));
1225 pTxFwInfo->TxHT = (tcb_desc->data_rate&0x80) ? 1 : 0;
1226 pTxFwInfo->TxRate = MRateToHwRate8190Pci((u8)tcb_desc->data_rate);
1227 pTxFwInfo->EnableCPUDur = tcb_desc->bTxEnableFwCalcDur;
1228 pTxFwInfo->Short = QueryIsShort(pTxFwInfo->TxHT, pTxFwInfo->TxRate, tcb_desc);
1229
1230 /* Aggregation related */
1231 if (tcb_desc->bAMPDUEnable) {
1232 pTxFwInfo->AllowAggregation = 1;
1233 pTxFwInfo->RxMF = tcb_desc->ampdu_factor;
1234 pTxFwInfo->RxAMD = tcb_desc->ampdu_density;
1235 } else {
1236 pTxFwInfo->AllowAggregation = 0;
1237 pTxFwInfo->RxMF = 0;
1238 pTxFwInfo->RxAMD = 0;
1239 }
1240
1241 /* Protection mode related */
1242 pTxFwInfo->RtsEnable = (tcb_desc->bRTSEnable) ? 1 : 0;
1243 pTxFwInfo->CtsEnable = (tcb_desc->bCTSEnable) ? 1 : 0;
1244 pTxFwInfo->RtsSTBC = (tcb_desc->bRTSSTBC) ? 1 : 0;
1245 pTxFwInfo->RtsHT = (tcb_desc->rts_rate&0x80) ? 1 : 0;
1246 pTxFwInfo->RtsRate = MRateToHwRate8190Pci((u8)tcb_desc->rts_rate);
1247 pTxFwInfo->RtsBandwidth = 0;
1248 pTxFwInfo->RtsSubcarrier = tcb_desc->RTSSC;
1249 pTxFwInfo->RtsShort = (pTxFwInfo->RtsHT == 0) ? (tcb_desc->bRTSUseShortPreamble ? 1 : 0) : (tcb_desc->bRTSUseShortGI? 1 : 0);
1250
1251 /* Set Bandwidth and sub-channel settings. */
1252 if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
1253 if (tcb_desc->bPacketBW) {
1254 pTxFwInfo->TxBandwidth = 1;
1255 /* use duplicated mode */
1256 pTxFwInfo->TxSubCarrier = 0;
1257 } else {
1258 pTxFwInfo->TxBandwidth = 0;
1259 pTxFwInfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
1260 }
1261 } else {
1262 pTxFwInfo->TxBandwidth = 0;
1263 pTxFwInfo->TxSubCarrier = 0;
1264 }
1265
1266 spin_lock_irqsave(&priv->irq_th_lock, flags);
1267 ring = &priv->tx_ring[tcb_desc->queue_index];
1268 if (tcb_desc->queue_index != BEACON_QUEUE)
1269 idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
1270 else
1271 idx = 0;
1272
1273 pdesc = &ring->desc[idx];
1274 if ((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) {
1275 RT_TRACE(COMP_ERR, "No more TX desc@%d, ring->idx = %d,idx = %d,%x\n",
1276 tcb_desc->queue_index, ring->idx, idx, skb->len);
1277 spin_unlock_irqrestore(&priv->irq_th_lock, flags);
1278 return skb->len;
1279 }
1280
1281 /* fill tx descriptor */
1282 memset(pdesc, 0, 12);
1283
1284 /*DWORD 0*/
1285 pdesc->LINIP = 0;
1286 pdesc->CmdInit = 1;
1287 pdesc->Offset = sizeof(TX_FWINFO_8190PCI) + 8; /* We must add 8!! */
1288 pdesc->PktSize = (u16)skb->len-sizeof(TX_FWINFO_8190PCI);
1289
1290 /*DWORD 1*/
1291 pdesc->SecCAMID = 0;
1292 pdesc->RATid = tcb_desc->RATRIndex;
1293
1294 pdesc->NoEnc = 1;
1295 pdesc->SecType = 0x0;
1296 if (tcb_desc->bHwSec) {
1297 switch (priv->ieee80211->pairwise_key_type) {
1298 case KEY_TYPE_WEP40:
1299 case KEY_TYPE_WEP104:
1300 pdesc->SecType = 0x1;
1301 pdesc->NoEnc = 0;
1302 break;
1303 case KEY_TYPE_TKIP:
1304 pdesc->SecType = 0x2;
1305 pdesc->NoEnc = 0;
1306 break;
1307 case KEY_TYPE_CCMP:
1308 pdesc->SecType = 0x3;
1309 pdesc->NoEnc = 0;
1310 break;
1311 case KEY_TYPE_NA:
1312 pdesc->SecType = 0x0;
1313 pdesc->NoEnc = 1;
1314 break;
1315 }
1316 }
1317
1318 /* Set Packet ID */
1319 pdesc->PktId = 0x0;
1320
1321 pdesc->QueueSelect = MapHwQueueToFirmwareQueue(tcb_desc->queue_index);
1322 pdesc->TxFWInfoSize = sizeof(TX_FWINFO_8190PCI);
1323
1324 pdesc->DISFB = tcb_desc->bTxDisableRateFallBack;
1325 pdesc->USERATE = tcb_desc->bTxUseDriverAssingedRate;
1326
1327 pdesc->FirstSeg = 1;
1328 pdesc->LastSeg = 1;
1329 pdesc->TxBufferSize = skb->len;
1330
1331 pdesc->TxBuffAddr = cpu_to_le32(mapping);
1332 __skb_queue_tail(&ring->queue, skb);
1333 pdesc->OWN = 1;
1334 spin_unlock_irqrestore(&priv->irq_th_lock, flags);
1335 priv->ieee80211->dev->trans_start = jiffies;
1336 write_nic_word(priv, TPPoll, 0x01<<tcb_desc->queue_index);
1337 return 0;
1338}
1339
1340static short rtl8192_alloc_rx_desc_ring(struct r8192_priv *priv)
1341{
1342 rx_desc_819x_pci *entry = NULL;
1343 int i;
1344
1345 priv->rx_ring = pci_alloc_consistent(priv->pdev,
1346 sizeof(*priv->rx_ring) * priv->rxringcount, &priv->rx_ring_dma);
1347
1348 if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {
1349 RT_TRACE(COMP_ERR,"Cannot allocate RX ring\n");
1350 return -ENOMEM;
1351 }
1352
1353 memset(priv->rx_ring, 0, sizeof(*priv->rx_ring) * priv->rxringcount);
1354 priv->rx_idx = 0;
1355
1356 for (i = 0; i < priv->rxringcount; i++) {
1357 struct sk_buff *skb = dev_alloc_skb(priv->rxbuffersize);
1358 dma_addr_t *mapping;
1359 entry = &priv->rx_ring[i];
1360 if (!skb)
1361 return 0;
1362 priv->rx_buf[i] = skb;
1363 mapping = (dma_addr_t *)skb->cb;
1364 *mapping = pci_map_single(priv->pdev, skb_tail_pointer(skb),
1365 priv->rxbuffersize, PCI_DMA_FROMDEVICE);
1366
1367 entry->BufferAddress = cpu_to_le32(*mapping);
1368
1369 entry->Length = priv->rxbuffersize;
1370 entry->OWN = 1;
1371 }
1372
1373 entry->EOR = 1;
1374 return 0;
1375}
1376
1377static int rtl8192_alloc_tx_desc_ring(struct r8192_priv *priv,
1378 unsigned int prio, unsigned int entries)
1379{
1380 tx_desc_819x_pci *ring;
1381 dma_addr_t dma;
1382 int i;
1383
1384 ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
1385 if (!ring || (unsigned long)ring & 0xFF) {
1386 RT_TRACE(COMP_ERR, "Cannot allocate TX ring (prio = %d)\n", prio);
1387 return -ENOMEM;
1388 }
1389
1390 memset(ring, 0, sizeof(*ring)*entries);
1391 priv->tx_ring[prio].desc = ring;
1392 priv->tx_ring[prio].dma = dma;
1393 priv->tx_ring[prio].idx = 0;
1394 priv->tx_ring[prio].entries = entries;
1395 skb_queue_head_init(&priv->tx_ring[prio].queue);
1396
1397 for (i = 0; i < entries; i++)
1398 ring[i].NextDescAddress =
1399 cpu_to_le32((u32)dma + ((i + 1) % entries) * sizeof(*ring));
1400
1401 return 0;
1402}
1403
1404static short rtl8192_pci_initdescring(struct r8192_priv *priv)
1405{
1406 u32 ret;
1407 int i;
1408
1409 ret = rtl8192_alloc_rx_desc_ring(priv);
1410 if (ret)
1411 return ret;
1412
1413 /* general process for other queue */
1414 for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
1415 ret = rtl8192_alloc_tx_desc_ring(priv, i, priv->txringcount);
1416 if (ret)
1417 goto err_free_rings;
1418 }
1419
1420 return 0;
1421
1422err_free_rings:
1423 rtl8192_free_rx_ring(priv);
1424 for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
1425 if (priv->tx_ring[i].desc)
1426 rtl8192_free_tx_ring(priv, i);
1427 return 1;
1428}
1429
1430static void rtl8192_pci_resetdescring(struct r8192_priv *priv)
1431{
1432 int i;
1433
1434 /* force the rx_idx to the first one */
1435 if(priv->rx_ring) {
1436 rx_desc_819x_pci *entry = NULL;
1437 for (i = 0; i < priv->rxringcount; i++) {
1438 entry = &priv->rx_ring[i];
1439 entry->OWN = 1;
1440 }
1441 priv->rx_idx = 0;
1442 }
1443
1444 /* after reset, release previous pending packet, and force the
1445 * tx idx to the first one */
1446 for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
1447 if (priv->tx_ring[i].desc) {
1448 struct rtl8192_tx_ring *ring = &priv->tx_ring[i];
1449
1450 while (skb_queue_len(&ring->queue)) {
1451 tx_desc_819x_pci *entry = &ring->desc[ring->idx];
1452 struct sk_buff *skb = __skb_dequeue(&ring->queue);
1453
1454 pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr),
1455 skb->len, PCI_DMA_TODEVICE);
1456 kfree_skb(skb);
1457 ring->idx = (ring->idx + 1) % ring->entries;
1458 }
1459 ring->idx = 0;
1460 }
1461 }
1462}
1463
1464static void rtl8192_link_change(struct ieee80211_device *ieee)
1465{
1466 struct r8192_priv *priv = ieee80211_priv(ieee->dev);
1467
1468 if (ieee->state == IEEE80211_LINKED)
1469 {
1470 rtl8192_net_update(priv);
1471 rtl8192_update_ratr_table(priv);
1472
1473 //add this as in pure N mode, wep encryption will use software way, but there is no chance to set this as wep will not set group key in wext. WB.2008.07.08
1474 if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
1475 EnableHWSecurityConfig8192(priv);
1476 }
1477 else
1478 {
1479 write_nic_byte(priv, 0x173, 0);
1480 }
1481
1482 rtl8192_update_msr(priv);
1483
1484 // 2007/10/16 MH MAC Will update TSF according to all received beacon, so we have
1485 // // To set CBSSID bit when link with any AP or STA.
1486 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
1487 {
1488 u32 reg = 0;
1489 reg = read_nic_dword(priv, RCR);
1490 if (priv->ieee80211->state == IEEE80211_LINKED)
1491 priv->ReceiveConfig = reg |= RCR_CBSSID;
1492 else
1493 priv->ReceiveConfig = reg &= ~RCR_CBSSID;
1494 write_nic_dword(priv, RCR, reg);
1495 }
1496}
1497
1498
1499static const struct ieee80211_qos_parameters def_qos_parameters = {
1500 {3,3,3,3},/* cw_min */
1501 {7,7,7,7},/* cw_max */
1502 {2,2,2,2},/* aifs */
1503 {0,0,0,0},/* flags */
1504 {0,0,0,0} /* tx_op_limit */
1505};
1506
1507static void rtl8192_update_beacon(struct work_struct * work)
1508{
1509 struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
1510 struct ieee80211_device* ieee = priv->ieee80211;
1511 struct ieee80211_network* net = &ieee->current_network;
1512
1513 if (ieee->pHTInfo->bCurrentHTSupport)
1514 HTUpdateSelfAndPeerSetting(ieee, net);
1515 ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
1516 rtl8192_update_cap(priv, net->capability);
1517}
1518
1519/*
1520* background support to run QoS activate functionality
1521*/
1522static const int WDCAPARA_ADD[] = {EDCAPARA_BE,EDCAPARA_BK,EDCAPARA_VI,EDCAPARA_VO};
1523static void rtl8192_qos_activate(struct work_struct * work)
1524{
1525 struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
1526 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
1527 u8 mode = priv->ieee80211->current_network.mode;
1528 u8 u1bAIFS;
1529 u32 u4bAcParam;
1530 int i;
1531
1532 mutex_lock(&priv->mutex);
1533 if(priv->ieee80211->state != IEEE80211_LINKED)
1534 goto success;
1535 RT_TRACE(COMP_QOS,"qos active process with associate response received\n");
1536 /* It better set slot time at first */
1537 /* For we just support b/g mode at present, let the slot time at 9/20 selection */
1538 /* update the ac parameter to related registers */
1539 for(i = 0; i < QOS_QUEUE_NUM; i++) {
1540 //Mode G/A: slotTimeTimer = 9; Mode B: 20
1541 u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
1542 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
1543 (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
1544 (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
1545 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
1546 write_nic_dword(priv, WDCAPARA_ADD[i], u4bAcParam);
1547 }
1548
1549success:
1550 mutex_unlock(&priv->mutex);
1551}
1552
1553static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
1554 int active_network,
1555 struct ieee80211_network *network)
1556{
1557 int ret = 0;
1558 u32 size = sizeof(struct ieee80211_qos_parameters);
1559
1560 if(priv->ieee80211->state !=IEEE80211_LINKED)
1561 return ret;
1562
1563 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
1564 return ret;
1565
1566 if (network->flags & NETWORK_HAS_QOS_MASK) {
1567 if (active_network &&
1568 (network->flags & NETWORK_HAS_QOS_PARAMETERS))
1569 network->qos_data.active = network->qos_data.supported;
1570
1571 if ((network->qos_data.active == 1) && (active_network == 1) &&
1572 (network->flags & NETWORK_HAS_QOS_PARAMETERS) &&
1573 (network->qos_data.old_param_count !=
1574 network->qos_data.param_count)) {
1575 network->qos_data.old_param_count =
1576 network->qos_data.param_count;
1577 queue_work(priv->priv_wq, &priv->qos_activate);
1578 RT_TRACE (COMP_QOS, "QoS parameters change call "
1579 "qos_activate\n");
1580 }
1581 } else {
1582 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
1583 &def_qos_parameters, size);
1584
1585 if ((network->qos_data.active == 1) && (active_network == 1)) {
1586 queue_work(priv->priv_wq, &priv->qos_activate);
1587 RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate\n");
1588 }
1589 network->qos_data.active = 0;
1590 network->qos_data.supported = 0;
1591 }
1592
1593 return 0;
1594}
1595
1596/* handle manage frame frame beacon and probe response */
1597static int rtl8192_handle_beacon(struct ieee80211_device *ieee,
1598 struct ieee80211_beacon * beacon,
1599 struct ieee80211_network * network)
1600{
1601 struct r8192_priv *priv = ieee80211_priv(ieee->dev);
1602
1603 rtl8192_qos_handle_probe_response(priv,1,network);
1604
1605 queue_delayed_work(priv->priv_wq, &priv->update_beacon_wq, 0);
1606 return 0;
1607
1608}
1609
1610/*
1611 * handling the beaconing responses. if we get different QoS setting
1612 * off the network from the associated setting, adjust the QoS setting
1613 */
1614static int rtl8192_qos_association_resp(struct r8192_priv *priv,
1615 struct ieee80211_network *network)
1616{
1617 int ret = 0;
1618 unsigned long flags;
1619 u32 size = sizeof(struct ieee80211_qos_parameters);
1620 int set_qos_param = 0;
1621
1622 if ((priv == NULL) || (network == NULL))
1623 return ret;
1624
1625 if (priv->ieee80211->state != IEEE80211_LINKED)
1626 return ret;
1627
1628 if ((priv->ieee80211->iw_mode != IW_MODE_INFRA))
1629 return ret;
1630
1631 spin_lock_irqsave(&priv->ieee80211->lock, flags);
1632 if (network->flags & NETWORK_HAS_QOS_PARAMETERS) {
1633 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
1634 &network->qos_data.parameters,
1635 sizeof(struct ieee80211_qos_parameters));
1636 priv->ieee80211->current_network.qos_data.active = 1;
1637 set_qos_param = 1;
1638 /* update qos parameter for current network */
1639 priv->ieee80211->current_network.qos_data.old_param_count =
1640 priv->ieee80211->current_network.qos_data.param_count;
1641 priv->ieee80211->current_network.qos_data.param_count =
1642 network->qos_data.param_count;
1643
1644 } else {
1645 memcpy(&priv->ieee80211->current_network.qos_data.parameters,
1646 &def_qos_parameters, size);
1647 priv->ieee80211->current_network.qos_data.active = 0;
1648 priv->ieee80211->current_network.qos_data.supported = 0;
1649 set_qos_param = 1;
1650 }
1651
1652 spin_unlock_irqrestore(&priv->ieee80211->lock, flags);
1653
1654 RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n", __FUNCTION__,
1655 network->flags, priv->ieee80211->current_network.qos_data.active);
1656 if (set_qos_param == 1)
1657 queue_work(priv->priv_wq, &priv->qos_activate);
1658
1659 return ret;
1660}
1661
1662
1663static int rtl8192_handle_assoc_response(struct ieee80211_device *ieee,
1664 struct ieee80211_assoc_response_frame *resp,
1665 struct ieee80211_network *network)
1666{
1667 struct r8192_priv *priv = ieee80211_priv(ieee->dev);
1668 rtl8192_qos_association_resp(priv, network);
1669 return 0;
1670}
1671
1672
1673/* updateRATRTabel for MCS only. Basic rate is not implemented. */
1674static void rtl8192_update_ratr_table(struct r8192_priv* priv)
1675{
1676 struct ieee80211_device* ieee = priv->ieee80211;
1677 u8* pMcsRate = ieee->dot11HTOperationalRateSet;
1678 u32 ratr_value = 0;
1679 u8 rate_index = 0;
1680
1681 rtl8192_config_rate(priv, (u16*)(&ratr_value));
1682 ratr_value |= (*(u16*)(pMcsRate)) << 12;
1683
1684 switch (ieee->mode)
1685 {
1686 case IEEE_A:
1687 ratr_value &= 0x00000FF0;
1688 break;
1689 case IEEE_B:
1690 ratr_value &= 0x0000000F;
1691 break;
1692 case IEEE_G:
1693 ratr_value &= 0x00000FF7;
1694 break;
1695 case IEEE_N_24G:
1696 case IEEE_N_5G:
1697 if (ieee->pHTInfo->PeerMimoPs == 0) //MIMO_PS_STATIC
1698 ratr_value &= 0x0007F007;
1699 else{
1700 if (priv->rf_type == RF_1T2R)
1701 ratr_value &= 0x000FF007;
1702 else
1703 ratr_value &= 0x0F81F007;
1704 }
1705 break;
1706 default:
1707 break;
1708 }
1709 ratr_value &= 0x0FFFFFFF;
1710 if(ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI40MHz){
1711 ratr_value |= 0x80000000;
1712 }else if(!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz){
1713 ratr_value |= 0x80000000;
1714 }
1715 write_nic_dword(priv, RATR0+rate_index*4, ratr_value);
1716 write_nic_byte(priv, UFWP, 1);
1717}
1718
1719static bool GetNmodeSupportBySecCfg8190Pci(struct ieee80211_device *ieee)
1720{
1721 return !(ieee->rtllib_ap_sec_type &&
1722 (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP)));
1723}
1724
1725static void rtl8192_refresh_supportrate(struct r8192_priv* priv)
1726{
1727 struct ieee80211_device* ieee = priv->ieee80211;
1728 //we donot consider set support rate for ABG mode, only HT MCS rate is set here.
1729 if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
1730 {
1731 memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
1732 }
1733 else
1734 memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
1735}
1736
1737static u8 rtl8192_getSupportedWireleeMode(void)
1738{
1739 return (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
1740}
1741
1742static void rtl8192_SetWirelessMode(struct ieee80211_device *ieee, u8 wireless_mode)
1743{
1744 struct r8192_priv *priv = ieee80211_priv(ieee->dev);
1745 u8 bSupportMode = rtl8192_getSupportedWireleeMode();
1746
1747 if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode)==0))
1748 {
1749 if(bSupportMode & WIRELESS_MODE_N_24G)
1750 {
1751 wireless_mode = WIRELESS_MODE_N_24G;
1752 }
1753 else if(bSupportMode & WIRELESS_MODE_N_5G)
1754 {
1755 wireless_mode = WIRELESS_MODE_N_5G;
1756 }
1757 else if((bSupportMode & WIRELESS_MODE_A))
1758 {
1759 wireless_mode = WIRELESS_MODE_A;
1760 }
1761 else if((bSupportMode & WIRELESS_MODE_G))
1762 {
1763 wireless_mode = WIRELESS_MODE_G;
1764 }
1765 else if((bSupportMode & WIRELESS_MODE_B))
1766 {
1767 wireless_mode = WIRELESS_MODE_B;
1768 }
1769 else{
1770 RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", __FUNCTION__,bSupportMode);
1771 wireless_mode = WIRELESS_MODE_B;
1772 }
1773 }
1774 priv->ieee80211->mode = wireless_mode;
1775
1776 if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G))
1777 priv->ieee80211->pHTInfo->bEnableHT = 1;
1778 else
1779 priv->ieee80211->pHTInfo->bEnableHT = 0;
1780 RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
1781 rtl8192_refresh_supportrate(priv);
1782}
1783
1784static bool GetHalfNmodeSupportByAPs819xPci(struct ieee80211_device* ieee)
1785{
1786 return ieee->bHalfWirelessN24GMode;
1787}
1788
1789static short rtl8192_is_tx_queue_empty(struct ieee80211_device *ieee)
1790{
1791 int i=0;
1792 struct r8192_priv *priv = ieee80211_priv(ieee->dev);
1793
1794 for (i=0; i<=MGNT_QUEUE; i++)
1795 {
1796 if ((i== TXCMD_QUEUE) || (i == HCCA_QUEUE) )
1797 continue;
1798 if (skb_queue_len(&(&priv->tx_ring[i])->queue) > 0){
1799 printk("===>tx queue is not empty:%d, %d\n", i, skb_queue_len(&(&priv->tx_ring[i])->queue));
1800 return 0;
1801 }
1802 }
1803 return 1;
1804}
1805
1806static void rtl8192_hw_sleep_down(struct r8192_priv *priv)
1807{
1808 MgntActSet_RF_State(priv, eRfSleep, RF_CHANGE_BY_PS);
1809}
1810
1811static void rtl8192_hw_wakeup(struct ieee80211_device *ieee)
1812{
1813 struct r8192_priv *priv = ieee80211_priv(ieee->dev);
1814 MgntActSet_RF_State(priv, eRfOn, RF_CHANGE_BY_PS);
1815}
1816
1817static void rtl8192_hw_wakeup_wq (struct work_struct *work)
1818{
1819 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
1820 struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_wakeup_wq);
1821
1822 rtl8192_hw_wakeup(ieee);
1823}
1824
1825#define MIN_SLEEP_TIME 50
1826#define MAX_SLEEP_TIME 10000
1827static void rtl8192_hw_to_sleep(struct ieee80211_device *ieee, u32 th, u32 tl)
1828{
1829 struct r8192_priv *priv = ieee80211_priv(ieee->dev);
1830 u32 tmp;
1831 u32 rb = jiffies;
1832
1833 // Writing HW register with 0 equals to disable
1834 // the timer, that is not really what we want
1835 //
1836 tl -= MSECS(8+16+7);
1837
1838 // If the interval in witch we are requested to sleep is too
1839 // short then give up and remain awake
1840 // when we sleep after send null frame, the timer will be too short to sleep.
1841 //
1842 if(((tl>=rb)&& (tl-rb) <= MSECS(MIN_SLEEP_TIME))
1843 ||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
1844 printk("too short to sleep::%x, %x, %lx\n",tl, rb, MSECS(MIN_SLEEP_TIME));
1845 return;
1846 }
1847
1848 if(((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME)))||
1849 ((tl < rb) && (tl>MSECS(69)) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))||
1850 ((tl<rb)&&(tl<MSECS(69))&&((tl+0xffffffff-rb)>MSECS(MAX_SLEEP_TIME)))) {
1851 printk("========>too long to sleep:%x, %x, %lx\n", tl, rb, MSECS(MAX_SLEEP_TIME));
1852 return;
1853 }
1854
1855 tmp = (tl>rb)?(tl-rb):(rb-tl);
1856 queue_delayed_work(priv->ieee80211->wq,
1857 &priv->ieee80211->hw_wakeup_wq,tmp);
1858
1859 rtl8192_hw_sleep_down(priv);
1860}
1861
1862static void rtl8192_init_priv_variable(struct r8192_priv *priv)
1863{
1864 u8 i;
1865 PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
1866
1867 // Default Halt the NIC if RF is OFF.
1868 pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC;
1869 pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_CLK_REQ;
1870 pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM;
1871 pPSC->RegRfPsLevel |= RT_RF_LPS_LEVEL_ASPM;
1872 pPSC->bLeisurePs = true;
1873 priv->ieee80211->RegMaxLPSAwakeIntvl = 5;
1874 priv->bHwRadioOff = false;
1875
1876 priv->being_init_adapter = false;
1877 priv->txringcount = 64;//32;
1878 priv->rxbuffersize = 9100;//2048;//1024;
1879 priv->rxringcount = MAX_RX_COUNT;//64;
1880 priv->chan = 1; //set to channel 1
1881 priv->RegWirelessMode = WIRELESS_MODE_AUTO;
1882 priv->RegChannelPlan = 0xf;
1883 priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
1884 priv->ieee80211->iw_mode = IW_MODE_INFRA;
1885 priv->ieee80211->ieee_up=0;
1886 priv->retry_rts = DEFAULT_RETRY_RTS;
1887 priv->retry_data = DEFAULT_RETRY_DATA;
1888 priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
1889 priv->ieee80211->rate = 110; //11 mbps
1890 priv->ieee80211->short_slot = 1;
1891 priv->promisc = (priv->ieee80211->dev->flags & IFF_PROMISC) ? 1:0;
1892 priv->bcck_in_ch14 = false;
1893 priv->CCKPresentAttentuation = 0;
1894 priv->rfa_txpowertrackingindex = 0;
1895 priv->rfc_txpowertrackingindex = 0;
1896 priv->CckPwEnl = 6;
1897 //added by amy for silent reset
1898 priv->ResetProgress = RESET_TYPE_NORESET;
1899 priv->bForcedSilentReset = 0;
1900 priv->bDisableNormalResetCheck = false;
1901 priv->force_reset = false;
1902 //added by amy for power save
1903 priv->RfOffReason = 0;
1904 priv->bHwRfOffAction = 0;
1905 priv->PowerSaveControl.bInactivePs = true;
1906 priv->PowerSaveControl.bIPSModeBackup = false;
1907
1908 priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
1909 priv->ieee80211->iw_mode = IW_MODE_INFRA;
1910 priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN |
1911 IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ |
1912 IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE;/* |
1913 IEEE_SOFTMAC_BEACONS;*///added by amy 080604 //| //IEEE_SOFTMAC_SINGLE_QUEUE;
1914
1915 priv->ieee80211->active_scan = 1;
1916 priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
1917 priv->ieee80211->host_encrypt = 1;
1918 priv->ieee80211->host_decrypt = 1;
1919 priv->ieee80211->start_send_beacons = rtl8192_start_beacon;
1920 priv->ieee80211->stop_send_beacons = rtl8192_stop_beacon;
1921 priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
1922 priv->ieee80211->set_chan = rtl8192_set_chan;
1923 priv->ieee80211->link_change = rtl8192_link_change;
1924 priv->ieee80211->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
1925 priv->ieee80211->data_hard_stop = rtl8192_data_hard_stop;
1926 priv->ieee80211->data_hard_resume = rtl8192_data_hard_resume;
1927 priv->ieee80211->init_wmmparam_flag = 0;
1928 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
1929 priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
1930 priv->ieee80211->tx_headroom = sizeof(TX_FWINFO_8190PCI);
1931 priv->ieee80211->qos_support = 1;
1932 priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
1933 priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
1934 priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
1935
1936 priv->ieee80211->sta_wake_up = rtl8192_hw_wakeup;
1937 priv->ieee80211->enter_sleep_state = rtl8192_hw_to_sleep;
1938 priv->ieee80211->ps_is_queue_empty = rtl8192_is_tx_queue_empty;
1939 priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8190Pci;
1940 priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
1941 priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xPci;
1942
1943 priv->ieee80211->InitialGainHandler = InitialGain819xPci;
1944
1945#ifdef ENABLE_IPS
1946 priv->ieee80211->ieee80211_ips_leave_wq = ieee80211_ips_leave_wq;
1947 priv->ieee80211->ieee80211_ips_leave = ieee80211_ips_leave;
1948#endif
1949#ifdef ENABLE_LPS
1950 priv->ieee80211->LeisurePSLeave = LeisurePSLeave;
1951#endif
1952
1953 priv->ieee80211->SetHwRegHandler = rtl8192e_SetHwReg;
1954 priv->ieee80211->rtllib_ap_sec_type = rtl8192e_ap_sec_type;
1955
1956 priv->ShortRetryLimit = 0x30;
1957 priv->LongRetryLimit = 0x30;
1958
1959 priv->ReceiveConfig = RCR_ADD3 |
1960 RCR_AMF | RCR_ADF | //accept management/data
1961 RCR_AICV | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
1962 RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
1963 RCR_AAP | ((u32)7<<RCR_MXDMA_OFFSET) |
1964 ((u32)7 << RCR_FIFO_OFFSET) | RCR_ONLYERLPKT;
1965
1966 priv->pFirmware = vzalloc(sizeof(rt_firmware));
1967
1968 /* rx related queue */
1969 skb_queue_head_init(&priv->skb_queue);
1970
1971 /* Tx related queue */
1972 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
1973 skb_queue_head_init(&priv->ieee80211->skb_waitQ [i]);
1974 }
1975 for(i = 0; i < MAX_QUEUE_SIZE; i++) {
1976 skb_queue_head_init(&priv->ieee80211->skb_aggQ [i]);
1977 }
1978 priv->rf_set_chan = rtl8192_phy_SwChnl;
1979}
1980
1981static void rtl8192_init_priv_lock(struct r8192_priv* priv)
1982{
1983 spin_lock_init(&priv->irq_th_lock);
1984 spin_lock_init(&priv->rf_ps_lock);
1985 sema_init(&priv->wx_sem,1);
1986 sema_init(&priv->rf_sem,1);
1987 mutex_init(&priv->mutex);
1988}
1989
1990/* init tasklet and wait_queue here */
1991#define DRV_NAME "wlan0"
1992static void rtl8192_init_priv_task(struct r8192_priv *priv)
1993{
1994 priv->priv_wq = create_workqueue(DRV_NAME);
1995
1996#ifdef ENABLE_IPS
1997 INIT_WORK(&priv->ieee80211->ips_leave_wq, IPSLeave_wq);
1998#endif
1999
2000 INIT_WORK(&priv->reset_wq, rtl8192_restart);
2001 INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
2002 INIT_DELAYED_WORK(&priv->txpower_tracking_wq, dm_txpower_trackingcallback);
2003 INIT_DELAYED_WORK(&priv->rfpath_check_wq, dm_rf_pathcheck_workitemcallback);
2004 INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
2005 INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
2006 INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq, rtl8192_hw_wakeup_wq);
2007
2008 tasklet_init(&priv->irq_rx_tasklet, rtl8192_irq_rx_tasklet,
2009 (unsigned long) priv);
2010 tasklet_init(&priv->irq_tx_tasklet, rtl8192_irq_tx_tasklet,
2011 (unsigned long) priv);
2012 tasklet_init(&priv->irq_prepare_beacon_tasklet, rtl8192_prepare_beacon,
2013 (unsigned long) priv);
2014}
2015
2016static void rtl8192_get_eeprom_size(struct r8192_priv *priv)
2017{
2018 u16 curCR = 0;
2019 RT_TRACE(COMP_INIT, "===========>%s()\n", __FUNCTION__);
2020 curCR = read_nic_dword(priv, EPROM_CMD);
2021 RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD, curCR);
2022 //whether need I consider BIT5?
2023 priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EPROM_93c56 : EPROM_93c46;
2024 RT_TRACE(COMP_INIT, "<===========%s(), epromtype:%d\n", __FUNCTION__, priv->epromtype);
2025}
2026
2027/*
2028 * Adapter->EEPROMAddressSize should be set before this function call.
2029 * EEPROM address size can be got through GetEEPROMSize8185()
2030 */
2031static void rtl8192_read_eeprom_info(struct r8192_priv *priv)
2032{
2033 struct net_device *dev = priv->ieee80211->dev;
2034 u8 tempval;
2035 u8 ICVer8192, ICVer8256;
2036 u16 i,usValue, IC_Version;
2037 u16 EEPROMId;
2038 u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x01};
2039 RT_TRACE(COMP_INIT, "====> rtl8192_read_eeprom_info\n");
2040
2041
2042 // TODO: I don't know if we need to apply EF function to EEPROM read function
2043
2044 //2 Read EEPROM ID to make sure autoload is success
2045 EEPROMId = eprom_read(priv, 0);
2046 if( EEPROMId != RTL8190_EEPROM_ID )
2047 {
2048 RT_TRACE(COMP_ERR, "EEPROM ID is invalid:%x, %x\n", EEPROMId, RTL8190_EEPROM_ID);
2049 priv->AutoloadFailFlag=true;
2050 }
2051 else
2052 {
2053 priv->AutoloadFailFlag=false;
2054 }
2055
2056 //
2057 // Assign Chip Version ID
2058 //
2059 // Read IC Version && Channel Plan
2060 if(!priv->AutoloadFailFlag)
2061 {
2062 // VID, PID
2063 priv->eeprom_vid = eprom_read(priv, (EEPROM_VID >> 1));
2064 priv->eeprom_did = eprom_read(priv, (EEPROM_DID >> 1));
2065
2066 usValue = eprom_read(priv, (u16)(EEPROM_Customer_ID>>1)) >> 8 ;
2067 priv->eeprom_CustomerID = (u8)( usValue & 0xff);
2068 usValue = eprom_read(priv, (EEPROM_ICVersion_ChannelPlan>>1));
2069 priv->eeprom_ChannelPlan = usValue&0xff;
2070 IC_Version = ((usValue&0xff00)>>8);
2071
2072 ICVer8192 = (IC_Version&0xf); //bit0~3; 1:A cut, 2:B cut, 3:C cut...
2073 ICVer8256 = ((IC_Version&0xf0)>>4);//bit4~6, bit7 reserved for other RF chip; 1:A cut, 2:B cut, 3:C cut...
2074 RT_TRACE(COMP_INIT, "ICVer8192 = 0x%x\n", ICVer8192);
2075 RT_TRACE(COMP_INIT, "ICVer8256 = 0x%x\n", ICVer8256);
2076 if(ICVer8192 == 0x2) //B-cut
2077 {
2078 if(ICVer8256 == 0x5) //E-cut
2079 priv->card_8192_version= VERSION_8190_BE;
2080 }
2081
2082 switch(priv->card_8192_version)
2083 {
2084 case VERSION_8190_BD:
2085 case VERSION_8190_BE:
2086 break;
2087 default:
2088 priv->card_8192_version = VERSION_8190_BD;
2089 break;
2090 }
2091 RT_TRACE(COMP_INIT, "\nIC Version = 0x%x\n", priv->card_8192_version);
2092 }
2093 else
2094 {
2095 priv->card_8192_version = VERSION_8190_BD;
2096 priv->eeprom_vid = 0;
2097 priv->eeprom_did = 0;
2098 priv->eeprom_CustomerID = 0;
2099 priv->eeprom_ChannelPlan = 0;
2100 RT_TRACE(COMP_INIT, "IC Version = 0x%x\n", 0xff);
2101 }
2102
2103 RT_TRACE(COMP_INIT, "EEPROM VID = 0x%4x\n", priv->eeprom_vid);
2104 RT_TRACE(COMP_INIT, "EEPROM DID = 0x%4x\n", priv->eeprom_did);
2105 RT_TRACE(COMP_INIT,"EEPROM Customer ID: 0x%2x\n", priv->eeprom_CustomerID);
2106
2107 //2 Read Permanent MAC address
2108 if(!priv->AutoloadFailFlag)
2109 {
2110 for(i = 0; i < 6; i += 2)
2111 {
2112 usValue = eprom_read(priv, (u16) ((EEPROM_NODE_ADDRESS_BYTE_0+i)>>1));
2113 *(u16*)(&dev->dev_addr[i]) = usValue;
2114 }
2115 } else {
2116 // when auto load failed, the last address byte set to be a random one.
2117 // added by david woo.2007/11/7
2118 memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
2119 }
2120
2121 RT_TRACE(COMP_INIT, "Permanent Address = %pM\n", dev->dev_addr);
2122
2123 //2 TX Power Check EEPROM Fail or not
2124 if(priv->card_8192_version > VERSION_8190_BD) {
2125 priv->bTXPowerDataReadFromEEPORM = true;
2126 } else {
2127 priv->bTXPowerDataReadFromEEPORM = false;
2128 }
2129
2130 // 2007/11/15 MH 8190PCI Default=2T4R, 8192PCIE default=1T2R
2131 priv->rf_type = RTL819X_DEFAULT_RF_TYPE;
2132
2133 if(priv->card_8192_version > VERSION_8190_BD)
2134 {
2135 // Read RF-indication and Tx Power gain index diff of legacy to HT OFDM rate.
2136 if(!priv->AutoloadFailFlag)
2137 {
2138 tempval = (eprom_read(priv, (EEPROM_RFInd_PowerDiff>>1))) & 0xff;
2139 priv->EEPROMLegacyHTTxPowerDiff = tempval & 0xf; // bit[3:0]
2140
2141 if (tempval&0x80) //RF-indication, bit[7]
2142 priv->rf_type = RF_1T2R;
2143 else
2144 priv->rf_type = RF_2T4R;
2145 }
2146 else
2147 {
2148 priv->EEPROMLegacyHTTxPowerDiff = EEPROM_Default_LegacyHTTxPowerDiff;
2149 }
2150 RT_TRACE(COMP_INIT, "EEPROMLegacyHTTxPowerDiff = %d\n",
2151 priv->EEPROMLegacyHTTxPowerDiff);
2152
2153 // Read ThermalMeter from EEPROM
2154 if(!priv->AutoloadFailFlag)
2155 {
2156 priv->EEPROMThermalMeter = (u8)(((eprom_read(priv, (EEPROM_ThermalMeter>>1))) & 0xff00)>>8);
2157 }
2158 else
2159 {
2160 priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
2161 }
2162 RT_TRACE(COMP_INIT, "ThermalMeter = %d\n", priv->EEPROMThermalMeter);
2163 //vivi, for tx power track
2164 priv->TSSI_13dBm = priv->EEPROMThermalMeter *100;
2165
2166 if(priv->epromtype == EPROM_93c46)
2167 {
2168 // Read antenna tx power offset of B/C/D to A and CrystalCap from EEPROM
2169 if(!priv->AutoloadFailFlag)
2170 {
2171 usValue = eprom_read(priv, (EEPROM_TxPwDiff_CrystalCap>>1));
2172 priv->EEPROMAntPwDiff = (usValue&0x0fff);
2173 priv->EEPROMCrystalCap = (u8)((usValue&0xf000)>>12);
2174 }
2175 else
2176 {
2177 priv->EEPROMAntPwDiff = EEPROM_Default_AntTxPowerDiff;
2178 priv->EEPROMCrystalCap = EEPROM_Default_TxPwDiff_CrystalCap;
2179 }
2180 RT_TRACE(COMP_INIT, "EEPROMAntPwDiff = %d\n", priv->EEPROMAntPwDiff);
2181 RT_TRACE(COMP_INIT, "EEPROMCrystalCap = %d\n", priv->EEPROMCrystalCap);
2182
2183 //
2184 // Get per-channel Tx Power Level
2185 //
2186 for(i=0; i<14; i+=2)
2187 {
2188 if(!priv->AutoloadFailFlag)
2189 {
2190 usValue = eprom_read(priv, (u16) ((EEPROM_TxPwIndex_CCK+i)>>1) );
2191 }
2192 else
2193 {
2194 usValue = EEPROM_Default_TxPower;
2195 }
2196 *((u16*)(&priv->EEPROMTxPowerLevelCCK[i])) = usValue;
2197 RT_TRACE(COMP_INIT,"CCK Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK[i]);
2198 RT_TRACE(COMP_INIT, "CCK Tx Power Level, Index %d = 0x%02x\n", i+1, priv->EEPROMTxPowerLevelCCK[i+1]);
2199 }
2200 for(i=0; i<14; i+=2)
2201 {
2202 if(!priv->AutoloadFailFlag)
2203 {
2204 usValue = eprom_read(priv, (u16) ((EEPROM_TxPwIndex_OFDM_24G+i)>>1) );
2205 }
2206 else
2207 {
2208 usValue = EEPROM_Default_TxPower;
2209 }
2210 *((u16*)(&priv->EEPROMTxPowerLevelOFDM24G[i])) = usValue;
2211 RT_TRACE(COMP_INIT, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i, priv->EEPROMTxPowerLevelOFDM24G[i]);
2212 RT_TRACE(COMP_INIT, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i+1, priv->EEPROMTxPowerLevelOFDM24G[i+1]);
2213 }
2214 }
2215
2216 //
2217 // Update HAL variables.
2218 //
2219 if(priv->epromtype == EPROM_93c46)
2220 {
2221 for(i=0; i<14; i++)
2222 {
2223 priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK[i];
2224 priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[i];
2225 }
2226 priv->LegacyHTTxPowerDiff = priv->EEPROMLegacyHTTxPowerDiff;
2227 // Antenna B gain offset to antenna A, bit0~3
2228 priv->AntennaTxPwDiff[0] = (priv->EEPROMAntPwDiff & 0xf);
2229 // Antenna C gain offset to antenna A, bit4~7
2230 priv->AntennaTxPwDiff[1] = ((priv->EEPROMAntPwDiff & 0xf0)>>4);
2231 // Antenna D gain offset to antenna A, bit8~11
2232 priv->AntennaTxPwDiff[2] = ((priv->EEPROMAntPwDiff & 0xf00)>>8);
2233 // CrystalCap, bit12~15
2234 priv->CrystalCap = priv->EEPROMCrystalCap;
2235 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
2236 priv->ThermalMeter[0] = (priv->EEPROMThermalMeter & 0xf);
2237 priv->ThermalMeter[1] = ((priv->EEPROMThermalMeter & 0xf0)>>4);
2238 }
2239 else if(priv->epromtype == EPROM_93c56)
2240 {
2241 for(i=0; i<3; i++) // channel 1~3 use the same Tx Power Level.
2242 {
2243 priv->TxPowerLevelCCK_A[i] = priv->EEPROMRfACCKChnl1TxPwLevel[0];
2244 priv->TxPowerLevelOFDM24G_A[i] = priv->EEPROMRfAOfdmChnlTxPwLevel[0];
2245 priv->TxPowerLevelCCK_C[i] = priv->EEPROMRfCCCKChnl1TxPwLevel[0];
2246 priv->TxPowerLevelOFDM24G_C[i] = priv->EEPROMRfCOfdmChnlTxPwLevel[0];
2247 }
2248 for(i=3; i<9; i++) // channel 4~9 use the same Tx Power Level
2249 {
2250 priv->TxPowerLevelCCK_A[i] = priv->EEPROMRfACCKChnl1TxPwLevel[1];
2251 priv->TxPowerLevelOFDM24G_A[i] = priv->EEPROMRfAOfdmChnlTxPwLevel[1];
2252 priv->TxPowerLevelCCK_C[i] = priv->EEPROMRfCCCKChnl1TxPwLevel[1];
2253 priv->TxPowerLevelOFDM24G_C[i] = priv->EEPROMRfCOfdmChnlTxPwLevel[1];
2254 }
2255 for(i=9; i<14; i++) // channel 10~14 use the same Tx Power Level
2256 {
2257 priv->TxPowerLevelCCK_A[i] = priv->EEPROMRfACCKChnl1TxPwLevel[2];
2258 priv->TxPowerLevelOFDM24G_A[i] = priv->EEPROMRfAOfdmChnlTxPwLevel[2];
2259 priv->TxPowerLevelCCK_C[i] = priv->EEPROMRfCCCKChnl1TxPwLevel[2];
2260 priv->TxPowerLevelOFDM24G_C[i] = priv->EEPROMRfCOfdmChnlTxPwLevel[2];
2261 }
2262 for(i=0; i<14; i++)
2263 RT_TRACE(COMP_INIT, "priv->TxPowerLevelCCK_A[%d] = 0x%x\n", i, priv->TxPowerLevelCCK_A[i]);
2264 for(i=0; i<14; i++)
2265 RT_TRACE(COMP_INIT,"priv->TxPowerLevelOFDM24G_A[%d] = 0x%x\n", i, priv->TxPowerLevelOFDM24G_A[i]);
2266 for(i=0; i<14; i++)
2267 RT_TRACE(COMP_INIT, "priv->TxPowerLevelCCK_C[%d] = 0x%x\n", i, priv->TxPowerLevelCCK_C[i]);
2268 for(i=0; i<14; i++)
2269 RT_TRACE(COMP_INIT, "priv->TxPowerLevelOFDM24G_C[%d] = 0x%x\n", i, priv->TxPowerLevelOFDM24G_C[i]);
2270 priv->LegacyHTTxPowerDiff = priv->EEPROMLegacyHTTxPowerDiff;
2271 priv->AntennaTxPwDiff[0] = 0;
2272 priv->AntennaTxPwDiff[1] = 0;
2273 priv->AntennaTxPwDiff[2] = 0;
2274 priv->CrystalCap = priv->EEPROMCrystalCap;
2275 // ThermalMeter, bit0~3 for RFIC1, bit4~7 for RFIC2
2276 priv->ThermalMeter[0] = (priv->EEPROMThermalMeter & 0xf);
2277 priv->ThermalMeter[1] = ((priv->EEPROMThermalMeter & 0xf0)>>4);
2278 }
2279 }
2280
2281 if(priv->rf_type == RF_1T2R)
2282 {
2283 RT_TRACE(COMP_INIT, "1T2R config\n");
2284 }
2285 else if (priv->rf_type == RF_2T4R)
2286 {
2287 RT_TRACE(COMP_INIT, "2T4R config\n");
2288 }
2289
2290 // 2008/01/16 MH We can only know RF type in the function. So we have to init
2291 // DIG RATR table again.
2292 init_rate_adaptive(priv);
2293
2294 //1 Make a copy for following variables and we can change them if we want
2295
2296 if(priv->RegChannelPlan == 0xf)
2297 {
2298 priv->ChannelPlan = priv->eeprom_ChannelPlan;
2299 }
2300 else
2301 {
2302 priv->ChannelPlan = priv->RegChannelPlan;
2303 }
2304
2305 //
2306 // Used PID and DID to Set CustomerID
2307 //
2308 if( priv->eeprom_vid == 0x1186 && priv->eeprom_did == 0x3304 )
2309 {
2310 priv->CustomerID = RT_CID_DLINK;
2311 }
2312
2313 switch(priv->eeprom_CustomerID)
2314 {
2315 case EEPROM_CID_DEFAULT:
2316 priv->CustomerID = RT_CID_DEFAULT;
2317 break;
2318 case EEPROM_CID_CAMEO:
2319 priv->CustomerID = RT_CID_819x_CAMEO;
2320 break;
2321 case EEPROM_CID_RUNTOP:
2322 priv->CustomerID = RT_CID_819x_RUNTOP;
2323 break;
2324 case EEPROM_CID_NetCore:
2325 priv->CustomerID = RT_CID_819x_Netcore;
2326 break;
2327 case EEPROM_CID_TOSHIBA: // Merge by Jacken, 2008/01/31
2328 priv->CustomerID = RT_CID_TOSHIBA;
2329 if(priv->eeprom_ChannelPlan&0x80)
2330 priv->ChannelPlan = priv->eeprom_ChannelPlan&0x7f;
2331 else
2332 priv->ChannelPlan = 0x0;
2333 RT_TRACE(COMP_INIT, "Toshiba ChannelPlan = 0x%x\n",
2334 priv->ChannelPlan);
2335 break;
2336 case EEPROM_CID_Nettronix:
2337 priv->CustomerID = RT_CID_Nettronix;
2338 break;
2339 case EEPROM_CID_Pronet:
2340 priv->CustomerID = RT_CID_PRONET;
2341 break;
2342 case EEPROM_CID_DLINK:
2343 priv->CustomerID = RT_CID_DLINK;
2344 break;
2345
2346 case EEPROM_CID_WHQL:
2347 break;
2348 default:
2349 // value from RegCustomerID
2350 break;
2351 }
2352
2353 //Avoid the channel plan array overflow, by Bruce, 2007-08-27.
2354 if(priv->ChannelPlan > CHANNEL_PLAN_LEN - 1)
2355 priv->ChannelPlan = 0; //FCC
2356
2357 if( priv->eeprom_vid == 0x1186 && priv->eeprom_did == 0x3304)
2358 priv->ieee80211->bSupportRemoteWakeUp = true;
2359 else
2360 priv->ieee80211->bSupportRemoteWakeUp = false;
2361
2362
2363 RT_TRACE(COMP_INIT, "RegChannelPlan(%d)\n", priv->RegChannelPlan);
2364 RT_TRACE(COMP_INIT, "ChannelPlan = %d\n", priv->ChannelPlan);
2365 RT_TRACE(COMP_TRACE, "<==== ReadAdapterInfo\n");
2366}
2367
2368
2369static short rtl8192_get_channel_map(struct r8192_priv *priv)
2370{
2371#ifdef ENABLE_DOT11D
2372 if(priv->ChannelPlan> COUNTRY_CODE_GLOBAL_DOMAIN){
2373 printk("rtl8180_init:Error channel plan! Set to default.\n");
2374 priv->ChannelPlan= 0;
2375 }
2376 RT_TRACE(COMP_INIT, "Channel plan is %d\n",priv->ChannelPlan);
2377
2378 rtl819x_set_channel_map(priv->ChannelPlan, priv);
2379#else
2380 int ch,i;
2381 //Set Default Channel Plan
2382 if(!channels){
2383 DMESG("No channels, aborting");
2384 return -1;
2385 }
2386 ch=channels;
2387 priv->ChannelPlan= 0;//hikaru
2388 // set channels 1..14 allowed in given locale
2389 for (i=1; i<=14; i++) {
2390 (priv->ieee80211->channel_map)[i] = (u8)(ch & 0x01);
2391 ch >>= 1;
2392 }
2393#endif
2394 return 0;
2395}
2396
2397static short rtl8192_init(struct r8192_priv *priv)
2398{
2399 struct net_device *dev = priv->ieee80211->dev;
2400
2401 memset(&(priv->stats),0,sizeof(struct Stats));
2402 rtl8192_init_priv_variable(priv);
2403 rtl8192_init_priv_lock(priv);
2404 rtl8192_init_priv_task(priv);
2405 rtl8192_get_eeprom_size(priv);
2406 rtl8192_read_eeprom_info(priv);
2407 rtl8192_get_channel_map(priv);
2408 init_hal_dm(priv);
2409 init_timer(&priv->watch_dog_timer);
2410 priv->watch_dog_timer.data = (unsigned long)priv;
2411 priv->watch_dog_timer.function = watch_dog_timer_callback;
2412 if (request_irq(dev->irq, rtl8192_interrupt, IRQF_SHARED, dev->name, priv)) {
2413 printk("Error allocating IRQ %d",dev->irq);
2414 return -1;
2415 }else{
2416 priv->irq=dev->irq;
2417 printk("IRQ %d",dev->irq);
2418 }
2419 if (rtl8192_pci_initdescring(priv) != 0){
2420 printk("Endopoints initialization failed");
2421 return -1;
2422 }
2423
2424 return 0;
2425}
2426
2427/*
2428 * Actually only set RRSR, RATR and BW_OPMODE registers
2429 * not to do all the hw config as its name says
2430 * This part need to modified according to the rate set we filtered
2431 */
2432static void rtl8192_hwconfig(struct r8192_priv *priv)
2433{
2434 u32 regRATR = 0, regRRSR = 0;
2435 u8 regBwOpMode = 0, regTmp = 0;
2436
2437// Set RRSR, RATR, and BW_OPMODE registers
2438 //
2439 switch (priv->ieee80211->mode)
2440 {
2441 case WIRELESS_MODE_B:
2442 regBwOpMode = BW_OPMODE_20MHZ;
2443 regRATR = RATE_ALL_CCK;
2444 regRRSR = RATE_ALL_CCK;
2445 break;
2446 case WIRELESS_MODE_A:
2447 regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ;
2448 regRATR = RATE_ALL_OFDM_AG;
2449 regRRSR = RATE_ALL_OFDM_AG;
2450 break;
2451 case WIRELESS_MODE_G:
2452 regBwOpMode = BW_OPMODE_20MHZ;
2453 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2454 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2455 break;
2456 case WIRELESS_MODE_AUTO:
2457 case WIRELESS_MODE_N_24G:
2458 // It support CCK rate by default.
2459 // CCK rate will be filtered out only when associated AP does not support it.
2460 regBwOpMode = BW_OPMODE_20MHZ;
2461 regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2462 regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG;
2463 break;
2464 case WIRELESS_MODE_N_5G:
2465 regBwOpMode = BW_OPMODE_5G;
2466 regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS;
2467 regRRSR = RATE_ALL_OFDM_AG;
2468 break;
2469 }
2470
2471 write_nic_byte(priv, BW_OPMODE, regBwOpMode);
2472 {
2473 u32 ratr_value = 0;
2474 ratr_value = regRATR;
2475 if (priv->rf_type == RF_1T2R)
2476 {
2477 ratr_value &= ~(RATE_ALL_OFDM_2SS);
2478 }
2479 write_nic_dword(priv, RATR0, ratr_value);
2480 write_nic_byte(priv, UFWP, 1);
2481 }
2482 regTmp = read_nic_byte(priv, 0x313);
2483 regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
2484 write_nic_dword(priv, RRSR, regRRSR);
2485
2486 //
2487 // Set Retry Limit here
2488 //
2489 write_nic_word(priv, RETRY_LIMIT,
2490 priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
2491 priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
2492 // Set Contention Window here
2493
2494 // Set Tx AGC
2495
2496 // Set Tx Antenna including Feedback control
2497
2498 // Set Auto Rate fallback control
2499
2500
2501}
2502
2503
2504static RT_STATUS rtl8192_adapter_start(struct r8192_priv *priv)
2505{
2506 struct net_device *dev = priv->ieee80211->dev;
2507 u32 ulRegRead;
2508 RT_STATUS rtStatus = RT_STATUS_SUCCESS;
2509 u8 tmpvalue;
2510 u8 ICVersion,SwitchingRegulatorOutput;
2511 bool bfirmwareok = true;
2512 u32 tmpRegA, tmpRegC, TempCCk;
2513 int i =0;
2514
2515 RT_TRACE(COMP_INIT, "====>%s()\n", __FUNCTION__);
2516 priv->being_init_adapter = true;
2517 rtl8192_pci_resetdescring(priv);
2518 // 2007/11/02 MH Before initalizing RF. We can not use FW to do RF-R/W.
2519 priv->Rf_Mode = RF_OP_By_SW_3wire;
2520
2521 //dPLL on
2522 if(priv->ResetProgress == RESET_TYPE_NORESET)
2523 {
2524 write_nic_byte(priv, ANAPAR, 0x37);
2525 // Accordign to designer's explain, LBUS active will never > 10ms. We delay 10ms
2526 // Joseph increae the time to prevent firmware download fail
2527 mdelay(500);
2528 }
2529
2530 //PlatformSleepUs(10000);
2531 // For any kind of InitializeAdapter process, we shall use system now!!
2532 priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
2533
2534 //
2535 //3 //Config CPUReset Register
2536 //3//
2537 //3 Firmware Reset Or Not
2538 ulRegRead = read_nic_dword(priv, CPU_GEN);
2539 if(priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
2540 { //called from MPInitialized. do nothing
2541 ulRegRead |= CPU_GEN_SYSTEM_RESET;
2542 }else if(priv->pFirmware->firmware_status == FW_STATUS_5_READY)
2543 ulRegRead |= CPU_GEN_FIRMWARE_RESET; // Called from MPReset
2544 else
2545 RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __FUNCTION__, priv->pFirmware->firmware_status);
2546
2547 write_nic_dword(priv, CPU_GEN, ulRegRead);
2548
2549 //3//
2550 //3 //Fix the issue of E-cut high temperature issue
2551 //3//
2552 // TODO: E cut only
2553 ICVersion = read_nic_byte(priv, IC_VERRSION);
2554 if(ICVersion >= 0x4) //E-cut only
2555 {
2556 // HW SD suggest that we should not wirte this register too often, so driver
2557 // should readback this register. This register will be modified only when
2558 // power on reset
2559 SwitchingRegulatorOutput = read_nic_byte(priv, SWREGULATOR);
2560 if(SwitchingRegulatorOutput != 0xb8)
2561 {
2562 write_nic_byte(priv, SWREGULATOR, 0xa8);
2563 mdelay(1);
2564 write_nic_byte(priv, SWREGULATOR, 0xb8);
2565 }
2566 }
2567
2568 //3//
2569 //3// Initialize BB before MAC
2570 //3//
2571 RT_TRACE(COMP_INIT, "BB Config Start!\n");
2572 rtStatus = rtl8192_BBConfig(priv);
2573 if(rtStatus != RT_STATUS_SUCCESS)
2574 {
2575 RT_TRACE(COMP_ERR, "BB Config failed\n");
2576 return rtStatus;
2577 }
2578 RT_TRACE(COMP_INIT,"BB Config Finished!\n");
2579
2580 //3//Set Loopback mode or Normal mode
2581 //3//
2582 //2006.12.13 by emily. Note!We should not merge these two CPU_GEN register writings
2583 // because setting of System_Reset bit reset MAC to default transmission mode.
2584 //Loopback mode or not
2585 priv->LoopbackMode = RTL819X_NO_LOOPBACK;
2586 if(priv->ResetProgress == RESET_TYPE_NORESET)
2587 {
2588 ulRegRead = read_nic_dword(priv, CPU_GEN);
2589 if(priv->LoopbackMode == RTL819X_NO_LOOPBACK)
2590 {
2591 ulRegRead = ((ulRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
2592 }
2593 else if (priv->LoopbackMode == RTL819X_MAC_LOOPBACK )
2594 {
2595 ulRegRead |= CPU_CCK_LOOPBACK;
2596 }
2597 else
2598 {
2599 RT_TRACE(COMP_ERR,"Serious error: wrong loopback mode setting\n");
2600 }
2601
2602 //2008.06.03, for WOL
2603 //ulRegRead &= (~(CPU_GEN_GPIO_UART));
2604 write_nic_dword(priv, CPU_GEN, ulRegRead);
2605
2606 // 2006.11.29. After reset cpu, we sholud wait for a second, otherwise, it may fail to write registers. Emily
2607 udelay(500);
2608 }
2609 //3Set Hardware(Do nothing now)
2610 rtl8192_hwconfig(priv);
2611 //2=======================================================
2612 // Common Setting for all of the FPGA platform. (part 1)
2613 //2=======================================================
2614 // If there is changes, please make sure it applies to all of the FPGA version
2615 //3 Turn on Tx/Rx
2616 write_nic_byte(priv, CMDR, CR_RE|CR_TE);
2617
2618 //2Set Tx dma burst
2619 write_nic_byte(priv, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) |
2620 (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT) ));
2621
2622 //set IDR0 here
2623 write_nic_dword(priv, MAC0, ((u32*)dev->dev_addr)[0]);
2624 write_nic_word(priv, MAC4, ((u16*)(dev->dev_addr + 4))[0]);
2625 //set RCR
2626 write_nic_dword(priv, RCR, priv->ReceiveConfig);
2627
2628 //3 Initialize Number of Reserved Pages in Firmware Queue
2629 write_nic_dword(priv, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |
2630 NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT |
2631 NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT |
2632 NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
2633 write_nic_dword(priv, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
2634 write_nic_dword(priv, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
2635 NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT|
2636 NUM_OF_PAGE_IN_FW_QUEUE_PUB<<RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
2637
2638 rtl8192_tx_enable(priv);
2639 rtl8192_rx_enable(priv);
2640 //3Set Response Rate Setting Register
2641 // CCK rate is supported by default.
2642 // CCK rate will be filtered out only when associated AP does not support it.
2643 ulRegRead = (0xFFF00000 & read_nic_dword(priv, RRSR)) | RATE_ALL_OFDM_AG | RATE_ALL_CCK;
2644 write_nic_dword(priv, RRSR, ulRegRead);
2645 write_nic_dword(priv, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
2646
2647 //2Set AckTimeout
2648 // TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
2649 write_nic_byte(priv, ACK_TIMEOUT, 0x30);
2650
2651 if(priv->ResetProgress == RESET_TYPE_NORESET)
2652 rtl8192_SetWirelessMode(priv->ieee80211, priv->ieee80211->mode);
2653 //-----------------------------------------------------------------------------
2654 // Set up security related. 070106, by rcnjko:
2655 // 1. Clear all H/W keys.
2656 // 2. Enable H/W encryption/decryption.
2657 //-----------------------------------------------------------------------------
2658 CamResetAllEntry(priv);
2659 {
2660 u8 SECR_value = 0x0;
2661 SECR_value |= SCR_TxEncEnable;
2662 SECR_value |= SCR_RxDecEnable;
2663 SECR_value |= SCR_NoSKMC;
2664 write_nic_byte(priv, SECR, SECR_value);
2665 }
2666 //3Beacon related
2667 write_nic_word(priv, ATIMWND, 2);
2668 write_nic_word(priv, BCN_INTERVAL, 100);
2669 for (i=0; i<QOS_QUEUE_NUM; i++)
2670 write_nic_dword(priv, WDCAPARA_ADD[i], 0x005e4332);
2671 //
2672 // Switching regulator controller: This is set temporarily.
2673 // It's not sure if this can be removed in the future.
2674 // PJ advised to leave it by default.
2675 //
2676 write_nic_byte(priv, 0xbe, 0xc0);
2677
2678 //2=======================================================
2679 // Set PHY related configuration defined in MAC register bank
2680 //2=======================================================
2681 rtl8192_phy_configmac(priv);
2682
2683 if (priv->card_8192_version > (u8) VERSION_8190_BD) {
2684 rtl8192_phy_getTxPower(priv);
2685 rtl8192_phy_setTxPower(priv, priv->chan);
2686 }
2687
2688 //if D or C cut
2689 tmpvalue = read_nic_byte(priv, IC_VERRSION);
2690 priv->IC_Cut = tmpvalue;
2691 RT_TRACE(COMP_INIT, "priv->IC_Cut = 0x%x\n", priv->IC_Cut);
2692 if(priv->IC_Cut >= IC_VersionCut_D)
2693 {
2694 //pHalData->bDcut = TRUE;
2695 if(priv->IC_Cut == IC_VersionCut_D)
2696 RT_TRACE(COMP_INIT, "D-cut\n");
2697 if(priv->IC_Cut == IC_VersionCut_E)
2698 {
2699 RT_TRACE(COMP_INIT, "E-cut\n");
2700 // HW SD suggest that we should not wirte this register too often, so driver
2701 // should readback this register. This register will be modified only when
2702 // power on reset
2703 }
2704 }
2705 else
2706 {
2707 //pHalData->bDcut = FALSE;
2708 RT_TRACE(COMP_INIT, "Before C-cut\n");
2709 }
2710
2711 //Firmware download
2712 RT_TRACE(COMP_INIT, "Load Firmware!\n");
2713 bfirmwareok = init_firmware(priv);
2714 if(bfirmwareok != true) {
2715 rtStatus = RT_STATUS_FAILURE;
2716 return rtStatus;
2717 }
2718 RT_TRACE(COMP_INIT, "Load Firmware finished!\n");
2719
2720 //RF config
2721 if(priv->ResetProgress == RESET_TYPE_NORESET)
2722 {
2723 RT_TRACE(COMP_INIT, "RF Config Started!\n");
2724 rtStatus = rtl8192_phy_RFConfig(priv);
2725 if(rtStatus != RT_STATUS_SUCCESS)
2726 {
2727 RT_TRACE(COMP_ERR, "RF Config failed\n");
2728 return rtStatus;
2729 }
2730 RT_TRACE(COMP_INIT, "RF Config Finished!\n");
2731 }
2732 rtl8192_phy_updateInitGain(priv);
2733
2734 /*---- Set CCK and OFDM Block "ON"----*/
2735 rtl8192_setBBreg(priv, rFPGA0_RFMOD, bCCKEn, 0x1);
2736 rtl8192_setBBreg(priv, rFPGA0_RFMOD, bOFDMEn, 0x1);
2737
2738 //Enable Led
2739 write_nic_byte(priv, 0x87, 0x0);
2740
2741 //2=======================================================
2742 // RF Power Save
2743 //2=======================================================
2744#ifdef ENABLE_IPS
2745
2746{
2747 if(priv->RfOffReason > RF_CHANGE_BY_PS)
2748 { // H/W or S/W RF OFF before sleep.
2749 RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RfOffReason(%d)\n", __FUNCTION__,priv->RfOffReason);
2750 MgntActSet_RF_State(priv, eRfOff, priv->RfOffReason);
2751 }
2752 else if(priv->RfOffReason >= RF_CHANGE_BY_IPS)
2753 { // H/W or S/W RF OFF before sleep.
2754 RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RfOffReason(%d)\n", __FUNCTION__, priv->RfOffReason);
2755 MgntActSet_RF_State(priv, eRfOff, priv->RfOffReason);
2756 }
2757 else
2758 {
2759 RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): RF-ON \n",__FUNCTION__);
2760 priv->eRFPowerState = eRfOn;
2761 priv->RfOffReason = 0;
2762 }
2763}
2764#endif
2765 // We can force firmware to do RF-R/W
2766 if(priv->ieee80211->FwRWRF)
2767 priv->Rf_Mode = RF_OP_By_FW;
2768 else
2769 priv->Rf_Mode = RF_OP_By_SW_3wire;
2770
2771 if(priv->ResetProgress == RESET_TYPE_NORESET)
2772 {
2773 dm_initialize_txpower_tracking(priv);
2774
2775 if(priv->IC_Cut >= IC_VersionCut_D)
2776 {
2777 tmpRegA = rtl8192_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord);
2778 tmpRegC = rtl8192_QueryBBReg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord);
2779 for(i = 0; i<TxBBGainTableLength; i++)
2780 {
2781 if(tmpRegA == priv->txbbgain_table[i].txbbgain_value)
2782 {
2783 priv->rfa_txpowertrackingindex= (u8)i;
2784 priv->rfa_txpowertrackingindex_real= (u8)i;
2785 priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
2786 break;
2787 }
2788 }
2789
2790 TempCCk = rtl8192_QueryBBReg(priv, rCCK0_TxFilter1, bMaskByte2);
2791
2792 for(i=0 ; i<CCKTxBBGainTableLength ; i++)
2793 {
2794 if(TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0])
2795 {
2796 priv->CCKPresentAttentuation_20Mdefault =(u8) i;
2797 break;
2798 }
2799 }
2800 priv->CCKPresentAttentuation_40Mdefault = 0;
2801 priv->CCKPresentAttentuation_difference = 0;
2802 priv->CCKPresentAttentuation = priv->CCKPresentAttentuation_20Mdefault;
2803 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_initial = %d\n", priv->rfa_txpowertrackingindex);
2804 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real__initial = %d\n", priv->rfa_txpowertrackingindex_real);
2805 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference_initial = %d\n", priv->CCKPresentAttentuation_difference);
2806 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_initial = %d\n", priv->CCKPresentAttentuation);
2807 priv->btxpower_tracking = FALSE;//TEMPLY DISABLE
2808 }
2809 }
2810
2811 rtl8192_irq_enable(priv);
2812 priv->being_init_adapter = false;
2813 return rtStatus;
2814
2815}
2816
2817static void rtl8192_prepare_beacon(unsigned long arg)
2818{
2819 struct r8192_priv *priv = (struct r8192_priv*) arg;
2820 struct sk_buff *skb;
2821 cb_desc *tcb_desc;
2822
2823 skb = ieee80211_get_beacon(priv->ieee80211);
2824 tcb_desc = (cb_desc *)(skb->cb + 8);
2825 /* prepare misc info for the beacon xmit */
2826 tcb_desc->queue_index = BEACON_QUEUE;
2827 /* IBSS does not support HT yet, use 1M defaultly */
2828 tcb_desc->data_rate = 2;
2829 tcb_desc->RATRIndex = 7;
2830 tcb_desc->bTxDisableRateFallBack = 1;
2831 tcb_desc->bTxUseDriverAssingedRate = 1;
2832
2833 skb_push(skb, priv->ieee80211->tx_headroom);
2834 if(skb){
2835 rtl8192_tx(priv, skb);
2836 }
2837}
2838
2839
2840/*
2841 * configure registers for beacon tx and enables it via
2842 * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
2843 * be used to stop beacon transmission
2844 */
2845static void rtl8192_start_beacon(struct ieee80211_device *ieee80211)
2846{
2847 struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
2848 struct ieee80211_network *net = &priv->ieee80211->current_network;
2849 u16 BcnTimeCfg = 0;
2850 u16 BcnCW = 6;
2851 u16 BcnIFS = 0xf;
2852
2853 DMESG("Enabling beacon TX");
2854 rtl8192_irq_disable(priv);
2855 //rtl8192_beacon_tx_enable(dev);
2856
2857 /* ATIM window */
2858 write_nic_word(priv, ATIMWND, 2);
2859
2860 /* Beacon interval (in unit of TU) */
2861 write_nic_word(priv, BCN_INTERVAL, net->beacon_interval);
2862
2863 /*
2864 * DrvErlyInt (in unit of TU).
2865 * (Time to send interrupt to notify driver to c
2866 * hange beacon content)
2867 * */
2868 write_nic_word(priv, BCN_DRV_EARLY_INT, 10);
2869
2870 /*
2871 * BcnDMATIM(in unit of us).
2872 * Indicates the time before TBTT to perform beacon queue DMA
2873 * */
2874 write_nic_word(priv, BCN_DMATIME, 256);
2875
2876 /*
2877 * Force beacon frame transmission even after receiving
2878 * beacon frame from other ad hoc STA
2879 * */
2880 write_nic_byte(priv, BCN_ERR_THRESH, 100);
2881
2882 /* Set CW and IFS */
2883 BcnTimeCfg |= BcnCW<<BCN_TCFG_CW_SHIFT;
2884 BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
2885 write_nic_word(priv, BCN_TCFG, BcnTimeCfg);
2886
2887
2888 /* enable the interrupt for ad-hoc process */
2889 rtl8192_irq_enable(priv);
2890}
2891
2892static bool HalRxCheckStuck8190Pci(struct r8192_priv *priv)
2893{
2894 u16 RegRxCounter = read_nic_word(priv, 0x130);
2895 bool bStuck = FALSE;
2896
2897 RT_TRACE(COMP_RESET,"%s(): RegRxCounter is %d,RxCounter is %d\n",__FUNCTION__,RegRxCounter,priv->RxCounter);
2898 // If rssi is small, we should check rx for long time because of bad rx.
2899 // or maybe it will continuous silent reset every 2 seconds.
2900 priv->rx_chk_cnt++;
2901 if(priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5))
2902 {
2903 priv->rx_chk_cnt = 0; /* high rssi, check rx stuck right now. */
2904 }
2905 else if(priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
2906 ((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_40M) ||
2907 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_20M)) )
2908
2909 {
2910 if(priv->rx_chk_cnt < 2)
2911 {
2912 return bStuck;
2913 }
2914 else
2915 {
2916 priv->rx_chk_cnt = 0;
2917 }
2918 }
2919 else if(((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_40M) ||
2920 (priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_20M)) &&
2921 priv->undecorated_smoothed_pwdb >= VeryLowRSSI)
2922 {
2923 if(priv->rx_chk_cnt < 4)
2924 {
2925 return bStuck;
2926 }
2927 else
2928 {
2929 priv->rx_chk_cnt = 0;
2930 }
2931 }
2932 else
2933 {
2934 if(priv->rx_chk_cnt < 8)
2935 {
2936 return bStuck;
2937 }
2938 else
2939 {
2940 priv->rx_chk_cnt = 0;
2941 }
2942 }
2943 if(priv->RxCounter==RegRxCounter)
2944 bStuck = TRUE;
2945
2946 priv->RxCounter = RegRxCounter;
2947
2948 return bStuck;
2949}
2950
2951static RESET_TYPE RxCheckStuck(struct r8192_priv *priv)
2952{
2953
2954 if(HalRxCheckStuck8190Pci(priv))
2955 {
2956 RT_TRACE(COMP_RESET, "RxStuck Condition\n");
2957 return RESET_TYPE_SILENT;
2958 }
2959
2960 return RESET_TYPE_NORESET;
2961}
2962
2963static RESET_TYPE rtl819x_check_reset(struct r8192_priv *priv)
2964{
2965 RESET_TYPE RxResetType = RESET_TYPE_NORESET;
2966 RT_RF_POWER_STATE rfState;
2967
2968 rfState = priv->eRFPowerState;
2969
2970 if (rfState != eRfOff && (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) {
2971 /*
2972 * If driver is in the status of firmware download failure,
2973 * driver skips RF initialization and RF is in turned off state.
2974 * Driver should check whether Rx stuck and do silent reset. And
2975 * if driver is in firmware download failure status, driver
2976 * should initialize RF in the following silent reset procedure
2977 *
2978 * Driver should not check RX stuck in IBSS mode because it is
2979 * required to set Check BSSID in order to send beacon, however,
2980 * if check BSSID is set, STA cannot hear any packet a all.
2981 */
2982 RxResetType = RxCheckStuck(priv);
2983 }
2984
2985 RT_TRACE(COMP_RESET, "%s(): RxResetType is %d\n", __FUNCTION__, RxResetType);
2986
2987 return RxResetType;
2988}
2989
2990#ifdef ENABLE_IPS
2991static void InactivePsWorkItemCallback(struct r8192_priv *priv)
2992{
2993 PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
2994
2995 RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() --------->\n");
2996 //
2997 // This flag "bSwRfProcessing", indicates the status of IPS procedure, should be set if the IPS workitem
2998 // is really scheduled.
2999 // The old code, sets this flag before scheduling the IPS workitem and however, at the same time the
3000 // previous IPS workitem did not end yet, fails to schedule the current workitem. Thus, bSwRfProcessing
3001 // blocks the IPS procedure of switching RF.
3002 // By Bruce, 2007-12-25.
3003 //
3004 pPSC->bSwRfProcessing = TRUE;
3005
3006 RT_TRACE(COMP_RF, "InactivePsWorkItemCallback(): Set RF to %s.\n",
3007 pPSC->eInactivePowerState == eRfOff?"OFF":"ON");
3008
3009
3010 MgntActSet_RF_State(priv, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS);
3011
3012 //
3013 // To solve CAM values miss in RF OFF, rewrite CAM values after RF ON. By Bruce, 2007-09-20.
3014 //
3015 pPSC->bSwRfProcessing = FALSE;
3016 RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() <---------\n");
3017}
3018
3019#ifdef ENABLE_LPS
3020/* Change current and default preamble mode. */
3021bool MgntActSet_802_11_PowerSaveMode(struct r8192_priv *priv, u8 rtPsMode)
3022{
3023
3024 // Currently, we do not change power save mode on IBSS mode.
3025 if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
3026 {
3027 return false;
3028 }
3029
3030 //
3031 // <RJ_NOTE> If we make HW to fill up the PwrMgt bit for us,
3032 // some AP will not response to our mgnt frames with PwrMgt bit set,
3033 // e.g. cannot associate the AP.
3034 // So I commented out it. 2005.02.16, by rcnjko.
3035 //
3036// // Change device's power save mode.
3037// Adapter->HalFunc.SetPSModeHandler( Adapter, rtPsMode );
3038
3039 // Update power save mode configured.
3040 //RT_TRACE(COMP_LPS,"%s(): set ieee->ps = %x\n",__FUNCTION__,rtPsMode);
3041 if(!priv->ps_force) {
3042 priv->ieee80211->ps = rtPsMode;
3043 }
3044
3045 // Awake immediately
3046 if(priv->ieee80211->sta_sleep != 0 && rtPsMode == IEEE80211_PS_DISABLED)
3047 {
3048 // Notify the AP we awke.
3049 rtl8192_hw_wakeup(priv->ieee80211);
3050 priv->ieee80211->sta_sleep = 0;
3051
3052 spin_lock(&priv->ieee80211->mgmt_tx_lock);
3053 printk("LPS leave: notify AP we are awaked ++++++++++ SendNullFunctionData\n");
3054 ieee80211_sta_ps_send_null_frame(priv->ieee80211, 0);
3055 spin_unlock(&priv->ieee80211->mgmt_tx_lock);
3056 }
3057
3058 return true;
3059}
3060
3061/* Enter the leisure power save mode. */
3062void LeisurePSEnter(struct ieee80211_device *ieee80211)
3063{
3064 struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
3065 PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
3066
3067 if(!((priv->ieee80211->iw_mode == IW_MODE_INFRA) &&
3068 (priv->ieee80211->state == IEEE80211_LINKED)) ||
3069 (priv->ieee80211->iw_mode == IW_MODE_ADHOC) ||
3070 (priv->ieee80211->iw_mode == IW_MODE_MASTER))
3071 return;
3072
3073 if (pPSC->bLeisurePs)
3074 {
3075 // Idle for a while if we connect to AP a while ago.
3076 if(pPSC->LpsIdleCount >= RT_CHECK_FOR_HANG_PERIOD) // 4 Sec
3077 {
3078
3079 if(priv->ieee80211->ps == IEEE80211_PS_DISABLED)
3080 {
3081 MgntActSet_802_11_PowerSaveMode(priv, IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST);
3082
3083 }
3084 }
3085 else
3086 pPSC->LpsIdleCount++;
3087 }
3088}
3089
3090
3091/* Leave leisure power save mode. */
3092void LeisurePSLeave(struct ieee80211_device *ieee80211)
3093{
3094 struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
3095 PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
3096
3097 if (pPSC->bLeisurePs)
3098 {
3099 if(priv->ieee80211->ps != IEEE80211_PS_DISABLED)
3100 {
3101 // move to lps_wakecomplete()
3102 MgntActSet_802_11_PowerSaveMode(priv, IEEE80211_PS_DISABLED);
3103
3104 }
3105 }
3106}
3107#endif
3108
3109
3110/* Enter the inactive power save mode. RF will be off */
3111void IPSEnter(struct r8192_priv *priv)
3112{
3113 PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
3114 RT_RF_POWER_STATE rtState;
3115
3116 if (pPSC->bInactivePs)
3117 {
3118 rtState = priv->eRFPowerState;
3119 //
3120 // Added by Bruce, 2007-12-25.
3121 // Do not enter IPS in the following conditions:
3122 // (1) RF is already OFF or Sleep
3123 // (2) bSwRfProcessing (indicates the IPS is still under going)
3124 // (3) Connectted (only disconnected can trigger IPS)
3125 // (4) IBSS (send Beacon)
3126 // (5) AP mode (send Beacon)
3127 //
3128 if (rtState == eRfOn && !pPSC->bSwRfProcessing
3129 && (priv->ieee80211->state != IEEE80211_LINKED) )
3130 {
3131 RT_TRACE(COMP_RF,"IPSEnter(): Turn off RF.\n");
3132 pPSC->eInactivePowerState = eRfOff;
3133// queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
3134 InactivePsWorkItemCallback(priv);
3135 }
3136 }
3137}
3138
3139//
3140// Description:
3141// Leave the inactive power save mode, RF will be on.
3142// 2007.08.17, by shien chang.
3143//
3144void IPSLeave(struct r8192_priv *priv)
3145{
3146 PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
3147 RT_RF_POWER_STATE rtState;
3148
3149 if (pPSC->bInactivePs)
3150 {
3151 rtState = priv->eRFPowerState;
3152 if (rtState != eRfOn && !pPSC->bSwRfProcessing && priv->RfOffReason <= RF_CHANGE_BY_IPS)
3153 {
3154 RT_TRACE(COMP_POWER, "IPSLeave(): Turn on RF.\n");
3155 pPSC->eInactivePowerState = eRfOn;
3156 InactivePsWorkItemCallback(priv);
3157 }
3158 }
3159}
3160
3161void IPSLeave_wq(struct work_struct *work)
3162{
3163 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, ips_leave_wq);
3164 struct net_device *dev = ieee->dev;
3165
3166 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3167 down(&priv->ieee80211->ips_sem);
3168 IPSLeave(priv);
3169 up(&priv->ieee80211->ips_sem);
3170}
3171
3172void ieee80211_ips_leave_wq(struct ieee80211_device *ieee80211)
3173{
3174 struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
3175 RT_RF_POWER_STATE rtState;
3176 rtState = priv->eRFPowerState;
3177
3178 if (priv->PowerSaveControl.bInactivePs){
3179 if(rtState == eRfOff){
3180 if(priv->RfOffReason > RF_CHANGE_BY_IPS)
3181 {
3182 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
3183 return;
3184 }
3185 else{
3186 printk("=========>%s(): IPSLeave\n",__FUNCTION__);
3187 queue_work(priv->ieee80211->wq,&priv->ieee80211->ips_leave_wq);
3188 }
3189 }
3190 }
3191}
3192//added by amy 090331 end
3193void ieee80211_ips_leave(struct ieee80211_device *ieee80211)
3194{
3195 struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
3196 down(&ieee80211->ips_sem);
3197 IPSLeave(priv);
3198 up(&ieee80211->ips_sem);
3199}
3200#endif
3201
3202static void rtl819x_update_rxcounts(
3203 struct r8192_priv *priv,
3204 u32* TotalRxBcnNum,
3205 u32* TotalRxDataNum
3206)
3207{
3208 u16 SlotIndex;
3209 u8 i;
3210
3211 *TotalRxBcnNum = 0;
3212 *TotalRxDataNum = 0;
3213
3214 SlotIndex = (priv->ieee80211->LinkDetectInfo.SlotIndex++)%(priv->ieee80211->LinkDetectInfo.SlotNum);
3215 priv->ieee80211->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvBcnInPeriod;
3216 priv->ieee80211->LinkDetectInfo.RxDataNum[SlotIndex] = priv->ieee80211->LinkDetectInfo.NumRecvDataInPeriod;
3217 for( i=0; i<priv->ieee80211->LinkDetectInfo.SlotNum; i++ ){
3218 *TotalRxBcnNum += priv->ieee80211->LinkDetectInfo.RxBcnNum[i];
3219 *TotalRxDataNum += priv->ieee80211->LinkDetectInfo.RxDataNum[i];
3220 }
3221}
3222
3223
3224static void rtl819x_watchdog_wqcallback(struct work_struct *work)
3225{
3226 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
3227 struct r8192_priv *priv = container_of(dwork,struct r8192_priv,watch_dog_wq);
3228 struct ieee80211_device* ieee = priv->ieee80211;
3229 RESET_TYPE ResetType = RESET_TYPE_NORESET;
3230 bool bBusyTraffic = false;
3231 bool bEnterPS = false;
3232
3233 if ((!priv->up) || priv->bHwRadioOff)
3234 return;
3235
3236 if(!priv->up)
3237 return;
3238 hal_dm_watchdog(priv);
3239#ifdef ENABLE_IPS
3240 if(ieee->actscanning == false){
3241 if((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == IEEE80211_NOLINK) &&
3242 (priv->eRFPowerState == eRfOn) && !ieee->is_set_key &&
3243 (!ieee->proto_stoppping) && !ieee->wx_set_enc){
3244 if (priv->PowerSaveControl.ReturnPoint == IPS_CALLBACK_NONE){
3245 IPSEnter(priv);
3246 }
3247 }
3248 }
3249#endif
3250 {//to get busy traffic condition
3251 if(ieee->state == IEEE80211_LINKED)
3252 {
3253 if( ieee->LinkDetectInfo.NumRxOkInPeriod> 100 ||
3254 ieee->LinkDetectInfo.NumTxOkInPeriod> 100 ) {
3255 bBusyTraffic = true;
3256 }
3257
3258#ifdef ENABLE_LPS
3259 //added by amy for Leisure PS
3260 if( ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod + ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
3261 (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
3262 {
3263 bEnterPS= false;
3264 }
3265 else
3266 {
3267 bEnterPS= true;
3268 }
3269
3270 // LeisurePS only work in infra mode.
3271 if(bEnterPS)
3272 {
3273 LeisurePSEnter(priv->ieee80211);
3274 }
3275 else
3276 {
3277 LeisurePSLeave(priv->ieee80211);
3278 }
3279#endif
3280
3281 }
3282 else
3283 {
3284#ifdef ENABLE_LPS
3285 LeisurePSLeave(priv->ieee80211);
3286#endif
3287 }
3288
3289 ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
3290 ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
3291 ieee->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
3292 ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
3293 }
3294
3295
3296 //added by amy for AP roaming
3297 if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA)
3298 {
3299 u32 TotalRxBcnNum = 0;
3300 u32 TotalRxDataNum = 0;
3301
3302 rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
3303 if((TotalRxBcnNum+TotalRxDataNum) == 0)
3304 {
3305 if (priv->eRFPowerState == eRfOff)
3306 RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
3307 printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__);
3308 // Dot11d_Reset(dev);
3309 ieee->state = IEEE80211_ASSOCIATING;
3310 notify_wx_assoc_event(priv->ieee80211);
3311 RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
3312 ieee->is_roaming = true;
3313 ieee->is_set_key = false;
3314 ieee->link_change(ieee);
3315 queue_work(ieee->wq, &ieee->associate_procedure_wq);
3316 }
3317 }
3318 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
3319 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
3320
3321 //check if reset the driver
3322 if (priv->watchdog_check_reset_cnt++ >= 3 && !ieee->is_roaming &&
3323 priv->watchdog_last_time != 1)
3324 {
3325 ResetType = rtl819x_check_reset(priv);
3326 priv->watchdog_check_reset_cnt = 3;
3327 }
3328 if(!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_NORMAL)
3329 {
3330 priv->ResetProgress = RESET_TYPE_NORMAL;
3331 RT_TRACE(COMP_RESET,"%s(): NOMAL RESET\n",__FUNCTION__);
3332 return;
3333 }
3334 /* disable silent reset temply 2008.9.11*/
3335
3336 if( ((priv->force_reset) || (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT))) // This is control by OID set in Pomelo
3337 {
3338 priv->watchdog_last_time = 1;
3339 }
3340 else
3341 priv->watchdog_last_time = 0;
3342
3343 priv->force_reset = false;
3344 priv->bForcedSilentReset = false;
3345 priv->bResetInProgress = false;
3346 RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
3347
3348}
3349
3350void watch_dog_timer_callback(unsigned long data)
3351{
3352 struct r8192_priv *priv = (struct r8192_priv *) data;
3353 queue_delayed_work(priv->priv_wq,&priv->watch_dog_wq,0);
3354 mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
3355
3356}
3357
3358static int _rtl8192_up(struct r8192_priv *priv)
3359{
3360 RT_STATUS init_status = RT_STATUS_SUCCESS;
3361 struct net_device *dev = priv->ieee80211->dev;
3362
3363 priv->up=1;
3364 priv->ieee80211->ieee_up=1;
3365 priv->bdisable_nic = false; //YJ,add,091111
3366 RT_TRACE(COMP_INIT, "Bringing up iface\n");
3367
3368 init_status = rtl8192_adapter_start(priv);
3369 if(init_status != RT_STATUS_SUCCESS)
3370 {
3371 RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
3372 return -1;
3373 }
3374 RT_TRACE(COMP_INIT, "start adapter finished\n");
3375
3376 if (priv->eRFPowerState != eRfOn)
3377 MgntActSet_RF_State(priv, eRfOn, priv->RfOffReason);
3378
3379 if(priv->ieee80211->state != IEEE80211_LINKED)
3380 ieee80211_softmac_start_protocol(priv->ieee80211);
3381 ieee80211_reset_queue(priv->ieee80211);
3382 watch_dog_timer_callback((unsigned long) priv);
3383 if(!netif_queue_stopped(dev))
3384 netif_start_queue(dev);
3385 else
3386 netif_wake_queue(dev);
3387
3388 return 0;
3389}
3390
3391
3392static int rtl8192_open(struct net_device *dev)
3393{
3394 struct r8192_priv *priv = ieee80211_priv(dev);
3395 int ret;
3396
3397 down(&priv->wx_sem);
3398 ret = rtl8192_up(dev);
3399 up(&priv->wx_sem);
3400 return ret;
3401
3402}
3403
3404
3405int rtl8192_up(struct net_device *dev)
3406{
3407 struct r8192_priv *priv = ieee80211_priv(dev);
3408
3409 if (priv->up == 1) return -1;
3410
3411 return _rtl8192_up(priv);
3412}
3413
3414
3415static int rtl8192_close(struct net_device *dev)
3416{
3417 struct r8192_priv *priv = ieee80211_priv(dev);
3418 int ret;
3419
3420 down(&priv->wx_sem);
3421
3422 ret = rtl8192_down(dev);
3423
3424 up(&priv->wx_sem);
3425
3426 return ret;
3427
3428}
3429
3430int rtl8192_down(struct net_device *dev)
3431{
3432 struct r8192_priv *priv = ieee80211_priv(dev);
3433
3434 if (priv->up == 0) return -1;
3435
3436#ifdef ENABLE_LPS
3437 //LZM for PS-Poll AID issue. 090429
3438 if(priv->ieee80211->state == IEEE80211_LINKED)
3439 LeisurePSLeave(priv->ieee80211);
3440#endif
3441
3442 priv->up=0;
3443 priv->ieee80211->ieee_up = 0;
3444 RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
3445/* FIXME */
3446 if (!netif_queue_stopped(dev))
3447 netif_stop_queue(dev);
3448
3449 rtl8192_irq_disable(priv);
3450 rtl8192_cancel_deferred_work(priv);
3451 deinit_hal_dm(priv);
3452 del_timer_sync(&priv->watch_dog_timer);
3453
3454 ieee80211_softmac_stop_protocol(priv->ieee80211,true);
3455
3456 rtl8192_halt_adapter(priv, false);
3457 memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list));
3458
3459 RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
3460
3461 return 0;
3462}
3463
3464
3465void rtl8192_commit(struct r8192_priv *priv)
3466{
3467 if (priv->up == 0) return ;
3468
3469
3470 ieee80211_softmac_stop_protocol(priv->ieee80211,true);
3471
3472 rtl8192_irq_disable(priv);
3473 rtl8192_halt_adapter(priv, true);
3474 _rtl8192_up(priv);
3475}
3476
3477static void rtl8192_restart(struct work_struct *work)
3478{
3479 struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
3480
3481 down(&priv->wx_sem);
3482
3483 rtl8192_commit(priv);
3484
3485 up(&priv->wx_sem);
3486}
3487
3488static void r8192_set_multicast(struct net_device *dev)
3489{
3490 struct r8192_priv *priv = ieee80211_priv(dev);
3491
3492 priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
3493}
3494
3495
3496static int r8192_set_mac_adr(struct net_device *dev, void *mac)
3497{
3498 struct r8192_priv *priv = ieee80211_priv(dev);
3499 struct sockaddr *addr = mac;
3500
3501 down(&priv->wx_sem);
3502
3503 memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
3504
3505 schedule_work(&priv->reset_wq);
3506 up(&priv->wx_sem);
3507
3508 return 0;
3509}
3510
3511static void r8192e_set_hw_key(struct r8192_priv *priv, struct ieee_param *ipw)
3512{
3513 struct ieee80211_device *ieee = priv->ieee80211;
3514 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
3515 u32 key[4];
3516
3517 if (ipw->u.crypt.set_tx) {
3518 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
3519 ieee->pairwise_key_type = KEY_TYPE_CCMP;
3520 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
3521 ieee->pairwise_key_type = KEY_TYPE_TKIP;
3522 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
3523 if (ipw->u.crypt.key_len == 13)
3524 ieee->pairwise_key_type = KEY_TYPE_WEP104;
3525 else if (ipw->u.crypt.key_len == 5)
3526 ieee->pairwise_key_type = KEY_TYPE_WEP40;
3527 } else
3528 ieee->pairwise_key_type = KEY_TYPE_NA;
3529
3530 if (ieee->pairwise_key_type) {
3531 memcpy(key, ipw->u.crypt.key, 16);
3532 EnableHWSecurityConfig8192(priv);
3533 /*
3534 * We fill both index entry and 4th entry for pairwise
3535 * key as in IPW interface, adhoc will only get here,
3536 * so we need index entry for its default key serching!
3537 */
3538 setKey(priv, 4, ipw->u.crypt.idx,
3539 ieee->pairwise_key_type,
3540 (u8*)ieee->ap_mac_addr, 0, key);
3541
3542 /* LEAP WEP will never set this. */
3543 if (ieee->auth_mode != 2)
3544 setKey(priv, ipw->u.crypt.idx, ipw->u.crypt.idx,
3545 ieee->pairwise_key_type,
3546 (u8*)ieee->ap_mac_addr, 0, key);
3547 }
3548 if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) &&
3549 ieee->pHTInfo->bCurrentHTSupport) {
3550 write_nic_byte(priv, 0x173, 1); /* fix aes bug */
3551 }
3552 } else {
3553 memcpy(key, ipw->u.crypt.key, 16);
3554 if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
3555 ieee->group_key_type= KEY_TYPE_CCMP;
3556 else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
3557 ieee->group_key_type = KEY_TYPE_TKIP;
3558 else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
3559 if (ipw->u.crypt.key_len == 13)
3560 ieee->group_key_type = KEY_TYPE_WEP104;
3561 else if (ipw->u.crypt.key_len == 5)
3562 ieee->group_key_type = KEY_TYPE_WEP40;
3563 } else
3564 ieee->group_key_type = KEY_TYPE_NA;
3565
3566 if (ieee->group_key_type) {
3567 setKey(priv, ipw->u.crypt.idx, ipw->u.crypt.idx,
3568 ieee->group_key_type, broadcast_addr, 0, key);
3569 }
3570 }
3571}
3572
3573/* based on ipw2200 driver */
3574static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
3575{
3576 struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
3577 struct iwreq *wrq = (struct iwreq *)rq;
3578 int ret=-1;
3579 struct iw_point *p = &wrq->u.data;
3580 struct ieee_param *ipw = NULL;//(struct ieee_param *)wrq->u.data.pointer;
3581
3582 down(&priv->wx_sem);
3583
3584
3585 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3586 ret = -EINVAL;
3587 goto out;
3588 }
3589
3590 ipw = kmalloc(p->length, GFP_KERNEL);
3591 if (ipw == NULL){
3592 ret = -ENOMEM;
3593 goto out;
3594 }
3595 if (copy_from_user(ipw, p->pointer, p->length)) {
3596 kfree(ipw);
3597 ret = -EFAULT;
3598 goto out;
3599 }
3600
3601 switch (cmd) {
3602 case RTL_IOCTL_WPA_SUPPLICANT:
3603 /* parse here for HW security */
3604 if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION)
3605 r8192e_set_hw_key(priv, ipw);
3606 ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
3607 break;
3608
3609 default:
3610 ret = -EOPNOTSUPP;
3611 break;
3612 }
3613
3614 kfree(ipw);
3615out:
3616 up(&priv->wx_sem);
3617
3618 return ret;
3619}
3620
3621static u8 HwRateToMRate90(bool bIsHT, u8 rate)
3622{
3623 u8 ret_rate = 0x02;
3624
3625 if(!bIsHT) {
3626 switch(rate) {
3627 case DESC90_RATE1M: ret_rate = MGN_1M; break;
3628 case DESC90_RATE2M: ret_rate = MGN_2M; break;
3629 case DESC90_RATE5_5M: ret_rate = MGN_5_5M; break;
3630 case DESC90_RATE11M: ret_rate = MGN_11M; break;
3631 case DESC90_RATE6M: ret_rate = MGN_6M; break;
3632 case DESC90_RATE9M: ret_rate = MGN_9M; break;
3633 case DESC90_RATE12M: ret_rate = MGN_12M; break;
3634 case DESC90_RATE18M: ret_rate = MGN_18M; break;
3635 case DESC90_RATE24M: ret_rate = MGN_24M; break;
3636 case DESC90_RATE36M: ret_rate = MGN_36M; break;
3637 case DESC90_RATE48M: ret_rate = MGN_48M; break;
3638 case DESC90_RATE54M: ret_rate = MGN_54M; break;
3639
3640 default:
3641 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n", rate, bIsHT);
3642 break;
3643 }
3644
3645 } else {
3646 switch(rate) {
3647 case DESC90_RATEMCS0: ret_rate = MGN_MCS0; break;
3648 case DESC90_RATEMCS1: ret_rate = MGN_MCS1; break;
3649 case DESC90_RATEMCS2: ret_rate = MGN_MCS2; break;
3650 case DESC90_RATEMCS3: ret_rate = MGN_MCS3; break;
3651 case DESC90_RATEMCS4: ret_rate = MGN_MCS4; break;
3652 case DESC90_RATEMCS5: ret_rate = MGN_MCS5; break;
3653 case DESC90_RATEMCS6: ret_rate = MGN_MCS6; break;
3654 case DESC90_RATEMCS7: ret_rate = MGN_MCS7; break;
3655 case DESC90_RATEMCS8: ret_rate = MGN_MCS8; break;
3656 case DESC90_RATEMCS9: ret_rate = MGN_MCS9; break;
3657 case DESC90_RATEMCS10: ret_rate = MGN_MCS10; break;
3658 case DESC90_RATEMCS11: ret_rate = MGN_MCS11; break;
3659 case DESC90_RATEMCS12: ret_rate = MGN_MCS12; break;
3660 case DESC90_RATEMCS13: ret_rate = MGN_MCS13; break;
3661 case DESC90_RATEMCS14: ret_rate = MGN_MCS14; break;
3662 case DESC90_RATEMCS15: ret_rate = MGN_MCS15; break;
3663 case DESC90_RATEMCS32: ret_rate = (0x80|0x20); break;
3664
3665 default:
3666 RT_TRACE(COMP_RECV, "HwRateToMRate90(): Non supported Rate [%x], bIsHT = %d!!!\n",rate, bIsHT);
3667 break;
3668 }
3669 }
3670
3671 return ret_rate;
3672}
3673
3674/* Record the TSF time stamp when receiving a packet */
3675static void UpdateRxPktTimeStamp8190(struct r8192_priv *priv, struct ieee80211_rx_stats *stats)
3676{
3677
3678 if(stats->bIsAMPDU && !stats->bFirstMPDU) {
3679 stats->mac_time[0] = priv->LastRxDescTSFLow;
3680 stats->mac_time[1] = priv->LastRxDescTSFHigh;
3681 } else {
3682 priv->LastRxDescTSFLow = stats->mac_time[0];
3683 priv->LastRxDescTSFHigh = stats->mac_time[1];
3684 }
3685}
3686
3687static long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
3688{
3689 long signal_power; // in dBm.
3690
3691 // Translate to dBm (x=0.5y-95).
3692 signal_power = (long)((signal_strength_index + 1) >> 1);
3693 signal_power -= 95;
3694
3695 return signal_power;
3696}
3697
3698/* 2008/01/22 MH We can not delcare RSSI/EVM total value of sliding window to
3699 be a local static. Otherwise, it may increase when we return from S3/S4. The
3700 value will be kept in memory or disk. We must delcare the value in adapter
3701 and it will be reinitialized when return from S3/S4. */
3702static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct ieee80211_rx_stats * pprevious_stats, struct ieee80211_rx_stats * pcurrent_stats)
3703{
3704 bool bcheck = false;
3705 u8 rfpath;
3706 u32 nspatial_stream, tmp_val;
3707 static u32 slide_rssi_index=0, slide_rssi_statistics=0;
3708 static u32 slide_evm_index=0, slide_evm_statistics=0;
3709 static u32 last_rssi=0, last_evm=0;
3710 //cosa add for beacon rssi smoothing
3711 static u32 slide_beacon_adc_pwdb_index=0, slide_beacon_adc_pwdb_statistics=0;
3712 static u32 last_beacon_adc_pwdb=0;
3713
3714 struct ieee80211_hdr_3addr *hdr;
3715 u16 sc ;
3716 unsigned int frag,seq;
3717 hdr = (struct ieee80211_hdr_3addr *)buffer;
3718 sc = le16_to_cpu(hdr->seq_ctl);
3719 frag = WLAN_GET_SEQ_FRAG(sc);
3720 seq = WLAN_GET_SEQ_SEQ(sc);
3721
3722 //
3723 // Check whether we should take the previous packet into accounting
3724 //
3725 if(!pprevious_stats->bIsAMPDU)
3726 {
3727 // if previous packet is not aggregated packet
3728 bcheck = true;
3729 }
3730
3731 if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
3732 {
3733 slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
3734 last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
3735 priv->stats.slide_rssi_total -= last_rssi;
3736 }
3737 priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
3738
3739 priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
3740 if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
3741 slide_rssi_index = 0;
3742
3743 // <1> Showed on UI for user, in dbm
3744 tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
3745 priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
3746 pcurrent_stats->rssi = priv->stats.signal_strength;
3747 //
3748 // If the previous packet does not match the criteria, neglect it
3749 //
3750 if(!pprevious_stats->bPacketMatchBSSID)
3751 {
3752 if(!pprevious_stats->bToSelfBA)
3753 return;
3754 }
3755
3756 if(!bcheck)
3757 return;
3758
3759 // <2> Showed on UI for engineering
3760 // hardware does not provide rssi information for each rf path in CCK
3761 if(!pprevious_stats->bIsCCK && pprevious_stats->bPacketToSelf)
3762 {
3763 for (rfpath = RF90_PATH_A; rfpath < RF90_PATH_C; rfpath++)
3764 {
3765 if (!rtl8192_phy_CheckIsLegalRFPath(priv, rfpath))
3766 continue;
3767 RT_TRACE(COMP_DBG, "pPreviousstats->RxMIMOSignalStrength[rfpath] = %d\n", pprevious_stats->RxMIMOSignalStrength[rfpath]);
3768 //Fixed by Jacken 2008-03-20
3769 if(priv->stats.rx_rssi_percentage[rfpath] == 0)
3770 {
3771 priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
3772 }
3773 if(pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath])
3774 {
3775 priv->stats.rx_rssi_percentage[rfpath] =
3776 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
3777 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
3778 priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1;
3779 }
3780 else
3781 {
3782 priv->stats.rx_rssi_percentage[rfpath] =
3783 ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
3784 (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
3785 }
3786 RT_TRACE(COMP_DBG, "priv->RxStats.RxRSSIPercentage[rfPath] = %d \n" , priv->stats.rx_rssi_percentage[rfpath]);
3787 }
3788 }
3789
3790
3791 //
3792 // Check PWDB.
3793 //
3794 //cosa add for beacon rssi smoothing by average.
3795 if(pprevious_stats->bPacketBeacon)
3796 {
3797 /* record the beacon pwdb to the sliding window. */
3798 if(slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX)
3799 {
3800 slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
3801 last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
3802 priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
3803 // slide_beacon_adc_pwdb_index, last_beacon_adc_pwdb, Adapter->RxStats.Slide_Beacon_Total);
3804 }
3805 priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
3806 priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
3807 slide_beacon_adc_pwdb_index++;
3808 if(slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
3809 slide_beacon_adc_pwdb_index = 0;
3810 pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics;
3811 if(pprevious_stats->RxPWDBAll >= 3)
3812 pprevious_stats->RxPWDBAll -= 3;
3813 }
3814
3815 RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n",
3816 pprevious_stats->bIsCCK? "CCK": "OFDM",
3817 pprevious_stats->RxPWDBAll);
3818
3819 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
3820 {
3821 if(priv->undecorated_smoothed_pwdb < 0) // initialize
3822 {
3823 priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
3824 }
3825
3826 if(pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb)
3827 {
3828 priv->undecorated_smoothed_pwdb =
3829 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
3830 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
3831 priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1;
3832 }
3833 else
3834 {
3835 priv->undecorated_smoothed_pwdb =
3836 ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
3837 (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
3838 }
3839 }
3840
3841 //
3842 // Check EVM
3843 //
3844 /* record the general EVM to the sliding window. */
3845 if(pprevious_stats->SignalQuality == 0)
3846 {
3847 }
3848 else
3849 {
3850 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA){
3851 if(slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX){
3852 slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX;
3853 last_evm = priv->stats.slide_evm[slide_evm_index];
3854 priv->stats.slide_evm_total -= last_evm;
3855 }
3856
3857 priv->stats.slide_evm_total += pprevious_stats->SignalQuality;
3858
3859 priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality;
3860 if(slide_evm_index >= PHY_RSSI_SLID_WIN_MAX)
3861 slide_evm_index = 0;
3862
3863 // <1> Showed on UI for user, in percentage.
3864 tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
3865 //cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
3866 }
3867
3868 // <2> Showed on UI for engineering
3869 if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA)
3870 {
3871 for(nspatial_stream = 0; nspatial_stream<2 ; nspatial_stream++) // 2 spatial stream
3872 {
3873 if(pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1)
3874 {
3875 if(priv->stats.rx_evm_percentage[nspatial_stream] == 0) // initialize
3876 {
3877 priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream];
3878 }
3879 priv->stats.rx_evm_percentage[nspatial_stream] =
3880 ( (priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) +
3881 (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor);
3882 }
3883 }
3884 }
3885 }
3886
3887}
3888
3889static u8 rtl819x_query_rxpwrpercentage(
3890 char antpower
3891 )
3892{
3893 if ((antpower <= -100) || (antpower >= 20))
3894 {
3895 return 0;
3896 }
3897 else if (antpower >= 0)
3898 {
3899 return 100;
3900 }
3901 else
3902 {
3903 return (100+antpower);
3904 }
3905
3906}
3907
3908static u8
3909rtl819x_evm_dbtopercentage(
3910 char value
3911 )
3912{
3913 char ret_val;
3914
3915 ret_val = value;
3916
3917 if(ret_val >= 0)
3918 ret_val = 0;
3919 if(ret_val <= -33)
3920 ret_val = -33;
3921 ret_val = 0 - ret_val;
3922 ret_val*=3;
3923 if(ret_val == 99)
3924 ret_val = 100;
3925 return ret_val;
3926}
3927
3928/* We want good-looking for signal strength/quality */
3929static long rtl819x_signal_scale_mapping(long currsig)
3930{
3931 long retsig;
3932
3933 // Step 1. Scale mapping.
3934 if(currsig >= 61 && currsig <= 100)
3935 {
3936 retsig = 90 + ((currsig - 60) / 4);
3937 }
3938 else if(currsig >= 41 && currsig <= 60)
3939 {
3940 retsig = 78 + ((currsig - 40) / 2);
3941 }
3942 else if(currsig >= 31 && currsig <= 40)
3943 {
3944 retsig = 66 + (currsig - 30);
3945 }
3946 else if(currsig >= 21 && currsig <= 30)
3947 {
3948 retsig = 54 + (currsig - 20);
3949 }
3950 else if(currsig >= 5 && currsig <= 20)
3951 {
3952 retsig = 42 + (((currsig - 5) * 2) / 3);
3953 }
3954 else if(currsig == 4)
3955 {
3956 retsig = 36;
3957 }
3958 else if(currsig == 3)
3959 {
3960 retsig = 27;
3961 }
3962 else if(currsig == 2)
3963 {
3964 retsig = 18;
3965 }
3966 else if(currsig == 1)
3967 {
3968 retsig = 9;
3969 }
3970 else
3971 {
3972 retsig = currsig;
3973 }
3974
3975 return retsig;
3976}
3977
3978static void rtl8192_query_rxphystatus(
3979 struct r8192_priv * priv,
3980 struct ieee80211_rx_stats * pstats,
3981 prx_desc_819x_pci pdesc,
3982 prx_fwinfo_819x_pci pdrvinfo,
3983 struct ieee80211_rx_stats * precord_stats,
3984 bool bpacket_match_bssid,
3985 bool bpacket_toself,
3986 bool bPacketBeacon,
3987 bool bToSelfBA
3988 )
3989{
3990 //PRT_RFD_STATUS pRtRfdStatus = &(pRfd->Status);
3991 phy_sts_ofdm_819xpci_t* pofdm_buf;
3992 phy_sts_cck_819xpci_t * pcck_buf;
3993 phy_ofdm_rx_status_rxsc_sgien_exintfflag* prxsc;
3994 u8 *prxpkt;
3995 u8 i,max_spatial_stream, tmp_rxsnr, tmp_rxevm, rxsc_sgien_exflg;
3996 char rx_pwr[4], rx_pwr_all=0;
3997 //long rx_avg_pwr = 0;
3998 char rx_snrX, rx_evmX;
3999 u8 evm, pwdb_all;
4000 u32 RSSI, total_rssi=0;//, total_evm=0;
4001// long signal_strength_index = 0;
4002 u8 is_cck_rate=0;
4003 u8 rf_rx_num = 0;
4004
4005 is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
4006
4007 // Record it for next packet processing
4008 memset(precord_stats, 0, sizeof(struct ieee80211_rx_stats));
4009 pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid;
4010 pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself;
4011 pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate;//RX_HAL_IS_CCK_RATE(pDrvInfo);
4012 pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
4013 pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
4014 /*2007.08.30 requested by SD3 Jerry */
4015 if (priv->phy_check_reg824 == 0)
4016 {
4017 priv->phy_reg824_bit9 = rtl8192_QueryBBReg(priv, rFPGA0_XA_HSSIParameter2, 0x200);
4018 priv->phy_check_reg824 = 1;
4019 }
4020
4021
4022 prxpkt = (u8*)pdrvinfo;
4023
4024 /* Move pointer to the 16th bytes. Phy status start address. */
4025 prxpkt += sizeof(rx_fwinfo_819x_pci);
4026
4027 /* Initial the cck and ofdm buffer pointer */
4028 pcck_buf = (phy_sts_cck_819xpci_t *)prxpkt;
4029 pofdm_buf = (phy_sts_ofdm_819xpci_t *)prxpkt;
4030
4031 pstats->RxMIMOSignalQuality[0] = -1;
4032 pstats->RxMIMOSignalQuality[1] = -1;
4033 precord_stats->RxMIMOSignalQuality[0] = -1;
4034 precord_stats->RxMIMOSignalQuality[1] = -1;
4035
4036 if(is_cck_rate)
4037 {
4038 //
4039 // (1)Hardware does not provide RSSI for CCK
4040 //
4041
4042 //
4043 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4044 //
4045 u8 report;//, cck_agc_rpt;
4046
4047 if (!priv->phy_reg824_bit9)
4048 {
4049 report = pcck_buf->cck_agc_rpt & 0xc0;
4050 report = report>>6;
4051 switch(report)
4052 {
4053 //Fixed by Jacken from Bryant 2008-03-20
4054 //Original value is -38 , -26 , -14 , -2
4055 //Fixed value is -35 , -23 , -11 , 6
4056 case 0x3:
4057 rx_pwr_all = -35 - (pcck_buf->cck_agc_rpt & 0x3e);
4058 break;
4059 case 0x2:
4060 rx_pwr_all = -23 - (pcck_buf->cck_agc_rpt & 0x3e);
4061 break;
4062 case 0x1:
4063 rx_pwr_all = -11 - (pcck_buf->cck_agc_rpt & 0x3e);
4064 break;
4065 case 0x0:
4066 rx_pwr_all = 8 - (pcck_buf->cck_agc_rpt & 0x3e);
4067 break;
4068 }
4069 }
4070 else
4071 {
4072 report = pcck_buf->cck_agc_rpt & 0x60;
4073 report = report>>5;
4074 switch(report)
4075 {
4076 case 0x3:
4077 rx_pwr_all = -35 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4078 break;
4079 case 0x2:
4080 rx_pwr_all = -23 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1);
4081 break;
4082 case 0x1:
4083 rx_pwr_all = -11 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4084 break;
4085 case 0x0:
4086 rx_pwr_all = -8 - ((pcck_buf->cck_agc_rpt & 0x1f)<<1) ;
4087 break;
4088 }
4089 }
4090
4091 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4092 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4093 pstats->RecvSignalPower = rx_pwr_all;
4094
4095 //
4096 // (3) Get Signal Quality (EVM)
4097 //
4098 if(bpacket_match_bssid)
4099 {
4100 u8 sq;
4101
4102 if(pstats->RxPWDBAll > 40)
4103 {
4104 sq = 100;
4105 }else
4106 {
4107 sq = pcck_buf->sq_rpt;
4108
4109 if(pcck_buf->sq_rpt > 64)
4110 sq = 0;
4111 else if (pcck_buf->sq_rpt < 20)
4112 sq = 100;
4113 else
4114 sq = ((64-sq) * 100) / 44;
4115 }
4116 pstats->SignalQuality = precord_stats->SignalQuality = sq;
4117 pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq;
4118 pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1;
4119 }
4120 }
4121 else
4122 {
4123 //
4124 // (1)Get RSSI for HT rate
4125 //
4126 for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
4127 {
4128 // 2008/01/30 MH we will judge RF RX path now.
4129 if (priv->brfpath_rxenable[i])
4130 rf_rx_num++;
4131 //else
4132 //continue;
4133
4134 //Fixed by Jacken from Bryant 2008-03-20
4135 //Original value is 106
4136 rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 110;
4137
4138 //Get Rx snr value in DB
4139 tmp_rxsnr = pofdm_buf->rxsnr_X[i];
4140 rx_snrX = (char)(tmp_rxsnr);
4141 rx_snrX /= 2;
4142
4143 /* Translate DBM to percentage. */
4144 RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
4145 if (priv->brfpath_rxenable[i])
4146 total_rssi += RSSI;
4147
4148 /* Record Signal Strength for next packet */
4149 if(bpacket_match_bssid)
4150 {
4151 pstats->RxMIMOSignalStrength[i] =(u8) RSSI;
4152 precord_stats->RxMIMOSignalStrength[i] =(u8) RSSI;
4153 }
4154 }
4155
4156
4157 //
4158 // (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
4159 //
4160 //Fixed by Jacken from Bryant 2008-03-20
4161 //Original value is 106
4162 rx_pwr_all = (((pofdm_buf->pwdb_all ) >> 1 )& 0x7f) -106;
4163 pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
4164
4165 pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
4166 pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
4167 pstats->RecvSignalPower = rx_pwr_all;
4168 //
4169 // (3)EVM of HT rate
4170 //
4171 if(pdrvinfo->RxHT && pdrvinfo->RxRate>=DESC90_RATEMCS8 &&
4172 pdrvinfo->RxRate<=DESC90_RATEMCS15)
4173 max_spatial_stream = 2; //both spatial stream make sense
4174 else
4175 max_spatial_stream = 1; //only spatial stream 1 makes sense
4176
4177 for(i=0; i<max_spatial_stream; i++)
4178 {
4179 tmp_rxevm = pofdm_buf->rxevm_X[i];
4180 rx_evmX = (char)(tmp_rxevm);
4181
4182 // Do not use shift operation like "rx_evmX >>= 1" because the compilor of free build environment
4183 // fill most significant bit to "zero" when doing shifting operation which may change a negative
4184 // value to positive one, then the dbm value (which is supposed to be negative) is not correct anymore.
4185 rx_evmX /= 2; //dbm
4186
4187 evm = rtl819x_evm_dbtopercentage(rx_evmX);
4188 if(bpacket_match_bssid)
4189 {
4190 if(i==0) // Fill value in RFD, Get the first spatial stream only
4191 pstats->SignalQuality = precord_stats->SignalQuality = (u8)(evm & 0xff);
4192 pstats->RxMIMOSignalQuality[i] = precord_stats->RxMIMOSignalQuality[i] = (u8)(evm & 0xff);
4193 }
4194 }
4195
4196
4197 /* record rx statistics for debug */
4198 rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
4199 prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
4200 }
4201
4202 //UI BSS List signal strength(in percentage), make it good looking, from 0~100.
4203 //It is assigned to the BSS List in GetValueFromBeaconOrProbeRsp().
4204 if(is_cck_rate)
4205 {
4206 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)pwdb_all));//PWDB_ALL;
4207
4208 }
4209 else
4210 {
4211 //pRfd->Status.SignalStrength = pRecordRfd->Status.SignalStrength = (u1Byte)(SignalScaleMapping(total_rssi/=RF90_PATH_MAX));//(u1Byte)(total_rssi/=RF90_PATH_MAX);
4212 // We can judge RX path number now.
4213 if (rf_rx_num != 0)
4214 pstats->SignalStrength = precord_stats->SignalStrength = (u8)(rtl819x_signal_scale_mapping((long)(total_rssi/=rf_rx_num)));
4215 }
4216}
4217
4218static void
4219rtl8192_record_rxdesc_forlateruse(
4220 struct ieee80211_rx_stats * psrc_stats,
4221 struct ieee80211_rx_stats * ptarget_stats
4222)
4223{
4224 ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
4225 ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
4226}
4227
4228
4229
4230static void TranslateRxSignalStuff819xpci(struct r8192_priv *priv,
4231 struct sk_buff *skb,
4232 struct ieee80211_rx_stats * pstats,
4233 prx_desc_819x_pci pdesc,
4234 prx_fwinfo_819x_pci pdrvinfo)
4235{
4236 // TODO: We must only check packet for current MAC address. Not finish
4237 bool bpacket_match_bssid, bpacket_toself;
4238 bool bPacketBeacon=false, bToSelfBA=false;
4239 struct ieee80211_hdr_3addr *hdr;
4240 u16 fc,type;
4241
4242 // Get Signal Quality for only RX data queue (but not command queue)
4243
4244 u8* tmp_buf;
4245 u8 *praddr;
4246
4247 /* Get MAC frame start address. */
4248 tmp_buf = skb->data;
4249
4250 hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
4251 fc = le16_to_cpu(hdr->frame_ctl);
4252 type = WLAN_FC_GET_TYPE(fc);
4253 praddr = hdr->addr1;
4254
4255 /* Check if the received packet is acceptabe. */
4256 bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
4257 (!compare_ether_addr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
4258 && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
4259 bpacket_toself = bpacket_match_bssid & (!compare_ether_addr(praddr, priv->ieee80211->dev->dev_addr));
4260
4261 if(WLAN_FC_GET_FRAMETYPE(fc)== IEEE80211_STYPE_BEACON)
4262 {
4263 bPacketBeacon = true;
4264 }
4265 if(WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK)
4266 {
4267 if (!compare_ether_addr(praddr, priv->ieee80211->dev->dev_addr))
4268 bToSelfBA = true;
4269 }
4270
4271 //
4272 // Process PHY information for previous packet (RSSI/PWDB/EVM)
4273 //
4274 // Because phy information is contained in the last packet of AMPDU only, so driver
4275 // should process phy information of previous packet
4276 rtl8192_process_phyinfo(priv, tmp_buf, &priv->previous_stats, pstats);
4277 rtl8192_query_rxphystatus(priv, pstats, pdesc, pdrvinfo, &priv->previous_stats, bpacket_match_bssid,
4278 bpacket_toself ,bPacketBeacon, bToSelfBA);
4279 rtl8192_record_rxdesc_forlateruse(pstats, &priv->previous_stats);
4280
4281}
4282
4283
4284static void rtl8192_tx_resume(struct r8192_priv *priv)
4285{
4286 struct ieee80211_device *ieee = priv->ieee80211;
4287 struct sk_buff *skb;
4288 int i;
4289
4290 for (i = BK_QUEUE; i < TXCMD_QUEUE; i++) {
4291 while ((!skb_queue_empty(&ieee->skb_waitQ[i])) &&
4292 (priv->ieee80211->check_nic_enough_desc(ieee, i) > 0)) {
4293 /* 1. dequeue the packet from the wait queue */
4294 skb = skb_dequeue(&ieee->skb_waitQ[i]);
4295 /* 2. tx the packet directly */
4296 ieee->softmac_data_hard_start_xmit(skb, ieee, 0);
4297 }
4298 }
4299}
4300
4301static void rtl8192_irq_tx_tasklet(unsigned long arg)
4302{
4303 struct r8192_priv *priv = (struct r8192_priv*) arg;
4304 struct rtl8192_tx_ring *mgnt_ring = &priv->tx_ring[MGNT_QUEUE];
4305 unsigned long flags;
4306
4307 /* check if we need to report that the management queue is drained */
4308 spin_lock_irqsave(&priv->irq_th_lock, flags);
4309
4310 if (!skb_queue_len(&mgnt_ring->queue) &&
4311 priv->ieee80211->ack_tx_to_ieee &&
4312 rtl8192_is_tx_queue_empty(priv->ieee80211)) {
4313 priv->ieee80211->ack_tx_to_ieee = 0;
4314 ieee80211_ps_tx_ack(priv->ieee80211, 1);
4315 }
4316
4317 spin_unlock_irqrestore(&priv->irq_th_lock, flags);
4318
4319 rtl8192_tx_resume(priv);
4320}
4321
4322/* Record the received data rate */
4323static void UpdateReceivedRateHistogramStatistics8190(
4324 struct r8192_priv *priv,
4325 struct ieee80211_rx_stats* pstats
4326 )
4327{
4328 u32 rcvType=1; //0: Total, 1:OK, 2:CRC, 3:ICV
4329 u32 rateIndex;
4330 u32 preamble_guardinterval; //1: short preamble/GI, 0: long preamble/GI
4331
4332 if(pstats->bCRC)
4333 rcvType = 2;
4334 else if(pstats->bICV)
4335 rcvType = 3;
4336
4337 if(pstats->bShortPreamble)
4338 preamble_guardinterval = 1;// short
4339 else
4340 preamble_guardinterval = 0;// long
4341
4342 switch(pstats->rate)
4343 {
4344 //
4345 // CCK rate
4346 //
4347 case MGN_1M: rateIndex = 0; break;
4348 case MGN_2M: rateIndex = 1; break;
4349 case MGN_5_5M: rateIndex = 2; break;
4350 case MGN_11M: rateIndex = 3; break;
4351 //
4352 // Legacy OFDM rate
4353 //
4354 case MGN_6M: rateIndex = 4; break;
4355 case MGN_9M: rateIndex = 5; break;
4356 case MGN_12M: rateIndex = 6; break;
4357 case MGN_18M: rateIndex = 7; break;
4358 case MGN_24M: rateIndex = 8; break;
4359 case MGN_36M: rateIndex = 9; break;
4360 case MGN_48M: rateIndex = 10; break;
4361 case MGN_54M: rateIndex = 11; break;
4362 //
4363 // 11n High throughput rate
4364 //
4365 case MGN_MCS0: rateIndex = 12; break;
4366 case MGN_MCS1: rateIndex = 13; break;
4367 case MGN_MCS2: rateIndex = 14; break;
4368 case MGN_MCS3: rateIndex = 15; break;
4369 case MGN_MCS4: rateIndex = 16; break;
4370 case MGN_MCS5: rateIndex = 17; break;
4371 case MGN_MCS6: rateIndex = 18; break;
4372 case MGN_MCS7: rateIndex = 19; break;
4373 case MGN_MCS8: rateIndex = 20; break;
4374 case MGN_MCS9: rateIndex = 21; break;
4375 case MGN_MCS10: rateIndex = 22; break;
4376 case MGN_MCS11: rateIndex = 23; break;
4377 case MGN_MCS12: rateIndex = 24; break;
4378 case MGN_MCS13: rateIndex = 25; break;
4379 case MGN_MCS14: rateIndex = 26; break;
4380 case MGN_MCS15: rateIndex = 27; break;
4381 default: rateIndex = 28; break;
4382 }
4383 priv->stats.received_rate_histogram[0][rateIndex]++; //total
4384 priv->stats.received_rate_histogram[rcvType][rateIndex]++;
4385}
4386
4387static void rtl8192_rx(struct r8192_priv *priv)
4388{
4389 struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
4390 bool unicast_packet = false;
4391 struct ieee80211_rx_stats stats = {
4392 .signal = 0,
4393 .noise = -98,
4394 .rate = 0,
4395 .freq = IEEE80211_24GHZ_BAND,
4396 };
4397 unsigned int count = priv->rxringcount;
4398 prx_fwinfo_819x_pci pDrvInfo = NULL;
4399 struct sk_buff *new_skb;
4400
4401 while (count--) {
4402 rx_desc_819x_pci *pdesc = &priv->rx_ring[priv->rx_idx];//rx descriptor
4403 struct sk_buff *skb = priv->rx_buf[priv->rx_idx];//rx pkt
4404
4405 if (pdesc->OWN)
4406 /* wait data to be filled by hardware */
4407 return;
4408
4409 stats.bICV = pdesc->ICV;
4410 stats.bCRC = pdesc->CRC32;
4411 stats.bHwError = pdesc->CRC32 | pdesc->ICV;
4412
4413 stats.Length = pdesc->Length;
4414 if(stats.Length < 24)
4415 stats.bHwError |= 1;
4416
4417 if(stats.bHwError) {
4418 stats.bShift = false;
4419 goto done;
4420 }
4421 pDrvInfo = NULL;
4422 new_skb = dev_alloc_skb(priv->rxbuffersize);
4423
4424 if (unlikely(!new_skb))
4425 goto done;
4426
4427 stats.RxDrvInfoSize = pdesc->RxDrvInfoSize;
4428 stats.RxBufShift = ((pdesc->Shift)&0x03);
4429 stats.Decrypted = !pdesc->SWDec;
4430
4431 pci_dma_sync_single_for_cpu(priv->pdev,
4432 *((dma_addr_t *)skb->cb),
4433 priv->rxbuffersize,
4434 PCI_DMA_FROMDEVICE);
4435 skb_put(skb, pdesc->Length);
4436 pDrvInfo = (rx_fwinfo_819x_pci *)(skb->data + stats.RxBufShift);
4437 skb_reserve(skb, stats.RxDrvInfoSize + stats.RxBufShift);
4438
4439 stats.rate = HwRateToMRate90((bool)pDrvInfo->RxHT, (u8)pDrvInfo->RxRate);
4440 stats.bShortPreamble = pDrvInfo->SPLCP;
4441
4442 /* it is debug only. It should be disabled in released driver.
4443 * 2007.1.11 by Emily
4444 * */
4445 UpdateReceivedRateHistogramStatistics8190(priv, &stats);
4446
4447 stats.bIsAMPDU = (pDrvInfo->PartAggr==1);
4448 stats.bFirstMPDU = (pDrvInfo->PartAggr==1) && (pDrvInfo->FirstAGGR==1);
4449
4450 stats.TimeStampLow = pDrvInfo->TSFL;
4451 stats.TimeStampHigh = read_nic_dword(priv, TSFR+4);
4452
4453 UpdateRxPktTimeStamp8190(priv, &stats);
4454
4455 //
4456 // Get Total offset of MPDU Frame Body
4457 //
4458 if((stats.RxBufShift + stats.RxDrvInfoSize) > 0)
4459 stats.bShift = 1;
4460
4461 /* ???? */
4462 TranslateRxSignalStuff819xpci(priv, skb, &stats, pdesc, pDrvInfo);
4463
4464 /* Rx A-MPDU */
4465 if(pDrvInfo->FirstAGGR==1 || pDrvInfo->PartAggr == 1)
4466 RT_TRACE(COMP_RXDESC, "pDrvInfo->FirstAGGR = %d, pDrvInfo->PartAggr = %d\n",
4467 pDrvInfo->FirstAGGR, pDrvInfo->PartAggr);
4468 skb_trim(skb, skb->len - 4/*sCrcLng*/);
4469 /* rx packets statistics */
4470 ieee80211_hdr = (struct ieee80211_hdr_1addr *)skb->data;
4471 unicast_packet = false;
4472
4473 if(is_broadcast_ether_addr(ieee80211_hdr->addr1)) {
4474 //TODO
4475 }else if(is_multicast_ether_addr(ieee80211_hdr->addr1)){
4476 //TODO
4477 }else {
4478 /* unicast packet */
4479 unicast_packet = true;
4480 }
4481
4482 if(!ieee80211_rtl_rx(priv->ieee80211, skb, &stats)){
4483 dev_kfree_skb_any(skb);
4484 } else {
4485 priv->stats.rxok++;
4486 if(unicast_packet) {
4487 priv->stats.rxbytesunicast += skb->len;
4488 }
4489 }
4490
4491 pci_unmap_single(priv->pdev, *((dma_addr_t *) skb->cb),
4492 priv->rxbuffersize, PCI_DMA_FROMDEVICE);
4493
4494 skb = new_skb;
4495 priv->rx_buf[priv->rx_idx] = skb;
4496 *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
4497
4498done:
4499 pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb));
4500 pdesc->OWN = 1;
4501 pdesc->Length = priv->rxbuffersize;
4502 if (priv->rx_idx == priv->rxringcount-1)
4503 pdesc->EOR = 1;
4504 priv->rx_idx = (priv->rx_idx + 1) % priv->rxringcount;
4505 }
4506
4507}
4508
4509static void rtl8192_irq_rx_tasklet(unsigned long arg)
4510{
4511 struct r8192_priv *priv = (struct r8192_priv*) arg;
4512 rtl8192_rx(priv);
4513 /* unmask RDU */
4514 write_nic_dword(priv, INTA_MASK, read_nic_dword(priv, INTA_MASK) | IMR_RDU);
4515}
4516
4517static const struct net_device_ops rtl8192_netdev_ops = {
4518 .ndo_open = rtl8192_open,
4519 .ndo_stop = rtl8192_close,
4520 .ndo_tx_timeout = tx_timeout,
4521 .ndo_do_ioctl = rtl8192_ioctl,
4522 .ndo_set_multicast_list = r8192_set_multicast,
4523 .ndo_set_mac_address = r8192_set_mac_adr,
4524 .ndo_start_xmit = ieee80211_rtl_xmit,
4525};
4526
4527static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
4528 const struct pci_device_id *id)
4529{
4530 struct net_device *dev = NULL;
4531 struct r8192_priv *priv= NULL;
4532 u8 unit = 0;
4533 int ret = -ENODEV;
4534 unsigned long pmem_start, pmem_len, pmem_flags;
4535 u8 revisionid;
4536
4537 RT_TRACE(COMP_INIT,"Configuring chip resources\n");
4538
4539 if( pci_enable_device (pdev) ){
4540 RT_TRACE(COMP_ERR,"Failed to enable PCI device");
4541 return -EIO;
4542 }
4543
4544 pci_set_master(pdev);
4545 //pci_set_wmi(pdev);
4546 pci_set_dma_mask(pdev, 0xffffff00ULL);
4547 pci_set_consistent_dma_mask(pdev,0xffffff00ULL);
4548 dev = alloc_ieee80211(sizeof(struct r8192_priv));
4549 if (!dev) {
4550 ret = -ENOMEM;
4551 goto fail_free;
4552 }
4553
4554 pci_set_drvdata(pdev, dev);
4555 SET_NETDEV_DEV(dev, &pdev->dev);
4556 priv = ieee80211_priv(dev);
4557 priv->ieee80211 = netdev_priv(dev);
4558 priv->pdev=pdev;
4559 if((pdev->subsystem_vendor == PCI_VENDOR_ID_DLINK)&&(pdev->subsystem_device == 0x3304)){
4560 priv->ieee80211->bSupportRemoteWakeUp = 1;
4561 } else
4562 {
4563 priv->ieee80211->bSupportRemoteWakeUp = 0;
4564 }
4565
4566 pmem_start = pci_resource_start(pdev, 1);
4567 pmem_len = pci_resource_len(pdev, 1);
4568 pmem_flags = pci_resource_flags (pdev, 1);
4569
4570 if (!(pmem_flags & IORESOURCE_MEM)) {
4571 RT_TRACE(COMP_ERR, "region #1 not a MMIO resource, aborting\n");
4572 goto fail;
4573 }
4574
4575 //DMESG("Memory mapped space @ 0x%08lx ", pmem_start);
4576 if( ! request_mem_region(pmem_start, pmem_len, RTL819xE_MODULE_NAME)) {
4577 RT_TRACE(COMP_ERR,"request_mem_region failed!\n");
4578 goto fail;
4579 }
4580
4581 priv->mem_start = ioremap_nocache(pmem_start, pmem_len);
4582 if (!priv->mem_start) {
4583 RT_TRACE(COMP_ERR,"ioremap failed!\n");
4584 goto fail1;
4585 }
4586
4587 dev->mem_start = (unsigned long) priv->mem_start;
4588 dev->mem_end = (unsigned long) (priv->mem_start +
4589 pci_resource_len(pdev, 0));
4590
4591 /* We disable the RETRY_TIMEOUT register (0x41) to keep
4592 * PCI Tx retries from interfering with C3 CPU state */
4593 pci_write_config_byte(pdev, 0x41, 0x00);
4594
4595
4596 pci_read_config_byte(pdev, 0x08, &revisionid);
4597 /* If the revisionid is 0x10, the device uses rtl8192se. */
4598 if (pdev->device == 0x8192 && revisionid == 0x10)
4599 goto fail1;
4600
4601 pci_read_config_byte(pdev, 0x05, &unit);
4602 pci_write_config_byte(pdev, 0x05, unit & (~0x04));
4603
4604 dev->irq = pdev->irq;
4605 priv->irq = 0;
4606
4607 dev->netdev_ops = &rtl8192_netdev_ops;
4608
4609 dev->wireless_handlers = &r8192_wx_handlers_def;
4610 dev->type=ARPHRD_ETHER;
4611
4612 dev->watchdog_timeo = HZ*3;
4613
4614 if (dev_alloc_name(dev, ifname) < 0){
4615 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
4616 strcpy(ifname, "wlan%d");
4617 dev_alloc_name(dev, ifname);
4618 }
4619
4620 RT_TRACE(COMP_INIT, "Driver probe completed1\n");
4621 if (rtl8192_init(priv)!=0) {
4622 RT_TRACE(COMP_ERR, "Initialization failed\n");
4623 goto fail;
4624 }
4625
4626 register_netdev(dev);
4627 RT_TRACE(COMP_INIT, "dev name=======> %s\n",dev->name);
4628 rtl8192_proc_init_one(priv);
4629
4630
4631 RT_TRACE(COMP_INIT, "Driver probe completed\n");
4632 return 0;
4633
4634fail1:
4635
4636 if (priv->mem_start) {
4637 iounmap(priv->mem_start);
4638 release_mem_region( pci_resource_start(pdev, 1),
4639 pci_resource_len(pdev, 1) );
4640 }
4641
4642fail:
4643 if(dev){
4644
4645 if (priv->irq) {
4646 free_irq(priv->irq, priv);
4647 priv->irq = 0;
4648 }
4649 free_ieee80211(dev);
4650 }
4651
4652fail_free:
4653 pci_disable_device(pdev);
4654
4655 DMESG("wlan driver load failed\n");
4656 pci_set_drvdata(pdev, NULL);
4657 return ret;
4658
4659}
4660
4661/* detach all the work and timer structure declared or inititialized
4662 * in r8192_init function.
4663 * */
4664static void rtl8192_cancel_deferred_work(struct r8192_priv* priv)
4665{
4666 /* call cancel_work_sync instead of cancel_delayed_work if and only if Linux_version_code
4667 * is or is newer than 2.6.20 and work structure is defined to be struct work_struct.
4668 * Otherwise call cancel_delayed_work is enough.
4669 * FIXME (2.6.20 should 2.6.22, work_struct should not cancel)
4670 * */
4671 cancel_delayed_work(&priv->watch_dog_wq);
4672 cancel_delayed_work(&priv->update_beacon_wq);
4673 cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq);
4674 cancel_delayed_work(&priv->gpio_change_rf_wq);
4675 cancel_work_sync(&priv->reset_wq);
4676 cancel_work_sync(&priv->qos_activate);
4677}
4678
4679
4680static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev)
4681{
4682 struct net_device *dev = pci_get_drvdata(pdev);
4683 struct r8192_priv *priv ;
4684 u32 i;
4685
4686 if (dev) {
4687
4688 unregister_netdev(dev);
4689
4690 priv = ieee80211_priv(dev);
4691
4692 rtl8192_proc_remove_one(priv);
4693
4694 rtl8192_down(dev);
4695 if (priv->pFirmware)
4696 {
4697 vfree(priv->pFirmware);
4698 priv->pFirmware = NULL;
4699 }
4700 destroy_workqueue(priv->priv_wq);
4701
4702 /* free tx/rx rings */
4703 rtl8192_free_rx_ring(priv);
4704 for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
4705 rtl8192_free_tx_ring(priv, i);
4706
4707 if (priv->irq) {
4708 printk("Freeing irq %d\n", priv->irq);
4709 free_irq(priv->irq, priv);
4710 priv->irq = 0;
4711 }
4712
4713 if (priv->mem_start) {
4714 iounmap(priv->mem_start);
4715 release_mem_region( pci_resource_start(pdev, 1),
4716 pci_resource_len(pdev, 1) );
4717 }
4718
4719 free_ieee80211(dev);
4720 }
4721
4722 pci_disable_device(pdev);
4723 RT_TRACE(COMP_DOWN, "wlan driver removed\n");
4724}
4725
4726extern int ieee80211_rtl_init(void);
4727extern void ieee80211_rtl_exit(void);
4728
4729static int __init rtl8192_pci_module_init(void)
4730{
4731 int retval;
4732
4733 retval = ieee80211_rtl_init();
4734 if (retval)
4735 return retval;
4736
4737 printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n");
4738 printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n");
4739 RT_TRACE(COMP_INIT, "Initializing module\n");
4740 rtl8192_proc_module_init();
4741 if(0!=pci_register_driver(&rtl8192_pci_driver))
4742 {
4743 DMESG("No device found");
4744 /*pci_unregister_driver (&rtl8192_pci_driver);*/
4745 return -ENODEV;
4746 }
4747 return 0;
4748}
4749
4750
4751static void __exit rtl8192_pci_module_exit(void)
4752{
4753 pci_unregister_driver(&rtl8192_pci_driver);
4754
4755 RT_TRACE(COMP_DOWN, "Exiting\n");
4756 rtl8192_proc_module_remove();
4757 ieee80211_rtl_exit();
4758}
4759
4760static irqreturn_t rtl8192_interrupt(int irq, void *param)
4761{
4762 struct r8192_priv *priv = param;
4763 struct net_device *dev = priv->ieee80211->dev;
4764 unsigned long flags;
4765 u32 inta;
4766 irqreturn_t ret = IRQ_HANDLED;
4767
4768 spin_lock_irqsave(&priv->irq_th_lock, flags);
4769
4770 /* ISR: 4bytes */
4771
4772 inta = read_nic_dword(priv, ISR); /* & priv->IntrMask; */
4773 write_nic_dword(priv, ISR, inta); /* reset int situation */
4774
4775 if (!inta) {
4776 /*
4777 * most probably we can safely return IRQ_NONE,
4778 * but for now is better to avoid problems
4779 */
4780 goto out_unlock;
4781 }
4782
4783 if (inta == 0xffff) {
4784 /* HW disappared */
4785 goto out_unlock;
4786 }
4787
4788 if (!netif_running(dev))
4789 goto out_unlock;
4790
4791 if (inta & IMR_TBDOK) {
4792 RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
4793 rtl8192_tx_isr(priv, BEACON_QUEUE);
4794 priv->stats.txbeaconokint++;
4795 }
4796
4797 if (inta & IMR_TBDER) {
4798 RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
4799 rtl8192_tx_isr(priv, BEACON_QUEUE);
4800 priv->stats.txbeaconerr++;
4801 }
4802
4803 if (inta & IMR_MGNTDOK ) {
4804 RT_TRACE(COMP_INTR, "Manage ok interrupt!\n");
4805 priv->stats.txmanageokint++;
4806 rtl8192_tx_isr(priv, MGNT_QUEUE);
4807 }
4808
4809 if (inta & IMR_COMDOK)
4810 {
4811 priv->stats.txcmdpktokint++;
4812 rtl8192_tx_isr(priv, TXCMD_QUEUE);
4813 }
4814
4815 if (inta & IMR_ROK) {
4816 priv->stats.rxint++;
4817 tasklet_schedule(&priv->irq_rx_tasklet);
4818 }
4819
4820 if (inta & IMR_BcnInt) {
4821 RT_TRACE(COMP_INTR, "prepare beacon for interrupt!\n");
4822 tasklet_schedule(&priv->irq_prepare_beacon_tasklet);
4823 }
4824
4825 if (inta & IMR_RDU) {
4826 RT_TRACE(COMP_INTR, "rx descriptor unavailable!\n");
4827 priv->stats.rxrdu++;
4828 /* reset int situation */
4829 write_nic_dword(priv, INTA_MASK, read_nic_dword(priv, INTA_MASK) & ~IMR_RDU);
4830 tasklet_schedule(&priv->irq_rx_tasklet);
4831 }
4832
4833 if (inta & IMR_RXFOVW) {
4834 RT_TRACE(COMP_INTR, "rx overflow !\n");
4835 priv->stats.rxoverflow++;
4836 tasklet_schedule(&priv->irq_rx_tasklet);
4837 }
4838
4839 if (inta & IMR_TXFOVW)
4840 priv->stats.txoverflow++;
4841
4842 if (inta & IMR_BKDOK) {
4843 RT_TRACE(COMP_INTR, "BK Tx OK interrupt!\n");
4844 priv->stats.txbkokint++;
4845 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
4846 rtl8192_tx_isr(priv, BK_QUEUE);
4847 }
4848
4849 if (inta & IMR_BEDOK) {
4850 RT_TRACE(COMP_INTR, "BE TX OK interrupt!\n");
4851 priv->stats.txbeokint++;
4852 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
4853 rtl8192_tx_isr(priv, BE_QUEUE);
4854 }
4855
4856 if (inta & IMR_VIDOK) {
4857 RT_TRACE(COMP_INTR, "VI TX OK interrupt!\n");
4858 priv->stats.txviokint++;
4859 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
4860 rtl8192_tx_isr(priv, VI_QUEUE);
4861 }
4862
4863 if (inta & IMR_VODOK) {
4864 priv->stats.txvookint++;
4865 priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
4866 rtl8192_tx_isr(priv, VO_QUEUE);
4867 }
4868
4869out_unlock:
4870 spin_unlock_irqrestore(&priv->irq_th_lock, flags);
4871
4872 return ret;
4873}
4874
4875void EnableHWSecurityConfig8192(struct r8192_priv *priv)
4876{
4877 u8 SECR_value = 0x0;
4878 struct ieee80211_device* ieee = priv->ieee80211;
4879
4880 SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
4881
4882 if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->ieee80211->auth_mode != 2))
4883 {
4884 SECR_value |= SCR_RxUseDK;
4885 SECR_value |= SCR_TxUseDK;
4886 }
4887 else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP)))
4888 {
4889 SECR_value |= SCR_RxUseDK;
4890 SECR_value |= SCR_TxUseDK;
4891 }
4892
4893 //add HWSec active enable here.
4894//default using hwsec. when peer AP is in N mode only and pairwise_key_type is none_aes(which HT_IOT_ACT_PURE_N_MODE indicates it), use software security. when peer AP is in b,g,n mode mixed and pairwise_key_type is none_aes, use g mode hw security. WB on 2008.7.4
4895 ieee->hwsec_active = 1;
4896
4897 if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep)//!ieee->hwsec_support) //add hwsec_support flag to totol control hw_sec on/off
4898 {
4899 ieee->hwsec_active = 0;
4900 SECR_value &= ~SCR_RxDecEnable;
4901 }
4902
4903 RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __FUNCTION__,
4904 ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
4905 {
4906 write_nic_byte(priv, SECR, SECR_value);//SECR_value | SCR_UseDK );
4907 }
4908
4909}
4910#define TOTAL_CAM_ENTRY 32
4911//#define CAM_CONTENT_COUNT 8
4912void setKey(struct r8192_priv *priv, u8 EntryNo, u8 KeyIndex, u16 KeyType,
4913 const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
4914{
4915 u32 TargetCommand = 0;
4916 u32 TargetContent = 0;
4917 u16 usConfig = 0;
4918 u8 i;
4919#ifdef ENABLE_IPS
4920 RT_RF_POWER_STATE rtState;
4921
4922 rtState = priv->eRFPowerState;
4923 if (priv->PowerSaveControl.bInactivePs){
4924 if(rtState == eRfOff){
4925 if(priv->RfOffReason > RF_CHANGE_BY_IPS)
4926 {
4927 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
4928 //up(&priv->wx_sem);
4929 return ;
4930 }
4931 else{
4932 down(&priv->ieee80211->ips_sem);
4933 IPSLeave(priv);
4934 up(&priv->ieee80211->ips_sem);
4935 }
4936 }
4937 }
4938 priv->ieee80211->is_set_key = true;
4939#endif
4940 if (EntryNo >= TOTAL_CAM_ENTRY)
4941 RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
4942
4943 RT_TRACE(COMP_SEC, "====>to setKey(), priv:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", priv, EntryNo, KeyIndex, KeyType, MacAddr);
4944
4945 if (DefaultKey)
4946 usConfig |= BIT15 | (KeyType<<2);
4947 else
4948 usConfig |= BIT15 | (KeyType<<2) | KeyIndex;
4949// usConfig |= BIT15 | (KeyType<<2) | (DefaultKey<<5) | KeyIndex;
4950
4951
4952 for(i=0 ; i<CAM_CONTENT_COUNT; i++){
4953 TargetCommand = i+CAM_CONTENT_COUNT*EntryNo;
4954 TargetCommand |= BIT31|BIT16;
4955
4956 if(i==0){//MAC|Config
4957 TargetContent = (u32)(*(MacAddr+0)) << 16|
4958 (u32)(*(MacAddr+1)) << 24|
4959 (u32)usConfig;
4960
4961 write_nic_dword(priv, WCAMI, TargetContent);
4962 write_nic_dword(priv, RWCAM, TargetCommand);
4963 }
4964 else if(i==1){//MAC
4965 TargetContent = (u32)(*(MacAddr+2)) |
4966 (u32)(*(MacAddr+3)) << 8|
4967 (u32)(*(MacAddr+4)) << 16|
4968 (u32)(*(MacAddr+5)) << 24;
4969 write_nic_dword(priv, WCAMI, TargetContent);
4970 write_nic_dword(priv, RWCAM, TargetCommand);
4971 }
4972 else { //Key Material
4973 if(KeyContent != NULL)
4974 {
4975 write_nic_dword(priv, WCAMI, (u32)(*(KeyContent+i-2)) );
4976 write_nic_dword(priv, RWCAM, TargetCommand);
4977 }
4978 }
4979 }
4980 RT_TRACE(COMP_SEC,"=========>after set key, usconfig:%x\n", usConfig);
4981}
4982
4983bool NicIFEnableNIC(struct r8192_priv *priv)
4984{
4985 RT_STATUS init_status = RT_STATUS_SUCCESS;
4986 PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
4987
4988 //YJ,add,091109
4989 if (priv->up == 0){
4990 RT_TRACE(COMP_ERR, "ERR!!! %s(): Driver is already down!\n",__FUNCTION__);
4991 priv->bdisable_nic = false; //YJ,add,091111
4992 return false;
4993 }
4994 // <1> Reset memory: descriptor, buffer,..
4995 //NicIFResetMemory(Adapter);
4996
4997 // <2> Enable Adapter
4998 //priv->bfirst_init = true;
4999 init_status = rtl8192_adapter_start(priv);
5000 if (init_status != RT_STATUS_SUCCESS) {
5001 RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
5002 priv->bdisable_nic = false; //YJ,add,091111
5003 return -1;
5004 }
5005 RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
5006 //priv->bfirst_init = false;
5007
5008 // <3> Enable Interrupt
5009 rtl8192_irq_enable(priv);
5010 priv->bdisable_nic = false;
5011
5012 return (init_status == RT_STATUS_SUCCESS);
5013}
5014
5015bool NicIFDisableNIC(struct r8192_priv *priv)
5016{
5017 bool status = true;
5018 u8 tmp_state = 0;
5019 // <1> Disable Interrupt
5020
5021 priv->bdisable_nic = true; //YJ,move,091109
5022 tmp_state = priv->ieee80211->state;
5023
5024 ieee80211_softmac_stop_protocol(priv->ieee80211, false);
5025
5026 priv->ieee80211->state = tmp_state;
5027 rtl8192_cancel_deferred_work(priv);
5028 rtl8192_irq_disable(priv);
5029 // <2> Stop all timer
5030
5031 // <3> Disable Adapter
5032 rtl8192_halt_adapter(priv, false);
5033// priv->bdisable_nic = true;
5034
5035 return status;
5036}
5037
5038module_init(rtl8192_pci_module_init);
5039module_exit(rtl8192_pci_module_exit);
diff --git a/drivers/staging/rtl8192e/r8192E_dm.c b/drivers/staging/rtl8192e/r8192E_dm.c
new file mode 100644
index 00000000000..688d29b5588
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8192E_dm.c
@@ -0,0 +1,2554 @@
1/*++
2Copyright-c Realtek Semiconductor Corp. All rights reserved.
3
4Module Name:
5 r8192U_dm.c
6
7Abstract:
8 HW dynamic mechanism.
9
10Major Change History:
11 When Who What
12 ---------- --------------- -------------------------------
13 2008-05-14 amy create version 0 porting from windows code.
14
15--*/
16#include "r8192E.h"
17#include "r8192E_dm.h"
18#include "r8192E_hw.h"
19#include "r819xE_phy.h"
20#include "r819xE_phyreg.h"
21#include "r8190_rtl8256.h"
22
23#define DRV_NAME "rtl819xE"
24
25//
26// Indicate different AP vendor for IOT issue.
27//
28static const u32 edca_setting_DL[HT_IOT_PEER_MAX] =
29{ 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0xa44f, 0x5e4322, 0x5e4322};
30static const u32 edca_setting_UL[HT_IOT_PEER_MAX] =
31{ 0x5e4322, 0xa44f, 0x5e4322, 0x604322, 0x5e4322, 0x5e4322, 0x5e4322};
32
33#define RTK_UL_EDCA 0xa44f
34#define RTK_DL_EDCA 0x5e4322
35
36
37dig_t dm_digtable;
38// For Dynamic Rx Path Selection by Signal Strength
39DRxPathSel DM_RxPathSelTable;
40
41void dm_gpio_change_rf_callback(struct work_struct *work);
42
43// DM --> Rate Adaptive
44static void dm_check_rate_adaptive(struct r8192_priv *priv);
45
46// DM --> Bandwidth switch
47static void dm_init_bandwidth_autoswitch(struct r8192_priv *priv);
48static void dm_bandwidth_autoswitch(struct r8192_priv *priv);
49
50// DM --> TX power control
51static void dm_check_txpower_tracking(struct r8192_priv *priv);
52
53// DM --> Dynamic Init Gain by RSSI
54static void dm_dig_init(struct r8192_priv *priv);
55static void dm_ctrl_initgain_byrssi(struct r8192_priv *priv);
56static void dm_ctrl_initgain_byrssi_highpwr(struct r8192_priv *priv);
57static void dm_ctrl_initgain_byrssi_by_driverrssi(struct r8192_priv *priv);
58static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct r8192_priv *priv);
59static void dm_initial_gain(struct r8192_priv *priv);
60static void dm_pd_th(struct r8192_priv *priv);
61static void dm_cs_ratio(struct r8192_priv *priv);
62
63static void dm_init_ctstoself(struct r8192_priv *priv);
64// DM --> EDCA turboe mode control
65static void dm_check_edca_turbo(struct r8192_priv *priv);
66static void dm_init_edca_turbo(struct r8192_priv *priv);
67
68// DM --> HW RF control
69static void dm_check_rfctrl_gpio(struct r8192_priv *priv);
70
71// DM --> Check current RX RF path state
72static void dm_check_rx_path_selection(struct r8192_priv *priv);
73static void dm_init_rxpath_selection(struct r8192_priv *priv);
74static void dm_rxpath_sel_byrssi(struct r8192_priv *priv);
75
76// DM --> Fsync for broadcom ap
77static void dm_init_fsync(struct r8192_priv *priv);
78static void dm_deInit_fsync(struct r8192_priv *priv);
79
80static void dm_check_txrateandretrycount(struct r8192_priv *priv);
81static void dm_check_fsync(struct r8192_priv *priv);
82
83
84/*---------------------Define of Tx Power Control For Near/Far Range --------*/ //Add by Jacken 2008/02/18
85static void dm_init_dynamic_txpower(struct r8192_priv *priv);
86static void dm_dynamic_txpower(struct r8192_priv *priv);
87
88// DM --> For rate adaptive and DIG, we must send RSSI to firmware
89static void dm_send_rssi_tofw(struct r8192_priv *priv);
90static void dm_ctstoself(struct r8192_priv *priv);
91
92static void dm_fsync_timer_callback(unsigned long data);
93
94/*
95 * Prepare SW resource for HW dynamic mechanism.
96 * This function is only invoked at driver intialization once.
97 */
98void init_hal_dm(struct r8192_priv *priv)
99{
100 // Undecorated Smoothed Signal Strength, it can utilized to dynamic mechanism.
101 priv->undecorated_smoothed_pwdb = -1;
102
103 //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code.
104 dm_init_dynamic_txpower(priv);
105 init_rate_adaptive(priv);
106 //dm_initialize_txpower_tracking(dev);
107 dm_dig_init(priv);
108 dm_init_edca_turbo(priv);
109 dm_init_bandwidth_autoswitch(priv);
110 dm_init_fsync(priv);
111 dm_init_rxpath_selection(priv);
112 dm_init_ctstoself(priv);
113 INIT_DELAYED_WORK(&priv->gpio_change_rf_wq, dm_gpio_change_rf_callback);
114
115}
116
117void deinit_hal_dm(struct r8192_priv *priv)
118{
119 dm_deInit_fsync(priv);
120}
121
122void hal_dm_watchdog(struct r8192_priv *priv)
123{
124
125 /*Add by amy 2008/05/15 ,porting from windows code.*/
126 dm_check_rate_adaptive(priv);
127 dm_dynamic_txpower(priv);
128 dm_check_txrateandretrycount(priv);
129
130 dm_check_txpower_tracking(priv);
131
132 dm_ctrl_initgain_byrssi(priv);
133 dm_check_edca_turbo(priv);
134 dm_bandwidth_autoswitch(priv);
135
136 dm_check_rfctrl_gpio(priv);
137 dm_check_rx_path_selection(priv);
138 dm_check_fsync(priv);
139
140 // Add by amy 2008-05-15 porting from windows code.
141 dm_send_rssi_tofw(priv);
142 dm_ctstoself(priv);
143}
144
145
146/*
147 * Decide Rate Adaptive Set according to distance (signal strength)
148 * 01/11/2008 MHC Modify input arguments and RATR table level.
149 * 01/16/2008 MHC RF_Type is assigned in ReadAdapterInfo(). We must call
150 * the function after making sure RF_Type.
151 */
152void init_rate_adaptive(struct r8192_priv *priv)
153{
154 prate_adaptive pra = &priv->rate_adaptive;
155
156 pra->ratr_state = DM_RATR_STA_MAX;
157 pra->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High;
158 pra->low2high_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M+5;
159 pra->low2high_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M+5;
160
161 pra->high_rssi_thresh_for_ra = RateAdaptiveTH_High+5;
162 pra->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M;
163 pra->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M;
164
165 if(priv->CustomerID == RT_CID_819x_Netcore)
166 pra->ping_rssi_enable = 1;
167 else
168 pra->ping_rssi_enable = 0;
169 pra->ping_rssi_thresh_for_ra = 15;
170
171
172 if (priv->rf_type == RF_2T4R)
173 {
174 // 07/10/08 MH Modify for RA smooth scheme.
175 /* 2008/01/11 MH Modify 2T RATR table for different RSSI. 080515 porting by amy from windows code.*/
176 pra->upper_rssi_threshold_ratr = 0x8f0f0000;
177 pra->middle_rssi_threshold_ratr = 0x8f0ff000;
178 pra->low_rssi_threshold_ratr = 0x8f0ff001;
179 pra->low_rssi_threshold_ratr_40M = 0x8f0ff005;
180 pra->low_rssi_threshold_ratr_20M = 0x8f0ff001;
181 pra->ping_rssi_ratr = 0x0000000d;//cosa add for test
182 }
183 else if (priv->rf_type == RF_1T2R)
184 {
185 pra->upper_rssi_threshold_ratr = 0x000f0000;
186 pra->middle_rssi_threshold_ratr = 0x000ff000;
187 pra->low_rssi_threshold_ratr = 0x000ff001;
188 pra->low_rssi_threshold_ratr_40M = 0x000ff005;
189 pra->low_rssi_threshold_ratr_20M = 0x000ff001;
190 pra->ping_rssi_ratr = 0x0000000d;//cosa add for test
191 }
192
193}
194
195
196static void dm_check_rate_adaptive(struct r8192_priv *priv)
197{
198 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
199 prate_adaptive pra = (prate_adaptive)&priv->rate_adaptive;
200 u32 currentRATR, targetRATR = 0;
201 u32 LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0;
202 bool bshort_gi_enabled = false;
203 static u8 ping_rssi_state=0;
204
205
206 if(!priv->up)
207 {
208 RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n");
209 return;
210 }
211
212 if(pra->rate_adaptive_disabled)//this variable is set by ioctl.
213 return;
214
215 // TODO: Only 11n mode is implemented currently,
216 if( !(priv->ieee80211->mode == WIRELESS_MODE_N_24G ||
217 priv->ieee80211->mode == WIRELESS_MODE_N_5G))
218 return;
219
220 if( priv->ieee80211->state == IEEE80211_LINKED )
221 {
222 // RT_TRACE(COMP_RATE, "dm_CheckRateAdaptive(): \t");
223
224 //
225 // Check whether Short GI is enabled
226 //
227 bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) ||
228 (!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz);
229
230
231 pra->upper_rssi_threshold_ratr =
232 (pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
233
234 pra->middle_rssi_threshold_ratr =
235 (pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
236
237 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
238 {
239 pra->low_rssi_threshold_ratr =
240 (pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
241 }
242 else
243 {
244 pra->low_rssi_threshold_ratr =
245 (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
246 }
247 //cosa add for test
248 pra->ping_rssi_ratr =
249 (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ;
250
251 /* 2007/10/08 MH We support RA smooth scheme now. When it is the first
252 time to link with AP. We will not change upper/lower threshold. If
253 STA stay in high or low level, we must change two different threshold
254 to prevent jumping frequently. */
255 if (pra->ratr_state == DM_RATR_STA_HIGH)
256 {
257 HighRSSIThreshForRA = pra->high2low_rssi_thresh_for_ra;
258 LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
259 (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
260 }
261 else if (pra->ratr_state == DM_RATR_STA_LOW)
262 {
263 HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra;
264 LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
265 (pra->low2high_rssi_thresh_for_ra40M):(pra->low2high_rssi_thresh_for_ra20M);
266 }
267 else
268 {
269 HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra;
270 LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)?
271 (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
272 }
273
274 if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA)
275 {
276 pra->ratr_state = DM_RATR_STA_HIGH;
277 targetRATR = pra->upper_rssi_threshold_ratr;
278 }else if(priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA)
279 {
280 pra->ratr_state = DM_RATR_STA_MIDDLE;
281 targetRATR = pra->middle_rssi_threshold_ratr;
282 }else
283 {
284 pra->ratr_state = DM_RATR_STA_LOW;
285 targetRATR = pra->low_rssi_threshold_ratr;
286 }
287
288 //cosa add for test
289 if(pra->ping_rssi_enable)
290 {
291 //pHalData->UndecoratedSmoothedPWDB = 19;
292 if(priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5))
293 {
294 if( (priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) ||
295 ping_rssi_state )
296 {
297 pra->ratr_state = DM_RATR_STA_LOW;
298 targetRATR = pra->ping_rssi_ratr;
299 ping_rssi_state = 1;
300 }
301 }
302 else
303 {
304 ping_rssi_state = 0;
305 }
306 }
307
308 // For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7.
309 if(priv->ieee80211->GetHalfNmodeSupportByAPsHandler(priv->ieee80211))
310 targetRATR &= 0xf00fffff;
311
312 //
313 // Check whether updating of RATR0 is required
314 //
315 currentRATR = read_nic_dword(priv, RATR0);
316 if( targetRATR != currentRATR )
317 {
318 u32 ratr_value;
319 ratr_value = targetRATR;
320 RT_TRACE(COMP_RATE,"currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR);
321 if(priv->rf_type == RF_1T2R)
322 {
323 ratr_value &= ~(RATE_ALL_OFDM_2SS);
324 }
325 write_nic_dword(priv, RATR0, ratr_value);
326 write_nic_byte(priv, UFWP, 1);
327
328 pra->last_ratr = targetRATR;
329 }
330
331 }
332 else
333 {
334 pra->ratr_state = DM_RATR_STA_MAX;
335 }
336
337}
338
339
340static void dm_init_bandwidth_autoswitch(struct r8192_priv *priv)
341{
342 priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH;
343 priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW;
344 priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false;
345 priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable = false;
346
347}
348
349
350static void dm_bandwidth_autoswitch(struct r8192_priv *priv)
351{
352 if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable){
353 return;
354 }else{
355 if(priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false){//If send packets in 40 Mhz in 20/40
356 if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz)
357 priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true;
358 }else{//in force send packets in 20 Mhz in 20/40
359 if(priv->undecorated_smoothed_pwdb >= priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz)
360 priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false;
361
362 }
363 }
364}
365
366//OFDM default at 0db, index=6.
367static const u32 OFDMSwingTable[OFDM_Table_Length] = {
368 0x7f8001fe, // 0, +6db
369 0x71c001c7, // 1, +5db
370 0x65400195, // 2, +4db
371 0x5a400169, // 3, +3db
372 0x50800142, // 4, +2db
373 0x47c0011f, // 5, +1db
374 0x40000100, // 6, +0db ===> default, upper for higher temperature, lower for low temperature
375 0x390000e4, // 7, -1db
376 0x32c000cb, // 8, -2db
377 0x2d4000b5, // 9, -3db
378 0x288000a2, // 10, -4db
379 0x24000090, // 11, -5db
380 0x20000080, // 12, -6db
381 0x1c800072, // 13, -7db
382 0x19800066, // 14, -8db
383 0x26c0005b, // 15, -9db
384 0x24400051, // 16, -10db
385 0x12000048, // 17, -11db
386 0x10000040 // 18, -12db
387};
388static const u8 CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = {
389 {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, // 0, +0db ===> CCK40M default
390 {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, // 1, -1db
391 {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, // 2, -2db
392 {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, // 3, -3db
393 {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, // 4, -4db
394 {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, // 5, -5db
395 {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, // 6, -6db ===> CCK20M default
396 {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, // 7, -7db
397 {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, // 8, -8db
398 {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, // 9, -9db
399 {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, // 10, -10db
400 {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} // 11, -11db
401};
402
403static const u8 CCKSwingTable_Ch14[CCK_Table_length][8] = {
404 {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, // 0, +0db ===> CCK40M default
405 {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, // 1, -1db
406 {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, // 2, -2db
407 {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, // 3, -3db
408 {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, // 4, -4db
409 {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, // 5, -5db
410 {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, // 6, -6db ===> CCK20M default
411 {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, // 7, -7db
412 {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, // 8, -8db
413 {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, // 9, -9db
414 {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, // 10, -10db
415 {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} // 11, -11db
416};
417
418#define Pw_Track_Flag 0x11d
419#define Tssi_Mea_Value 0x13c
420#define Tssi_Report_Value1 0x134
421#define Tssi_Report_Value2 0x13e
422#define FW_Busy_Flag 0x13f
423static void dm_TXPowerTrackingCallback_TSSI(struct r8192_priv *priv)
424{
425 bool bHighpowerstate, viviflag = FALSE;
426 DCMD_TXCMD_T tx_cmd;
427 u8 powerlevelOFDM24G;
428 int i =0, j = 0, k = 0;
429 u8 RF_Type, tmp_report[5]={0, 0, 0, 0, 0};
430 u32 Value;
431 u8 Pwr_Flag;
432 u16 Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver=0;
433// bool rtStatus = true;
434 u32 delta=0;
435 RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__);
436// write_nic_byte(priv, 0x1ba, 0);
437 write_nic_byte(priv, Pw_Track_Flag, 0);
438 write_nic_byte(priv, FW_Busy_Flag, 0);
439 priv->ieee80211->bdynamic_txpower_enable = false;
440 bHighpowerstate = priv->bDynamicTxHighPower;
441
442 powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24);
443 RF_Type = priv->rf_type;
444 Value = (RF_Type<<8) | powerlevelOFDM24G;
445
446 RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n", powerlevelOFDM24G);
447
448 for(j = 0; j<=30; j++)
449{ //fill tx_cmd
450
451 tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING;
452 tx_cmd.Length = 4;
453 tx_cmd.Value = Value;
454 cmpk_message_handle_tx(priv, (u8*)&tx_cmd, DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
455 mdelay(1);
456
457 for(i = 0;i <= 30; i++)
458 {
459 Pwr_Flag = read_nic_byte(priv, Pw_Track_Flag);
460
461 if (Pwr_Flag == 0)
462 {
463 mdelay(1);
464 continue;
465 }
466
467 Avg_TSSI_Meas = read_nic_word(priv, Tssi_Mea_Value);
468
469 if(Avg_TSSI_Meas == 0)
470 {
471 write_nic_byte(priv, Pw_Track_Flag, 0);
472 write_nic_byte(priv, FW_Busy_Flag, 0);
473 return;
474 }
475
476 for(k = 0;k < 5; k++)
477 {
478 if(k !=4)
479 tmp_report[k] = read_nic_byte(priv, Tssi_Report_Value1+k);
480 else
481 tmp_report[k] = read_nic_byte(priv, Tssi_Report_Value2);
482
483 RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]);
484 }
485
486 //check if the report value is right
487 for(k = 0;k < 5; k++)
488 {
489 if(tmp_report[k] <= 20)
490 {
491 viviflag =TRUE;
492 break;
493 }
494 }
495 if(viviflag ==TRUE)
496 {
497 write_nic_byte(priv, Pw_Track_Flag, 0);
498 viviflag = FALSE;
499 RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n");
500 for(k = 0;k < 5; k++)
501 tmp_report[k] = 0;
502 break;
503 }
504
505 for(k = 0;k < 5; k++)
506 {
507 Avg_TSSI_Meas_from_driver += tmp_report[k];
508 }
509
510 Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5;
511 RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver);
512 TSSI_13dBm = priv->TSSI_13dBm;
513 RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm);
514
515 //if(abs(Avg_TSSI_Meas_from_driver - TSSI_13dBm) <= E_FOR_TX_POWER_TRACK)
516 // For MacOS-compatible
517 if(Avg_TSSI_Meas_from_driver > TSSI_13dBm)
518 delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm;
519 else
520 delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver;
521
522 if(delta <= E_FOR_TX_POWER_TRACK)
523 {
524 priv->ieee80211->bdynamic_txpower_enable = TRUE;
525 write_nic_byte(priv, Pw_Track_Flag, 0);
526 write_nic_byte(priv, FW_Busy_Flag, 0);
527 RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n");
528 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
529 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
530 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference);
531 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
532 return;
533 }
534 else
535 {
536 if(Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK)
537 {
538 if (RF_Type == RF_2T4R)
539 {
540
541 if((priv->rfa_txpowertrackingindex > 0) &&(priv->rfc_txpowertrackingindex > 0))
542 {
543 priv->rfa_txpowertrackingindex--;
544 if(priv->rfa_txpowertrackingindex_real > 4)
545 {
546 priv->rfa_txpowertrackingindex_real--;
547 rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
548 }
549
550 priv->rfc_txpowertrackingindex--;
551 if(priv->rfc_txpowertrackingindex_real > 4)
552 {
553 priv->rfc_txpowertrackingindex_real--;
554 rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
555 }
556 }
557 else
558 {
559 rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
560 rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
561 }
562 }
563 else
564 {
565 if(priv->rfc_txpowertrackingindex > 0)
566 {
567 priv->rfc_txpowertrackingindex--;
568 if(priv->rfc_txpowertrackingindex_real > 4)
569 {
570 priv->rfc_txpowertrackingindex_real--;
571 rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
572 }
573 }
574 else
575 rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
576 }
577 }
578 else
579 {
580 if (RF_Type == RF_2T4R)
581 {
582 if((priv->rfa_txpowertrackingindex < TxBBGainTableLength - 1) &&(priv->rfc_txpowertrackingindex < TxBBGainTableLength - 1))
583 {
584 priv->rfa_txpowertrackingindex++;
585 priv->rfa_txpowertrackingindex_real++;
586 rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
587 priv->rfc_txpowertrackingindex++;
588 priv->rfc_txpowertrackingindex_real++;
589 rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
590 }
591 else
592 {
593 rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
594 rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
595 }
596 }
597 else
598 {
599 if(priv->rfc_txpowertrackingindex < (TxBBGainTableLength - 1))
600 {
601 priv->rfc_txpowertrackingindex++;
602 priv->rfc_txpowertrackingindex_real++;
603 rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
604 }
605 else
606 rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
607 }
608 }
609 if (RF_Type == RF_2T4R)
610 priv->CCKPresentAttentuation_difference
611 = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default;
612 else
613 priv->CCKPresentAttentuation_difference
614 = priv->rfc_txpowertrackingindex - priv->rfc_txpowertracking_default;
615
616 if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20)
617 priv->CCKPresentAttentuation
618 = priv->CCKPresentAttentuation_20Mdefault + priv->CCKPresentAttentuation_difference;
619 else
620 priv->CCKPresentAttentuation
621 = priv->CCKPresentAttentuation_40Mdefault + priv->CCKPresentAttentuation_difference;
622
623 if(priv->CCKPresentAttentuation > (CCKTxBBGainTableLength-1))
624 priv->CCKPresentAttentuation = CCKTxBBGainTableLength-1;
625 if(priv->CCKPresentAttentuation < 0)
626 priv->CCKPresentAttentuation = 0;
627
628 if(1)
629 {
630 if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
631 {
632 priv->bcck_in_ch14 = TRUE;
633 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
634 }
635 else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
636 {
637 priv->bcck_in_ch14 = FALSE;
638 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
639 }
640 else
641 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
642 }
643 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
644 RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
645 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference);
646 RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
647
648 if (priv->CCKPresentAttentuation_difference <= -12||priv->CCKPresentAttentuation_difference >= 24)
649 {
650 priv->ieee80211->bdynamic_txpower_enable = TRUE;
651 write_nic_byte(priv, Pw_Track_Flag, 0);
652 write_nic_byte(priv, FW_Busy_Flag, 0);
653 RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n");
654 return;
655 }
656
657
658 }
659 write_nic_byte(priv, Pw_Track_Flag, 0);
660 Avg_TSSI_Meas_from_driver = 0;
661 for(k = 0;k < 5; k++)
662 tmp_report[k] = 0;
663 break;
664 }
665 write_nic_byte(priv, FW_Busy_Flag, 0);
666}
667 priv->ieee80211->bdynamic_txpower_enable = TRUE;
668 write_nic_byte(priv, Pw_Track_Flag, 0);
669}
670
671static void dm_TXPowerTrackingCallback_ThermalMeter(struct r8192_priv *priv)
672{
673#define ThermalMeterVal 9
674 u32 tmpRegA, TempCCk;
675 u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval;
676 int i =0, CCKSwingNeedUpdate=0;
677
678 if(!priv->btxpower_trackingInit)
679 {
680 //Query OFDM default setting
681 tmpRegA = rtl8192_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord);
682 for(i=0; i<OFDM_Table_Length; i++) //find the index
683 {
684 if(tmpRegA == OFDMSwingTable[i])
685 {
686 priv->OFDM_index= (u8)i;
687 RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, OFDM_index=0x%x\n",
688 rOFDM0_XATxIQImbalance, tmpRegA, priv->OFDM_index);
689 }
690 }
691
692 //Query CCK default setting From 0xa22
693 TempCCk = rtl8192_QueryBBReg(priv, rCCK0_TxFilter1, bMaskByte2);
694 for(i=0 ; i<CCK_Table_length ; i++)
695 {
696 if(TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0])
697 {
698 priv->CCK_index =(u8) i;
699 RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, CCK_index=0x%x\n",
700 rCCK0_TxFilter1, TempCCk, priv->CCK_index);
701 break;
702 }
703 }
704 priv->btxpower_trackingInit = TRUE;
705 //pHalData->TXPowercount = 0;
706 return;
707 }
708
709 // read and filter out unreasonable value
710 tmpRegA = rtl8192_phy_QueryRFReg(priv, RF90_PATH_A, 0x12, 0x078); // 0x12: RF Reg[10:7]
711 RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d\n", tmpRegA);
712 if(tmpRegA < 3 || tmpRegA > 13)
713 return;
714 if(tmpRegA >= 12) // if over 12, TP will be bad when high temperature
715 tmpRegA = 12;
716 RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d\n", tmpRegA);
717 priv->ThermalMeter[0] = ThermalMeterVal; //We use fixed value by Bryant's suggestion
718 priv->ThermalMeter[1] = ThermalMeterVal; //We use fixed value by Bryant's suggestion
719
720 //Get current RF-A temperature index
721 if(priv->ThermalMeter[0] >= (u8)tmpRegA) //lower temperature
722 {
723 tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA);
724 tmpCCK40Mindex = tmpCCK20Mindex - 6;
725 if(tmpOFDMindex >= OFDM_Table_Length)
726 tmpOFDMindex = OFDM_Table_Length-1;
727 if(tmpCCK20Mindex >= CCK_Table_length)
728 tmpCCK20Mindex = CCK_Table_length-1;
729 if(tmpCCK40Mindex >= CCK_Table_length)
730 tmpCCK40Mindex = CCK_Table_length-1;
731 }
732 else
733 {
734 tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]);
735 if(tmpval >= 6) // higher temperature
736 tmpOFDMindex = tmpCCK20Mindex = 0; // max to +6dB
737 else
738 tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval;
739 tmpCCK40Mindex = 0;
740 }
741
742 if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) //40M
743 tmpCCKindex = tmpCCK40Mindex;
744 else
745 tmpCCKindex = tmpCCK20Mindex;
746
747 //record for bandwidth swith
748 priv->Record_CCK_20Mindex = tmpCCK20Mindex;
749 priv->Record_CCK_40Mindex = tmpCCK40Mindex;
750 RT_TRACE(COMP_POWER_TRACKING, "Record_CCK_20Mindex / Record_CCK_40Mindex = %d / %d.\n",
751 priv->Record_CCK_20Mindex, priv->Record_CCK_40Mindex);
752
753 if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
754 {
755 priv->bcck_in_ch14 = TRUE;
756 CCKSwingNeedUpdate = 1;
757 }
758 else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
759 {
760 priv->bcck_in_ch14 = FALSE;
761 CCKSwingNeedUpdate = 1;
762 }
763
764 if(priv->CCK_index != tmpCCKindex)
765{
766 priv->CCK_index = tmpCCKindex;
767 CCKSwingNeedUpdate = 1;
768 }
769
770 if(CCKSwingNeedUpdate)
771 {
772 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
773 }
774 if(priv->OFDM_index != tmpOFDMindex)
775 {
776 priv->OFDM_index = tmpOFDMindex;
777 rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index]);
778 RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n",
779 priv->OFDM_index, OFDMSwingTable[priv->OFDM_index]);
780 }
781 priv->txpower_count = 0;
782}
783
784void dm_txpower_trackingcallback(struct work_struct *work)
785{
786 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
787 struct r8192_priv *priv = container_of(dwork,struct r8192_priv,txpower_tracking_wq);
788
789 if(priv->IC_Cut >= IC_VersionCut_D)
790 dm_TXPowerTrackingCallback_TSSI(priv);
791 else
792 dm_TXPowerTrackingCallback_ThermalMeter(priv);
793}
794
795
796static const txbbgain_struct rtl8192_txbbgain_table[] = {
797 { 12, 0x7f8001fe },
798 { 11, 0x788001e2 },
799 { 10, 0x71c001c7 },
800 { 9, 0x6b8001ae },
801 { 8, 0x65400195 },
802 { 7, 0x5fc0017f },
803 { 6, 0x5a400169 },
804 { 5, 0x55400155 },
805 { 4, 0x50800142 },
806 { 3, 0x4c000130 },
807 { 2, 0x47c0011f },
808 { 1, 0x43c0010f },
809 { 0, 0x40000100 },
810 { -1, 0x3c8000f2 },
811 { -2, 0x390000e4 },
812 { -3, 0x35c000d7 },
813 { -4, 0x32c000cb },
814 { -5, 0x300000c0 },
815 { -6, 0x2d4000b5 },
816 { -7, 0x2ac000ab },
817 { -8, 0x288000a2 },
818 { -9, 0x26000098 },
819 { -10, 0x24000090 },
820 { -11, 0x22000088 },
821 { -12, 0x20000080 },
822 { -13, 0x1a00006c },
823 { -14, 0x1c800072 },
824 { -15, 0x18000060 },
825 { -16, 0x19800066 },
826 { -17, 0x15800056 },
827 { -18, 0x26c0005b },
828 { -19, 0x14400051 },
829 { -20, 0x24400051 },
830 { -21, 0x1300004c },
831 { -22, 0x12000048 },
832 { -23, 0x11000044 },
833 { -24, 0x10000040 },
834};
835
836/*
837 * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
838 * This Table is for CH1~CH13
839 */
840static const ccktxbbgain_struct rtl8192_cck_txbbgain_table[] = {
841 {{ 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 }},
842 {{ 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04 }},
843 {{ 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03 }},
844 {{ 0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03 }},
845 {{ 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 }},
846 {{ 0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03 }},
847 {{ 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 }},
848 {{ 0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03 }},
849 {{ 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02 }},
850 {{ 0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02 }},
851 {{ 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02 }},
852 {{ 0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02 }},
853 {{ 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02 }},
854 {{ 0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02 }},
855 {{ 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02 }},
856 {{ 0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02 }},
857 {{ 0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01 }},
858 {{ 0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02 }},
859 {{ 0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01 }},
860 {{ 0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01 }},
861 {{ 0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01 }},
862 {{ 0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01 }},
863 {{ 0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01 }},
864};
865
866/*
867 * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
868 * This Table is for CH14
869 */
870static const ccktxbbgain_struct rtl8192_cck_txbbgain_ch14_table[] = {
871 {{ 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 }},
872 {{ 0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00 }},
873 {{ 0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00 }},
874 {{ 0x2d, 0x2d, 0x27, 0x17, 0x00, 0x00, 0x00, 0x00 }},
875 {{ 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 }},
876 {{ 0x28, 0x28, 0x22, 0x14, 0x00, 0x00, 0x00, 0x00 }},
877 {{ 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00 }},
878 {{ 0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00 }},
879 {{ 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00 }},
880 {{ 0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00 }},
881 {{ 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00 }},
882 {{ 0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
883 {{ 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
884 {{ 0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00 }},
885 {{ 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00 }},
886 {{ 0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00 }},
887 {{ 0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00 }},
888 {{ 0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00 }},
889 {{ 0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00 }},
890 {{ 0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00 }},
891 {{ 0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00 }},
892 {{ 0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00 }},
893 {{ 0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00 }},
894};
895
896static void dm_InitializeTXPowerTracking_TSSI(struct r8192_priv *priv)
897{
898 priv->txbbgain_table = rtl8192_txbbgain_table;
899 priv->cck_txbbgain_table = rtl8192_cck_txbbgain_table;
900 priv->cck_txbbgain_ch14_table = rtl8192_cck_txbbgain_ch14_table;
901
902 priv->btxpower_tracking = TRUE;
903 priv->txpower_count = 0;
904 priv->btxpower_trackingInit = FALSE;
905
906}
907
908static void dm_InitializeTXPowerTracking_ThermalMeter(struct r8192_priv *priv)
909{
910 // Tx Power tracking by Theremal Meter require Firmware R/W 3-wire. This mechanism
911 // can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w
912 // 3-wire by driver cause RF goes into wrong state.
913 if(priv->ieee80211->FwRWRF)
914 priv->btxpower_tracking = TRUE;
915 else
916 priv->btxpower_tracking = FALSE;
917 priv->txpower_count = 0;
918 priv->btxpower_trackingInit = FALSE;
919}
920
921void dm_initialize_txpower_tracking(struct r8192_priv *priv)
922{
923 if(priv->IC_Cut >= IC_VersionCut_D)
924 dm_InitializeTXPowerTracking_TSSI(priv);
925 else
926 dm_InitializeTXPowerTracking_ThermalMeter(priv);
927}
928
929
930static void dm_CheckTXPowerTracking_TSSI(struct r8192_priv *priv)
931{
932 static u32 tx_power_track_counter = 0;
933 RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__);
934 if(read_nic_byte(priv, 0x11e) ==1)
935 return;
936 if(!priv->btxpower_tracking)
937 return;
938 tx_power_track_counter++;
939
940 if (tx_power_track_counter > 90) {
941 queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0);
942 tx_power_track_counter =0;
943 }
944}
945
946static void dm_CheckTXPowerTracking_ThermalMeter(struct r8192_priv *priv)
947{
948 static u8 TM_Trigger=0;
949
950 if(!priv->btxpower_tracking)
951 return;
952 else
953 {
954 if(priv->txpower_count <= 2)
955 {
956 priv->txpower_count++;
957 return;
958 }
959 }
960
961 if(!TM_Trigger)
962 {
963 //Attention!! You have to wirte all 12bits data to RF, or it may cause RF to crash
964 //actually write reg0x02 bit1=0, then bit1=1.
965 rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
966 rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
967 rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
968 rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
969 TM_Trigger = 1;
970 return;
971 }
972 else {
973 queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0);
974 TM_Trigger = 0;
975 }
976}
977
978static void dm_check_txpower_tracking(struct r8192_priv *priv)
979{
980 if(priv->IC_Cut >= IC_VersionCut_D)
981 dm_CheckTXPowerTracking_TSSI(priv);
982 else
983 dm_CheckTXPowerTracking_ThermalMeter(priv);
984}
985
986
987static void dm_CCKTxPowerAdjust_TSSI(struct r8192_priv *priv, bool bInCH14)
988{
989 u32 TempVal;
990 //Write 0xa22 0xa23
991 TempVal = 0;
992 if(!bInCH14){
993 //Write 0xa22 0xa23
994 TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
995 (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
996
997 rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
998 //Write 0xa24 ~ 0xa27
999 TempVal = 0;
1000 TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
1001 (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
1002 (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+
1003 (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
1004 rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
1005 //Write 0xa28 0xa29
1006 TempVal = 0;
1007 TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
1008 (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
1009
1010 rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
1011 }
1012 else
1013 {
1014 TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
1015 (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
1016
1017 rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
1018 //Write 0xa24 ~ 0xa27
1019 TempVal = 0;
1020 TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
1021 (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
1022 (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+
1023 (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
1024 rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
1025 //Write 0xa28 0xa29
1026 TempVal = 0;
1027 TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
1028 (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
1029
1030 rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
1031 }
1032
1033
1034}
1035
1036static void dm_CCKTxPowerAdjust_ThermalMeter(struct r8192_priv *priv,
1037 bool bInCH14)
1038{
1039 u32 TempVal;
1040
1041 TempVal = 0;
1042 if(!bInCH14)
1043 {
1044 //Write 0xa22 0xa23
1045 TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] +
1046 (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ;
1047 rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
1048 RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1049 rCCK0_TxFilter1, TempVal);
1050 //Write 0xa24 ~ 0xa27
1051 TempVal = 0;
1052 TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][2] +
1053 (CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) +
1054 (CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16 )+
1055 (CCKSwingTable_Ch1_Ch13[priv->CCK_index][5]<<24);
1056 rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
1057 RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1058 rCCK0_TxFilter2, TempVal);
1059 //Write 0xa28 0xa29
1060 TempVal = 0;
1061 TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] +
1062 (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8) ;
1063
1064 rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
1065 RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
1066 rCCK0_DebugPort, TempVal);
1067 }
1068 else
1069 {
1070// priv->CCKTxPowerAdjustCntNotCh14++; //cosa add for debug.
1071 //Write 0xa22 0xa23
1072 TempVal = CCKSwingTable_Ch14[priv->CCK_index][0] +
1073 (CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ;
1074
1075 rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
1076 RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
1077 rCCK0_TxFilter1, TempVal);
1078 //Write 0xa24 ~ 0xa27
1079 TempVal = 0;
1080 TempVal = CCKSwingTable_Ch14[priv->CCK_index][2] +
1081 (CCKSwingTable_Ch14[priv->CCK_index][3]<<8) +
1082 (CCKSwingTable_Ch14[priv->CCK_index][4]<<16 )+
1083 (CCKSwingTable_Ch14[priv->CCK_index][5]<<24);
1084 rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
1085 RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
1086 rCCK0_TxFilter2, TempVal);
1087 //Write 0xa28 0xa29
1088 TempVal = 0;
1089 TempVal = CCKSwingTable_Ch14[priv->CCK_index][6] +
1090 (CCKSwingTable_Ch14[priv->CCK_index][7]<<8) ;
1091
1092 rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
1093 RT_TRACE(COMP_POWER_TRACKING,"CCK chnl 14, reg 0x%x = 0x%x\n",
1094 rCCK0_DebugPort, TempVal);
1095 }
1096}
1097
1098void dm_cck_txpower_adjust(struct r8192_priv *priv, bool binch14)
1099{
1100 if(priv->IC_Cut >= IC_VersionCut_D)
1101 dm_CCKTxPowerAdjust_TSSI(priv, binch14);
1102 else
1103 dm_CCKTxPowerAdjust_ThermalMeter(priv, binch14);
1104}
1105
1106/* Set DIG scheme init value. */
1107static void dm_dig_init(struct r8192_priv *priv)
1108{
1109 /* 2007/10/05 MH Disable DIG scheme now. Not tested. */
1110 dm_digtable.dig_enable_flag = true;
1111 dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI;
1112 dm_digtable.dbg_mode = DM_DBG_OFF; //off=by real rssi value, on=by DM_DigTable.Rssi_val for new dig
1113 dm_digtable.dig_algorithm_switch = 0;
1114
1115 /* 2007/10/04 MH Define init gain threshold. */
1116 dm_digtable.dig_state = DM_STA_DIG_MAX;
1117 dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
1118 dm_digtable.initialgain_lowerbound_state = false;
1119
1120 dm_digtable.rssi_low_thresh = DM_DIG_THRESH_LOW;
1121 dm_digtable.rssi_high_thresh = DM_DIG_THRESH_HIGH;
1122
1123 dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
1124 dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
1125
1126 dm_digtable.rssi_val = 50; //for new dig debug rssi value
1127 dm_digtable.backoff_val = DM_DIG_BACKOFF;
1128 dm_digtable.rx_gain_range_max = DM_DIG_MAX;
1129 if(priv->CustomerID == RT_CID_819x_Netcore)
1130 dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore;
1131 else
1132 dm_digtable.rx_gain_range_min = DM_DIG_MIN;
1133
1134}
1135
1136
1137/*
1138 * Driver must monitor RSSI and notify firmware to change initial
1139 * gain according to different threshold. BB team provide the
1140 * suggested solution.
1141 */
1142static void dm_ctrl_initgain_byrssi(struct r8192_priv *priv)
1143{
1144 if (dm_digtable.dig_enable_flag == false)
1145 return;
1146
1147 if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
1148 dm_ctrl_initgain_byrssi_by_fwfalse_alarm(priv);
1149 else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
1150 dm_ctrl_initgain_byrssi_by_driverrssi(priv);
1151}
1152
1153
1154static void dm_ctrl_initgain_byrssi_by_driverrssi(struct r8192_priv *priv)
1155{
1156 u8 i;
1157 static u8 fw_dig=0;
1158
1159 if (dm_digtable.dig_enable_flag == false)
1160 return;
1161
1162 if(dm_digtable.dig_algorithm_switch) // if swithed algorithm, we have to disable FW Dig.
1163 fw_dig = 0;
1164 if(fw_dig <= 3) // execute several times to make sure the FW Dig is disabled
1165 {// FW DIG Off
1166 for(i=0; i<3; i++)
1167 rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite.
1168 fw_dig++;
1169 dm_digtable.dig_state = DM_STA_DIG_OFF; //fw dig off.
1170 }
1171
1172 if(priv->ieee80211->state == IEEE80211_LINKED)
1173 dm_digtable.cur_connect_state = DIG_CONNECT;
1174 else
1175 dm_digtable.cur_connect_state = DIG_DISCONNECT;
1176
1177 if(dm_digtable.dbg_mode == DM_DBG_OFF)
1178 dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb;
1179
1180 dm_initial_gain(priv);
1181 dm_pd_th(priv);
1182 dm_cs_ratio(priv);
1183 if(dm_digtable.dig_algorithm_switch)
1184 dm_digtable.dig_algorithm_switch = 0;
1185 dm_digtable.pre_connect_state = dm_digtable.cur_connect_state;
1186
1187}
1188
1189static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct r8192_priv *priv)
1190{
1191 static u32 reset_cnt = 0;
1192 u8 i;
1193
1194 if (dm_digtable.dig_enable_flag == false)
1195 return;
1196
1197 if(dm_digtable.dig_algorithm_switch)
1198 {
1199 dm_digtable.dig_state = DM_STA_DIG_MAX;
1200 // Fw DIG On.
1201 for(i=0; i<3; i++)
1202 rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite.
1203 dm_digtable.dig_algorithm_switch = 0;
1204 }
1205
1206 if (priv->ieee80211->state != IEEE80211_LINKED)
1207 return;
1208
1209 // For smooth, we can not change DIG state.
1210 if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) &&
1211 (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh))
1212 {
1213 return;
1214 }
1215
1216 /* 1. When RSSI decrease, We have to judge if it is smaller than a threshold
1217 and then execute below step. */
1218 if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh))
1219 {
1220 /* 2008/02/05 MH When we execute silent reset, the DIG PHY parameters
1221 will be reset to init value. We must prevent the condition. */
1222 if (dm_digtable.dig_state == DM_STA_DIG_OFF &&
1223 (priv->reset_count == reset_cnt))
1224 {
1225 return;
1226 }
1227 else
1228 {
1229 reset_cnt = priv->reset_count;
1230 }
1231
1232 // If DIG is off, DIG high power state must reset.
1233 dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
1234 dm_digtable.dig_state = DM_STA_DIG_OFF;
1235
1236 // 1.1 DIG Off.
1237 rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x8); // Only clear byte 1 and rewrite.
1238
1239 // 1.2 Set initial gain.
1240 write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x17);
1241 write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x17);
1242 write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x17);
1243 write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x17);
1244
1245 // 1.3 Lower PD_TH for OFDM.
1246 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1247 {
1248 /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1249 // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1250 write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x00);
1251 }
1252 else
1253 write_nic_byte(priv, rOFDM0_RxDetector1, 0x42);
1254
1255 // 1.4 Lower CS ratio for CCK.
1256 write_nic_byte(priv, 0xa0a, 0x08);
1257
1258 // 1.5 Higher EDCCA.
1259 //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x325);
1260 return;
1261
1262 }
1263
1264 /* 2. When RSSI increase, We have to judge if it is larger than a threshold
1265 and then execute below step. */
1266 if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) )
1267 {
1268 u8 reset_flag = 0;
1269
1270 if (dm_digtable.dig_state == DM_STA_DIG_ON &&
1271 (priv->reset_count == reset_cnt))
1272 {
1273 dm_ctrl_initgain_byrssi_highpwr(priv);
1274 return;
1275 }
1276 else
1277 {
1278 if (priv->reset_count != reset_cnt)
1279 reset_flag = 1;
1280
1281 reset_cnt = priv->reset_count;
1282 }
1283
1284 dm_digtable.dig_state = DM_STA_DIG_ON;
1285
1286 // 2.1 Set initial gain.
1287 // 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment.
1288 if (reset_flag == 1)
1289 {
1290 write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x2c);
1291 write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x2c);
1292 write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x2c);
1293 write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x2c);
1294 }
1295 else
1296 {
1297 write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x20);
1298 write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x20);
1299 write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x20);
1300 write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x20);
1301 }
1302
1303 // 2.2 Higher PD_TH for OFDM.
1304 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1305 {
1306 /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1307 // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1308 write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
1309 }
1310 else
1311 write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
1312
1313 // 2.3 Higher CS ratio for CCK.
1314 write_nic_byte(priv, 0xa0a, 0xcd);
1315
1316 // 2.4 Lower EDCCA.
1317 /* 2008/01/11 MH 90/92 series are the same. */
1318 //PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x346);
1319
1320 // 2.5 DIG On.
1321 rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x1); // Only clear byte 1 and rewrite.
1322
1323 }
1324
1325 dm_ctrl_initgain_byrssi_highpwr(priv);
1326
1327}
1328
1329static void dm_ctrl_initgain_byrssi_highpwr(struct r8192_priv *priv)
1330{
1331 static u32 reset_cnt_highpwr = 0;
1332
1333 // For smooth, we can not change high power DIG state in the range.
1334 if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) &&
1335 (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh))
1336 {
1337 return;
1338 }
1339
1340 /* 3. When RSSI >75% or <70%, it is a high power issue. We have to judge if
1341 it is larger than a threshold and then execute below step. */
1342 // 2008/02/05 MH SD3-Jerry Modify PD_TH for high power issue.
1343 if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh)
1344 {
1345 if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON &&
1346 (priv->reset_count == reset_cnt_highpwr))
1347 return;
1348 else
1349 dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
1350
1351 // 3.1 Higher PD_TH for OFDM for high power state.
1352 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1353 {
1354 write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x10);
1355 }
1356 else
1357 write_nic_byte(priv, rOFDM0_RxDetector1, 0x43);
1358 }
1359 else
1360 {
1361 if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF&&
1362 (priv->reset_count == reset_cnt_highpwr))
1363 return;
1364 else
1365 dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF;
1366
1367 if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh &&
1368 priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh)
1369 {
1370 // 3.2 Recover PD_TH for OFDM for normal power region.
1371 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1372 {
1373 write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
1374 }
1375 else
1376 write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
1377 }
1378 }
1379
1380 reset_cnt_highpwr = priv->reset_count;
1381
1382}
1383
1384
1385static void dm_initial_gain(struct r8192_priv *priv)
1386{
1387 u8 initial_gain=0;
1388 static u8 initialized=0, force_write=0;
1389 static u32 reset_cnt=0;
1390
1391 if(dm_digtable.dig_algorithm_switch)
1392 {
1393 initialized = 0;
1394 reset_cnt = 0;
1395 }
1396
1397 if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state)
1398 {
1399 if(dm_digtable.cur_connect_state == DIG_CONNECT)
1400 {
1401 if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max)
1402 dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max;
1403 else if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
1404 dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min;
1405 else
1406 dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val;
1407 }
1408 else //current state is disconnected
1409 {
1410 if(dm_digtable.cur_ig_value == 0)
1411 dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
1412 else
1413 dm_digtable.cur_ig_value = dm_digtable.pre_ig_value;
1414 }
1415 }
1416 else // disconnected -> connected or connected -> disconnected
1417 {
1418 dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
1419 dm_digtable.pre_ig_value = 0;
1420 }
1421
1422 // if silent reset happened, we should rewrite the values back
1423 if(priv->reset_count != reset_cnt)
1424 {
1425 force_write = 1;
1426 reset_cnt = priv->reset_count;
1427 }
1428
1429 if(dm_digtable.pre_ig_value != read_nic_byte(priv, rOFDM0_XAAGCCore1))
1430 force_write = 1;
1431
1432 {
1433 if((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value)
1434 || !initialized || force_write)
1435 {
1436 initial_gain = (u8)dm_digtable.cur_ig_value;
1437 // Set initial gain.
1438 write_nic_byte(priv, rOFDM0_XAAGCCore1, initial_gain);
1439 write_nic_byte(priv, rOFDM0_XBAGCCore1, initial_gain);
1440 write_nic_byte(priv, rOFDM0_XCAGCCore1, initial_gain);
1441 write_nic_byte(priv, rOFDM0_XDAGCCore1, initial_gain);
1442 dm_digtable.pre_ig_value = dm_digtable.cur_ig_value;
1443 initialized = 1;
1444 force_write = 0;
1445 }
1446 }
1447}
1448
1449static void dm_pd_th(struct r8192_priv *priv)
1450{
1451 static u8 initialized=0, force_write=0;
1452 static u32 reset_cnt = 0;
1453
1454 if(dm_digtable.dig_algorithm_switch)
1455 {
1456 initialized = 0;
1457 reset_cnt = 0;
1458 }
1459
1460 if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state)
1461 {
1462 if(dm_digtable.cur_connect_state == DIG_CONNECT)
1463 {
1464 if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh)
1465 dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER;
1466 else if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh))
1467 dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
1468 else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) &&
1469 (dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh))
1470 dm_digtable.curpd_thstate = DIG_PD_AT_NORMAL_POWER;
1471 else
1472 dm_digtable.curpd_thstate = dm_digtable.prepd_thstate;
1473 }
1474 else
1475 {
1476 dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
1477 }
1478 }
1479 else // disconnected -> connected or connected -> disconnected
1480 {
1481 dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER;
1482 }
1483
1484 // if silent reset happened, we should rewrite the values back
1485 if(priv->reset_count != reset_cnt)
1486 {
1487 force_write = 1;
1488 reset_cnt = priv->reset_count;
1489 }
1490
1491 {
1492 if((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) ||
1493 (initialized<=3) || force_write)
1494 {
1495 if(dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER)
1496 {
1497 // Lower PD_TH for OFDM.
1498 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1499 {
1500 /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1501 // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1502 write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x00);
1503 }
1504 else
1505 write_nic_byte(priv, rOFDM0_RxDetector1, 0x42);
1506 }
1507 else if(dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER)
1508 {
1509 // Higher PD_TH for OFDM.
1510 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1511 {
1512 /* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
1513 // 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
1514 write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
1515 }
1516 else
1517 write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
1518 }
1519 else if(dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER)
1520 {
1521 // Higher PD_TH for OFDM for high power state.
1522 if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
1523 {
1524 write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x10);
1525 }
1526 else
1527 write_nic_byte(priv, rOFDM0_RxDetector1, 0x43);
1528 }
1529 dm_digtable.prepd_thstate = dm_digtable.curpd_thstate;
1530 if(initialized <= 3)
1531 initialized++;
1532 force_write = 0;
1533 }
1534 }
1535}
1536
1537static void dm_cs_ratio(struct r8192_priv *priv)
1538{
1539 static u8 initialized=0,force_write=0;
1540 static u32 reset_cnt = 0;
1541
1542 if(dm_digtable.dig_algorithm_switch)
1543 {
1544 initialized = 0;
1545 reset_cnt = 0;
1546 }
1547
1548 if(dm_digtable.pre_connect_state == dm_digtable.cur_connect_state)
1549 {
1550 if(dm_digtable.cur_connect_state == DIG_CONNECT)
1551 {
1552 if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh))
1553 dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
1554 else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) )
1555 dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER;
1556 else
1557 dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state;
1558 }
1559 else
1560 {
1561 dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
1562 }
1563 }
1564 else // disconnected -> connected or connected -> disconnected
1565 {
1566 dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER;
1567 }
1568
1569 // if silent reset happened, we should rewrite the values back
1570 if(priv->reset_count != reset_cnt)
1571 {
1572 force_write = 1;
1573 reset_cnt = priv->reset_count;
1574 }
1575
1576
1577 if((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) ||
1578 !initialized || force_write)
1579 {
1580 if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER)
1581 {
1582 // Lower CS ratio for CCK.
1583 write_nic_byte(priv, 0xa0a, 0x08);
1584 }
1585 else if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER)
1586 {
1587 // Higher CS ratio for CCK.
1588 write_nic_byte(priv, 0xa0a, 0xcd);
1589 }
1590 dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state;
1591 initialized = 1;
1592 force_write = 0;
1593 }
1594}
1595
1596void dm_init_edca_turbo(struct r8192_priv *priv)
1597{
1598
1599 priv->bcurrent_turbo_EDCA = false;
1600 priv->ieee80211->bis_any_nonbepkts = false;
1601 priv->bis_cur_rdlstate = false;
1602}
1603
1604static void dm_check_edca_turbo(struct r8192_priv *priv)
1605{
1606 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
1607 //PSTA_QOS pStaQos = pMgntInfo->pStaQos;
1608
1609 // Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.
1610 static unsigned long lastTxOkCnt = 0;
1611 static unsigned long lastRxOkCnt = 0;
1612 unsigned long curTxOkCnt = 0;
1613 unsigned long curRxOkCnt = 0;
1614
1615 //
1616 // Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters
1617 // should follow the settings from QAP. By Bruce, 2007-12-07.
1618 //
1619 if(priv->ieee80211->state != IEEE80211_LINKED)
1620 goto dm_CheckEdcaTurbo_EXIT;
1621 // We do not turn on EDCA turbo mode for some AP that has IOT issue
1622 if(priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO)
1623 goto dm_CheckEdcaTurbo_EXIT;
1624
1625 // Check the status for current condition.
1626 if(!priv->ieee80211->bis_any_nonbepkts)
1627 {
1628 curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
1629 curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
1630 // For RT-AP, we needs to turn it on when Rx>Tx
1631 if(curRxOkCnt > 4*curTxOkCnt)
1632 {
1633 if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
1634 {
1635 write_nic_dword(priv, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]);
1636 priv->bis_cur_rdlstate = true;
1637 }
1638 }
1639 else
1640 {
1641 if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
1642 {
1643 write_nic_dword(priv, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]);
1644 priv->bis_cur_rdlstate = false;
1645 }
1646
1647 }
1648
1649 priv->bcurrent_turbo_EDCA = true;
1650 }
1651 else
1652 {
1653 //
1654 // Turn Off EDCA turbo here.
1655 // Restore original EDCA according to the declaration of AP.
1656 //
1657 if(priv->bcurrent_turbo_EDCA)
1658 {
1659
1660 {
1661 u8 u1bAIFS;
1662 u32 u4bAcParam;
1663 struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
1664 u8 mode = priv->ieee80211->mode;
1665
1666 // For Each time updating EDCA parameter, reset EDCA turbo mode status.
1667 dm_init_edca_turbo(priv);
1668 u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
1669 u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
1670 (((u32)(qos_parameters->cw_max[0]))<< AC_PARAM_ECW_MAX_OFFSET)|
1671 (((u32)(qos_parameters->cw_min[0]))<< AC_PARAM_ECW_MIN_OFFSET)|
1672 ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
1673 printk("===>u4bAcParam:%x, ", u4bAcParam);
1674 //write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
1675 write_nic_dword(priv, EDCAPARA_BE, u4bAcParam);
1676
1677 // Check ACM bit.
1678 // If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13.
1679 {
1680 // TODO: Modified this part and try to set acm control in only 1 IO processing!!
1681
1682 PACI_AIFSN pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]);
1683 u8 AcmCtrl = read_nic_byte(priv, AcmHwCtrl );
1684 if( pAciAifsn->f.ACM )
1685 { // ACM bit is 1.
1686 AcmCtrl |= AcmHw_BeqEn;
1687 }
1688 else
1689 { // ACM bit is 0.
1690 AcmCtrl &= (~AcmHw_BeqEn);
1691 }
1692
1693 RT_TRACE( COMP_QOS,"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl ) ;
1694 write_nic_byte(priv, AcmHwCtrl, AcmCtrl );
1695 }
1696 }
1697 priv->bcurrent_turbo_EDCA = false;
1698 }
1699 }
1700
1701
1702dm_CheckEdcaTurbo_EXIT:
1703 // Set variables for next time.
1704 priv->ieee80211->bis_any_nonbepkts = false;
1705 lastTxOkCnt = priv->stats.txbytesunicast;
1706 lastRxOkCnt = priv->stats.rxbytesunicast;
1707}
1708
1709static void dm_init_ctstoself(struct r8192_priv *priv)
1710{
1711 priv->ieee80211->bCTSToSelfEnable = TRUE;
1712 priv->ieee80211->CTSToSelfTH = CTSToSelfTHVal;
1713}
1714
1715static void dm_ctstoself(struct r8192_priv *priv)
1716{
1717 PRT_HIGH_THROUGHPUT pHTInfo = priv->ieee80211->pHTInfo;
1718 static unsigned long lastTxOkCnt = 0;
1719 static unsigned long lastRxOkCnt = 0;
1720 unsigned long curTxOkCnt = 0;
1721 unsigned long curRxOkCnt = 0;
1722
1723 if(priv->ieee80211->bCTSToSelfEnable != TRUE)
1724 {
1725 pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
1726 return;
1727 }
1728 /*
1729 1. Uplink
1730 2. Linksys350/Linksys300N
1731 3. <50 disable, >55 enable
1732 */
1733
1734 if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM)
1735 {
1736 curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
1737 curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
1738 if(curRxOkCnt > 4*curTxOkCnt) //downlink, disable CTS to self
1739 {
1740 pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
1741 }
1742 else //uplink
1743 {
1744 pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
1745 }
1746
1747 lastTxOkCnt = priv->stats.txbytesunicast;
1748 lastRxOkCnt = priv->stats.rxbytesunicast;
1749 }
1750}
1751
1752
1753
1754/* Copy 8187B template for 9xseries */
1755static void dm_check_rfctrl_gpio(struct r8192_priv *priv)
1756{
1757
1758 // Walk around for DTM test, we will not enable HW - radio on/off because r/w
1759 // page 1 register before Lextra bus is enabled cause system fails when resuming
1760 // from S4. 20080218, Emily
1761
1762 // Stop to execute workitem to prevent S3/S4 bug.
1763 queue_delayed_work(priv->priv_wq,&priv->gpio_change_rf_wq,0);
1764}
1765
1766/* PCI will not support workitem call back HW radio on-off control. */
1767void dm_gpio_change_rf_callback(struct work_struct *work)
1768{
1769 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
1770 struct r8192_priv *priv = container_of(dwork,struct r8192_priv,gpio_change_rf_wq);
1771 u8 tmp1byte;
1772 RT_RF_POWER_STATE eRfPowerStateToSet;
1773 bool bActuallySet = false;
1774
1775 if (!priv->up) {
1776 RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF),"dm_gpio_change_rf_callback(): Callback function breaks out!!\n");
1777 } else {
1778 // 0x108 GPIO input register is read only
1779 //set 0x108 B1= 1: RF-ON; 0: RF-OFF.
1780 tmp1byte = read_nic_byte(priv, GPI);
1781
1782 eRfPowerStateToSet = (tmp1byte&BIT1) ? eRfOn : eRfOff;
1783
1784 if (priv->bHwRadioOff && (eRfPowerStateToSet == eRfOn)) {
1785 RT_TRACE(COMP_RF, "gpiochangeRF - HW Radio ON\n");
1786
1787 priv->bHwRadioOff = false;
1788 bActuallySet = true;
1789 } else if ((!priv->bHwRadioOff) && (eRfPowerStateToSet == eRfOff)) {
1790 RT_TRACE(COMP_RF, "gpiochangeRF - HW Radio OFF\n");
1791 priv->bHwRadioOff = true;
1792 bActuallySet = true;
1793 }
1794
1795 if (bActuallySet) {
1796 priv->bHwRfOffAction = 1;
1797 MgntActSet_RF_State(priv, eRfPowerStateToSet, RF_CHANGE_BY_HW);
1798 //DrvIFIndicateCurrentPhyStatus(pAdapter);
1799 } else {
1800 msleep(2000);
1801 }
1802 }
1803}
1804
1805/* Check if Current RF RX path is enabled */
1806void dm_rf_pathcheck_workitemcallback(struct work_struct *work)
1807{
1808 struct delayed_work *dwork = container_of(work,struct delayed_work,work);
1809 struct r8192_priv *priv = container_of(dwork,struct r8192_priv,rfpath_check_wq);
1810 u8 rfpath = 0, i;
1811
1812
1813 /* 2008/01/30 MH After discussing with SD3 Jerry, 0xc04/0xd04 register will
1814 always be the same. We only read 0xc04 now. */
1815 rfpath = read_nic_byte(priv, 0xc04);
1816
1817 // Check Bit 0-3, it means if RF A-D is enabled.
1818 for (i = 0; i < RF90_PATH_MAX; i++)
1819 {
1820 if (rfpath & (0x01<<i))
1821 priv->brfpath_rxenable[i] = 1;
1822 else
1823 priv->brfpath_rxenable[i] = 0;
1824 }
1825 if(!DM_RxPathSelTable.Enable)
1826 return;
1827
1828 dm_rxpath_sel_byrssi(priv);
1829}
1830
1831static void dm_init_rxpath_selection(struct r8192_priv *priv)
1832{
1833 u8 i;
1834
1835 DM_RxPathSelTable.Enable = 1; //default enabled
1836 DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low;
1837 DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH;
1838 if(priv->CustomerID == RT_CID_819x_Netcore)
1839 DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;
1840 else
1841 DM_RxPathSelTable.cck_method = CCK_Rx_Version_1;
1842 DM_RxPathSelTable.DbgMode = DM_DBG_OFF;
1843 DM_RxPathSelTable.disabledRF = 0;
1844 for(i=0; i<4; i++)
1845 {
1846 DM_RxPathSelTable.rf_rssi[i] = 50;
1847 DM_RxPathSelTable.cck_pwdb_sta[i] = -64;
1848 DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
1849 }
1850}
1851
1852static void dm_rxpath_sel_byrssi(struct r8192_priv *priv)
1853{
1854 u8 i, max_rssi_index=0, min_rssi_index=0, sec_rssi_index=0, rf_num=0;
1855 u8 tmp_max_rssi=0, tmp_min_rssi=0, tmp_sec_rssi=0;
1856 u8 cck_default_Rx=0x2; //RF-C
1857 u8 cck_optional_Rx=0x3;//RF-D
1858 long tmp_cck_max_pwdb=0, tmp_cck_min_pwdb=0, tmp_cck_sec_pwdb=0;
1859 u8 cck_rx_ver2_max_index=0, cck_rx_ver2_min_index=0, cck_rx_ver2_sec_index=0;
1860 u8 cur_rf_rssi;
1861 long cur_cck_pwdb;
1862 static u8 disabled_rf_cnt=0, cck_Rx_Path_initialized=0;
1863 u8 update_cck_rx_path;
1864
1865 if(priv->rf_type != RF_2T4R)
1866 return;
1867
1868 if(!cck_Rx_Path_initialized)
1869 {
1870 DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(priv, 0xa07)&0xf);
1871 cck_Rx_Path_initialized = 1;
1872 }
1873
1874 DM_RxPathSelTable.disabledRF = 0xf;
1875 DM_RxPathSelTable.disabledRF &=~ (read_nic_byte(priv, 0xc04));
1876
1877 if(priv->ieee80211->mode == WIRELESS_MODE_B)
1878 {
1879 DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; //pure B mode, fixed cck version2
1880 }
1881
1882 //decide max/sec/min rssi index
1883 for (i=0; i<RF90_PATH_MAX; i++)
1884 {
1885 if(!DM_RxPathSelTable.DbgMode)
1886 DM_RxPathSelTable.rf_rssi[i] = priv->stats.rx_rssi_percentage[i];
1887
1888 if(priv->brfpath_rxenable[i])
1889 {
1890 rf_num++;
1891 cur_rf_rssi = DM_RxPathSelTable.rf_rssi[i];
1892
1893 if(rf_num == 1) // find first enabled rf path and the rssi values
1894 { //initialize, set all rssi index to the same one
1895 max_rssi_index = min_rssi_index = sec_rssi_index = i;
1896 tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi;
1897 }
1898 else if(rf_num == 2)
1899 { // we pick up the max index first, and let sec and min to be the same one
1900 if(cur_rf_rssi >= tmp_max_rssi)
1901 {
1902 tmp_max_rssi = cur_rf_rssi;
1903 max_rssi_index = i;
1904 }
1905 else
1906 {
1907 tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi;
1908 sec_rssi_index = min_rssi_index = i;
1909 }
1910 }
1911 else
1912 {
1913 if(cur_rf_rssi > tmp_max_rssi)
1914 {
1915 tmp_sec_rssi = tmp_max_rssi;
1916 sec_rssi_index = max_rssi_index;
1917 tmp_max_rssi = cur_rf_rssi;
1918 max_rssi_index = i;
1919 }
1920 else if(cur_rf_rssi == tmp_max_rssi)
1921 { // let sec and min point to the different index
1922 tmp_sec_rssi = cur_rf_rssi;
1923 sec_rssi_index = i;
1924 }
1925 else if((cur_rf_rssi < tmp_max_rssi) &&(cur_rf_rssi > tmp_sec_rssi))
1926 {
1927 tmp_sec_rssi = cur_rf_rssi;
1928 sec_rssi_index = i;
1929 }
1930 else if(cur_rf_rssi == tmp_sec_rssi)
1931 {
1932 if(tmp_sec_rssi == tmp_min_rssi)
1933 { // let sec and min point to the different index
1934 tmp_sec_rssi = cur_rf_rssi;
1935 sec_rssi_index = i;
1936 }
1937 else
1938 {
1939 // This case we don't need to set any index
1940 }
1941 }
1942 else if((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi))
1943 {
1944 // This case we don't need to set any index
1945 }
1946 else if(cur_rf_rssi == tmp_min_rssi)
1947 {
1948 if(tmp_sec_rssi == tmp_min_rssi)
1949 { // let sec and min point to the different index
1950 tmp_min_rssi = cur_rf_rssi;
1951 min_rssi_index = i;
1952 }
1953 else
1954 {
1955 // This case we don't need to set any index
1956 }
1957 }
1958 else if(cur_rf_rssi < tmp_min_rssi)
1959 {
1960 tmp_min_rssi = cur_rf_rssi;
1961 min_rssi_index = i;
1962 }
1963 }
1964 }
1965 }
1966
1967 rf_num = 0;
1968 // decide max/sec/min cck pwdb index
1969 if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2)
1970 {
1971 for (i=0; i<RF90_PATH_MAX; i++)
1972 {
1973 if(priv->brfpath_rxenable[i])
1974 {
1975 rf_num++;
1976 cur_cck_pwdb = DM_RxPathSelTable.cck_pwdb_sta[i];
1977
1978 if(rf_num == 1) // find first enabled rf path and the rssi values
1979 { //initialize, set all rssi index to the same one
1980 cck_rx_ver2_max_index = cck_rx_ver2_min_index = cck_rx_ver2_sec_index = i;
1981 tmp_cck_max_pwdb = tmp_cck_min_pwdb = tmp_cck_sec_pwdb = cur_cck_pwdb;
1982 }
1983 else if(rf_num == 2)
1984 { // we pick up the max index first, and let sec and min to be the same one
1985 if(cur_cck_pwdb >= tmp_cck_max_pwdb)
1986 {
1987 tmp_cck_max_pwdb = cur_cck_pwdb;
1988 cck_rx_ver2_max_index = i;
1989 }
1990 else
1991 {
1992 tmp_cck_sec_pwdb = tmp_cck_min_pwdb = cur_cck_pwdb;
1993 cck_rx_ver2_sec_index = cck_rx_ver2_min_index = i;
1994 }
1995 }
1996 else
1997 {
1998 if(cur_cck_pwdb > tmp_cck_max_pwdb)
1999 {
2000 tmp_cck_sec_pwdb = tmp_cck_max_pwdb;
2001 cck_rx_ver2_sec_index = cck_rx_ver2_max_index;
2002 tmp_cck_max_pwdb = cur_cck_pwdb;
2003 cck_rx_ver2_max_index = i;
2004 }
2005 else if(cur_cck_pwdb == tmp_cck_max_pwdb)
2006 { // let sec and min point to the different index
2007 tmp_cck_sec_pwdb = cur_cck_pwdb;
2008 cck_rx_ver2_sec_index = i;
2009 }
2010 else if((cur_cck_pwdb < tmp_cck_max_pwdb) &&(cur_cck_pwdb > tmp_cck_sec_pwdb))
2011 {
2012 tmp_cck_sec_pwdb = cur_cck_pwdb;
2013 cck_rx_ver2_sec_index = i;
2014 }
2015 else if(cur_cck_pwdb == tmp_cck_sec_pwdb)
2016 {
2017 if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb)
2018 { // let sec and min point to the different index
2019 tmp_cck_sec_pwdb = cur_cck_pwdb;
2020 cck_rx_ver2_sec_index = i;
2021 }
2022 else
2023 {
2024 // This case we don't need to set any index
2025 }
2026 }
2027 else if((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb))
2028 {
2029 // This case we don't need to set any index
2030 }
2031 else if(cur_cck_pwdb == tmp_cck_min_pwdb)
2032 {
2033 if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb)
2034 { // let sec and min point to the different index
2035 tmp_cck_min_pwdb = cur_cck_pwdb;
2036 cck_rx_ver2_min_index = i;
2037 }
2038 else
2039 {
2040 // This case we don't need to set any index
2041 }
2042 }
2043 else if(cur_cck_pwdb < tmp_cck_min_pwdb)
2044 {
2045 tmp_cck_min_pwdb = cur_cck_pwdb;
2046 cck_rx_ver2_min_index = i;
2047 }
2048 }
2049
2050 }
2051 }
2052 }
2053
2054
2055 // Set CCK Rx path
2056 // reg0xA07[3:2]=cck default rx path, reg0xa07[1:0]=cck optional rx path.
2057 update_cck_rx_path = 0;
2058 if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2)
2059 {
2060 cck_default_Rx = cck_rx_ver2_max_index;
2061 cck_optional_Rx = cck_rx_ver2_sec_index;
2062 if(tmp_cck_max_pwdb != -64)
2063 update_cck_rx_path = 1;
2064 }
2065
2066 if(tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2)
2067 {
2068 if((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH)
2069 {
2070 //record the enabled rssi threshold
2071 DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5;
2072 //disable the BB Rx path, OFDM
2073 rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0x1<<min_rssi_index, 0x0); // 0xc04[3:0]
2074 rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0x1<<min_rssi_index, 0x0); // 0xd04[3:0]
2075 disabled_rf_cnt++;
2076 }
2077 if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_1)
2078 {
2079 cck_default_Rx = max_rssi_index;
2080 cck_optional_Rx = sec_rssi_index;
2081 if(tmp_max_rssi)
2082 update_cck_rx_path = 1;
2083 }
2084 }
2085
2086 if(update_cck_rx_path)
2087 {
2088 DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2)|(cck_optional_Rx);
2089 rtl8192_setBBreg(priv, rCCK0_AFESetting, 0x0f000000, DM_RxPathSelTable.cck_Rx_path);
2090 }
2091
2092 if(DM_RxPathSelTable.disabledRF)
2093 {
2094 for(i=0; i<4; i++)
2095 {
2096 if((DM_RxPathSelTable.disabledRF>>i) & 0x1) //disabled rf
2097 {
2098 if(tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i])
2099 {
2100 //enable the BB Rx path
2101 rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0x1<<i, 0x1); // 0xc04[3:0]
2102 rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0x1<<i, 0x1); // 0xd04[3:0]
2103 DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
2104 disabled_rf_cnt--;
2105 }
2106 }
2107 }
2108 }
2109}
2110
2111/*
2112 * Call a workitem to check current RXRF path and Rx Path selection by RSSI.
2113 */
2114static void dm_check_rx_path_selection(struct r8192_priv *priv)
2115{
2116 queue_delayed_work(priv->priv_wq,&priv->rfpath_check_wq,0);
2117}
2118
2119static void dm_init_fsync(struct r8192_priv *priv)
2120{
2121 priv->ieee80211->fsync_time_interval = 500;
2122 priv->ieee80211->fsync_rate_bitmap = 0x0f000800;
2123 priv->ieee80211->fsync_rssi_threshold = 30;
2124 priv->ieee80211->bfsync_enable = false;
2125 priv->ieee80211->fsync_multiple_timeinterval = 3;
2126 priv->ieee80211->fsync_firstdiff_ratethreshold= 100;
2127 priv->ieee80211->fsync_seconddiff_ratethreshold= 200;
2128 priv->ieee80211->fsync_state = Default_Fsync;
2129 priv->framesyncMonitor = 1; // current default 0xc38 monitor on
2130
2131 init_timer(&priv->fsync_timer);
2132 priv->fsync_timer.data = (unsigned long)priv;
2133 priv->fsync_timer.function = dm_fsync_timer_callback;
2134}
2135
2136
2137static void dm_deInit_fsync(struct r8192_priv *priv)
2138{
2139 del_timer_sync(&priv->fsync_timer);
2140}
2141
2142static void dm_fsync_timer_callback(unsigned long data)
2143{
2144 struct r8192_priv *priv = (struct r8192_priv *)data;
2145 u32 rate_index, rate_count = 0, rate_count_diff=0;
2146 bool bSwitchFromCountDiff = false;
2147 bool bDoubleTimeInterval = false;
2148
2149 if( priv->ieee80211->state == IEEE80211_LINKED &&
2150 priv->ieee80211->bfsync_enable &&
2151 (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC))
2152 {
2153 // Count rate 54, MCS [7], [12, 13, 14, 15]
2154 u32 rate_bitmap;
2155 for(rate_index = 0; rate_index <= 27; rate_index++)
2156 {
2157 rate_bitmap = 1 << rate_index;
2158 if(priv->ieee80211->fsync_rate_bitmap & rate_bitmap)
2159 rate_count+= priv->stats.received_rate_histogram[1][rate_index];
2160 }
2161
2162 if(rate_count < priv->rate_record)
2163 rate_count_diff = 0xffffffff - rate_count + priv->rate_record;
2164 else
2165 rate_count_diff = rate_count - priv->rate_record;
2166 if(rate_count_diff < priv->rateCountDiffRecord)
2167 {
2168
2169 u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff;
2170 // Contiune count
2171 if(DiffNum >= priv->ieee80211->fsync_seconddiff_ratethreshold)
2172 priv->ContiuneDiffCount++;
2173 else
2174 priv->ContiuneDiffCount = 0;
2175
2176 // Contiune count over
2177 if(priv->ContiuneDiffCount >=2)
2178 {
2179 bSwitchFromCountDiff = true;
2180 priv->ContiuneDiffCount = 0;
2181 }
2182 }
2183 else
2184 {
2185 // Stop contiune count
2186 priv->ContiuneDiffCount = 0;
2187 }
2188
2189 //If Count diff <= FsyncRateCountThreshold
2190 if(rate_count_diff <= priv->ieee80211->fsync_firstdiff_ratethreshold)
2191 {
2192 bSwitchFromCountDiff = true;
2193 priv->ContiuneDiffCount = 0;
2194 }
2195 priv->rate_record = rate_count;
2196 priv->rateCountDiffRecord = rate_count_diff;
2197 RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
2198 // if we never receive those mcs rate and rssi > 30 % then switch fsyn
2199 if(priv->undecorated_smoothed_pwdb > priv->ieee80211->fsync_rssi_threshold && bSwitchFromCountDiff)
2200 {
2201 bDoubleTimeInterval = true;
2202 priv->bswitch_fsync = !priv->bswitch_fsync;
2203 if(priv->bswitch_fsync)
2204 {
2205 write_nic_byte(priv,0xC36, 0x1c);
2206 write_nic_byte(priv, 0xC3e, 0x90);
2207 }
2208 else
2209 {
2210 write_nic_byte(priv, 0xC36, 0x5c);
2211 write_nic_byte(priv, 0xC3e, 0x96);
2212 }
2213 }
2214 else if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->fsync_rssi_threshold)
2215 {
2216 if(priv->bswitch_fsync)
2217 {
2218 priv->bswitch_fsync = false;
2219 write_nic_byte(priv, 0xC36, 0x5c);
2220 write_nic_byte(priv, 0xC3e, 0x96);
2221 }
2222 }
2223 if(bDoubleTimeInterval){
2224 if(timer_pending(&priv->fsync_timer))
2225 del_timer_sync(&priv->fsync_timer);
2226 priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval*priv->ieee80211->fsync_multiple_timeinterval);
2227 add_timer(&priv->fsync_timer);
2228 }
2229 else{
2230 if(timer_pending(&priv->fsync_timer))
2231 del_timer_sync(&priv->fsync_timer);
2232 priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
2233 add_timer(&priv->fsync_timer);
2234 }
2235 }
2236 else
2237 {
2238 // Let Register return to default value;
2239 if(priv->bswitch_fsync)
2240 {
2241 priv->bswitch_fsync = false;
2242 write_nic_byte(priv, 0xC36, 0x5c);
2243 write_nic_byte(priv, 0xC3e, 0x96);
2244 }
2245 priv->ContiuneDiffCount = 0;
2246 write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
2247 }
2248 RT_TRACE(COMP_HALDM, "ContiuneDiffCount %d\n", priv->ContiuneDiffCount);
2249 RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
2250}
2251
2252static void dm_StartHWFsync(struct r8192_priv *priv)
2253{
2254 RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__);
2255 write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c12cf);
2256 write_nic_byte(priv, 0xc3b, 0x41);
2257}
2258
2259static void dm_EndSWFsync(struct r8192_priv *priv)
2260{
2261 RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__);
2262 del_timer_sync(&(priv->fsync_timer));
2263
2264 // Let Register return to default value;
2265 if(priv->bswitch_fsync)
2266 {
2267 priv->bswitch_fsync = false;
2268
2269 write_nic_byte(priv, 0xC36, 0x40);
2270
2271 write_nic_byte(priv, 0xC3e, 0x96);
2272 }
2273
2274 priv->ContiuneDiffCount = 0;
2275
2276 write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
2277}
2278
2279static void dm_StartSWFsync(struct r8192_priv *priv)
2280{
2281 u32 rateIndex;
2282 u32 rateBitmap;
2283
2284 RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__);
2285 // Initial rate record to zero, start to record.
2286 priv->rate_record = 0;
2287 // Initial contiune diff count to zero, start to record.
2288 priv->ContiuneDiffCount = 0;
2289 priv->rateCountDiffRecord = 0;
2290 priv->bswitch_fsync = false;
2291
2292 if(priv->ieee80211->mode == WIRELESS_MODE_N_24G)
2293 {
2294 priv->ieee80211->fsync_firstdiff_ratethreshold= 600;
2295 priv->ieee80211->fsync_seconddiff_ratethreshold = 0xffff;
2296 }
2297 else
2298 {
2299 priv->ieee80211->fsync_firstdiff_ratethreshold= 200;
2300 priv->ieee80211->fsync_seconddiff_ratethreshold = 200;
2301 }
2302 for(rateIndex = 0; rateIndex <= 27; rateIndex++)
2303 {
2304 rateBitmap = 1 << rateIndex;
2305 if(priv->ieee80211->fsync_rate_bitmap & rateBitmap)
2306 priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex];
2307 }
2308 if(timer_pending(&priv->fsync_timer))
2309 del_timer_sync(&priv->fsync_timer);
2310 priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
2311 add_timer(&priv->fsync_timer);
2312
2313 write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c12cd);
2314}
2315
2316static void dm_EndHWFsync(struct r8192_priv *priv)
2317{
2318 RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__);
2319 write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
2320 write_nic_byte(priv, 0xc3b, 0x49);
2321}
2322
2323static void dm_check_fsync(struct r8192_priv *priv)
2324{
2325#define RegC38_Default 0
2326#define RegC38_NonFsync_Other_AP 1
2327#define RegC38_Fsync_AP_BCM 2
2328 //u32 framesyncC34;
2329 static u8 reg_c38_State=RegC38_Default;
2330 static u32 reset_cnt=0;
2331
2332 RT_TRACE(COMP_HALDM, "RSSI %d TimeInterval %d MultipleTimeInterval %d\n", priv->ieee80211->fsync_rssi_threshold, priv->ieee80211->fsync_time_interval, priv->ieee80211->fsync_multiple_timeinterval);
2333 RT_TRACE(COMP_HALDM, "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n", priv->ieee80211->fsync_rate_bitmap, priv->ieee80211->fsync_firstdiff_ratethreshold, priv->ieee80211->fsync_seconddiff_ratethreshold);
2334
2335 if( priv->ieee80211->state == IEEE80211_LINKED &&
2336 (priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC))
2337 {
2338 if(priv->ieee80211->bfsync_enable == 0)
2339 {
2340 switch(priv->ieee80211->fsync_state)
2341 {
2342 case Default_Fsync:
2343 dm_StartHWFsync(priv);
2344 priv->ieee80211->fsync_state = HW_Fsync;
2345 break;
2346 case SW_Fsync:
2347 dm_EndSWFsync(priv);
2348 dm_StartHWFsync(priv);
2349 priv->ieee80211->fsync_state = HW_Fsync;
2350 break;
2351 case HW_Fsync:
2352 default:
2353 break;
2354 }
2355 }
2356 else
2357 {
2358 switch(priv->ieee80211->fsync_state)
2359 {
2360 case Default_Fsync:
2361 dm_StartSWFsync(priv);
2362 priv->ieee80211->fsync_state = SW_Fsync;
2363 break;
2364 case HW_Fsync:
2365 dm_EndHWFsync(priv);
2366 dm_StartSWFsync(priv);
2367 priv->ieee80211->fsync_state = SW_Fsync;
2368 break;
2369 case SW_Fsync:
2370 default:
2371 break;
2372
2373 }
2374 }
2375 if(priv->framesyncMonitor)
2376 {
2377 if(reg_c38_State != RegC38_Fsync_AP_BCM)
2378 { //For broadcom AP we write different default value
2379 write_nic_byte(priv, rOFDM0_RxDetector3, 0x95);
2380
2381 reg_c38_State = RegC38_Fsync_AP_BCM;
2382 }
2383 }
2384 }
2385 else
2386 {
2387 switch(priv->ieee80211->fsync_state)
2388 {
2389 case HW_Fsync:
2390 dm_EndHWFsync(priv);
2391 priv->ieee80211->fsync_state = Default_Fsync;
2392 break;
2393 case SW_Fsync:
2394 dm_EndSWFsync(priv);
2395 priv->ieee80211->fsync_state = Default_Fsync;
2396 break;
2397 case Default_Fsync:
2398 default:
2399 break;
2400 }
2401
2402 if(priv->framesyncMonitor)
2403 {
2404 if(priv->ieee80211->state == IEEE80211_LINKED)
2405 {
2406 if(priv->undecorated_smoothed_pwdb <= RegC38_TH)
2407 {
2408 if(reg_c38_State != RegC38_NonFsync_Other_AP)
2409 {
2410 write_nic_byte(priv, rOFDM0_RxDetector3, 0x90);
2411
2412 reg_c38_State = RegC38_NonFsync_Other_AP;
2413 }
2414 }
2415 else if(priv->undecorated_smoothed_pwdb >= (RegC38_TH+5))
2416 {
2417 if(reg_c38_State)
2418 {
2419 write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2420 reg_c38_State = RegC38_Default;
2421 }
2422 }
2423 }
2424 else
2425 {
2426 if(reg_c38_State)
2427 {
2428 write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2429 reg_c38_State = RegC38_Default;
2430 }
2431 }
2432 }
2433 }
2434 if(priv->framesyncMonitor)
2435 {
2436 if(priv->reset_count != reset_cnt)
2437 { //After silent reset, the reg_c38_State will be returned to default value
2438 write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2439 reg_c38_State = RegC38_Default;
2440 reset_cnt = priv->reset_count;
2441 }
2442 }
2443 else
2444 {
2445 if(reg_c38_State)
2446 {
2447 write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
2448 reg_c38_State = RegC38_Default;
2449 }
2450 }
2451}
2452
2453/*
2454 * Detect Signal strength to control TX Registry
2455 * Tx Power Control For Near/Far Range
2456 */
2457static void dm_init_dynamic_txpower(struct r8192_priv *priv)
2458{
2459 //Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code.
2460 priv->ieee80211->bdynamic_txpower_enable = true; //Default to enable Tx Power Control
2461 priv->bLastDTPFlag_High = false;
2462 priv->bLastDTPFlag_Low = false;
2463 priv->bDynamicTxHighPower = false;
2464 priv->bDynamicTxLowPower = false;
2465}
2466
2467static void dm_dynamic_txpower(struct r8192_priv *priv)
2468{
2469 unsigned int txhipower_threshhold=0;
2470 unsigned int txlowpower_threshold=0;
2471 if(priv->ieee80211->bdynamic_txpower_enable != true)
2472 {
2473 priv->bDynamicTxHighPower = false;
2474 priv->bDynamicTxLowPower = false;
2475 return;
2476 }
2477 if((priv->ieee80211->current_network.atheros_cap_exist ) && (priv->ieee80211->mode == IEEE_G)){
2478 txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH;
2479 txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW;
2480 }
2481 else
2482 {
2483 txhipower_threshhold = TX_POWER_NEAR_FIELD_THRESH_HIGH;
2484 txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW;
2485 }
2486
2487 RT_TRACE(COMP_TXAGC, "priv->undecorated_smoothed_pwdb = %ld\n" , priv->undecorated_smoothed_pwdb);
2488
2489 if(priv->ieee80211->state == IEEE80211_LINKED)
2490 {
2491 if(priv->undecorated_smoothed_pwdb >= txhipower_threshhold)
2492 {
2493 priv->bDynamicTxHighPower = true;
2494 priv->bDynamicTxLowPower = false;
2495 }
2496 else
2497 {
2498 // high power state check
2499 if(priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true)
2500 {
2501 priv->bDynamicTxHighPower = false;
2502 }
2503 // low power state check
2504 if(priv->undecorated_smoothed_pwdb < 35)
2505 {
2506 priv->bDynamicTxLowPower = true;
2507 }
2508 else if(priv->undecorated_smoothed_pwdb >= 40)
2509 {
2510 priv->bDynamicTxLowPower = false;
2511 }
2512 }
2513 }
2514 else
2515 {
2516 //pHalData->bTXPowerCtrlforNearFarRange = !pHalData->bTXPowerCtrlforNearFarRange;
2517 priv->bDynamicTxHighPower = false;
2518 priv->bDynamicTxLowPower = false;
2519 }
2520
2521 if( (priv->bDynamicTxHighPower != priv->bLastDTPFlag_High ) ||
2522 (priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low ) )
2523 {
2524 RT_TRACE(COMP_TXAGC, "SetTxPowerLevel8190() channel = %d\n", priv->ieee80211->current_network.channel);
2525
2526
2527 rtl8192_phy_setTxPower(priv, priv->ieee80211->current_network.channel);
2528
2529 }
2530 priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
2531 priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower;
2532
2533}
2534
2535//added by vivi, for read tx rate and retrycount
2536static void dm_check_txrateandretrycount(struct r8192_priv *priv)
2537{
2538 struct ieee80211_device* ieee = priv->ieee80211;
2539
2540 //for initial tx rate
2541 ieee->softmac_stats.last_packet_rate = read_nic_byte(priv ,Initial_Tx_Rate_Reg);
2542 //for tx tx retry count
2543 ieee->softmac_stats.txretrycount = read_nic_dword(priv, Tx_Retry_Count_Reg);
2544}
2545
2546static void dm_send_rssi_tofw(struct r8192_priv *priv)
2547{
2548 // If we test chariot, we should stop the TX command ?
2549 // Because 92E will always silent reset when we send tx command. We use register
2550 // 0x1e0(byte) to botify driver.
2551 write_nic_byte(priv, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
2552 return;
2553}
2554
diff --git a/drivers/staging/rtl8192e/r8192E_dm.h b/drivers/staging/rtl8192e/r8192E_dm.h
new file mode 100644
index 00000000000..b5b34eaaee9
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8192E_dm.h
@@ -0,0 +1,228 @@
1/*****************************************************************************
2 * Copyright(c) 2007, RealTEK Technology Inc. All Right Reserved.
3 *
4 * Module: Hal819xUsbDM.h (RTL8192 Header H File)
5 *
6 *
7 * Note: For dynamic control definition constant structure.
8 *
9 *
10 * Export:
11 *
12 * Abbrev:
13 *
14 * History:
15 * Data Who Remark
16 * 10/04/2007 MHC Create initial version.
17 *
18 *****************************************************************************/
19
20#ifndef __R8192UDM_H__
21#define __R8192UDM_H__
22
23#define OFDM_Table_Length 19
24#define CCK_Table_length 12
25
26#define DM_DIG_THRESH_HIGH 40
27#define DM_DIG_THRESH_LOW 35
28
29#define DM_DIG_HIGH_PWR_THRESH_HIGH 75
30#define DM_DIG_HIGH_PWR_THRESH_LOW 70
31
32#define BW_AUTO_SWITCH_HIGH_LOW 25
33#define BW_AUTO_SWITCH_LOW_HIGH 30
34
35#define DM_check_fsync_time_interval 500
36
37
38#define DM_DIG_BACKOFF 12
39#define DM_DIG_MAX 0x36
40#define DM_DIG_MIN 0x1c
41#define DM_DIG_MIN_Netcore 0x12
42
43#define RxPathSelection_SS_TH_low 30
44#define RxPathSelection_diff_TH 18
45
46#define RateAdaptiveTH_High 50
47#define RateAdaptiveTH_Low_20M 30
48#define RateAdaptiveTH_Low_40M 10
49#define VeryLowRSSI 15
50#define CTSToSelfTHVal 35
51
52//defined by vivi, for tx power track
53#define E_FOR_TX_POWER_TRACK 300
54//Dynamic Tx Power Control Threshold
55#define TX_POWER_NEAR_FIELD_THRESH_HIGH 68
56#define TX_POWER_NEAR_FIELD_THRESH_LOW 62
57//added by amy for atheros AP
58#define TX_POWER_ATHEROAP_THRESH_HIGH 78
59#define TX_POWER_ATHEROAP_THRESH_LOW 72
60
61//defined by vivi, for showing on UI. Newer firmware has changed to 0x1e0
62#define Current_Tx_Rate_Reg 0x1e0//0x1b8
63#define Initial_Tx_Rate_Reg 0x1e1 //0x1b9
64#define Tx_Retry_Count_Reg 0x1ac
65#define RegC38_TH 20
66
67/* 2007/10/04 MH Define upper and lower threshold of DIG enable or disable. */
68typedef struct _dynamic_initial_gain_threshold_
69{
70 u8 dig_enable_flag;
71 u8 dig_algorithm;
72 u8 dbg_mode;
73 u8 dig_algorithm_switch;
74
75 long rssi_low_thresh;
76 long rssi_high_thresh;
77
78 long rssi_high_power_lowthresh;
79 long rssi_high_power_highthresh;
80
81 u8 dig_state;
82 u8 dig_highpwr_state;
83 u8 cur_connect_state;
84 u8 pre_connect_state;
85
86 u8 curpd_thstate;
87 u8 prepd_thstate;
88 u8 curcs_ratio_state;
89 u8 precs_ratio_state;
90
91 u32 pre_ig_value;
92 u32 cur_ig_value;
93
94 u8 backoff_val;
95 u8 rx_gain_range_max;
96 u8 rx_gain_range_min;
97 bool initialgain_lowerbound_state;
98
99 long rssi_val;
100}dig_t;
101
102typedef enum tag_dynamic_init_gain_state_definition
103{
104 DM_STA_DIG_OFF = 0,
105 DM_STA_DIG_ON,
106 DM_STA_DIG_MAX
107}dm_dig_sta_e;
108
109
110/* 2007/10/08 MH Define RATR state. */
111typedef enum tag_dynamic_ratr_state_definition
112{
113 DM_RATR_STA_HIGH = 0,
114 DM_RATR_STA_MIDDLE = 1,
115 DM_RATR_STA_LOW = 2,
116 DM_RATR_STA_MAX
117}dm_ratr_sta_e;
118
119/* 2007/10/11 MH Define DIG operation type. */
120typedef enum tag_dynamic_init_gain_operation_type_definition
121{
122 DIG_TYPE_THRESH_HIGH = 0,
123 DIG_TYPE_THRESH_LOW = 1,
124 DIG_TYPE_THRESH_HIGHPWR_HIGH = 2,
125 DIG_TYPE_THRESH_HIGHPWR_LOW = 3,
126 DIG_TYPE_DBG_MODE = 4,
127 DIG_TYPE_RSSI = 5,
128 DIG_TYPE_ALGORITHM = 6,
129 DIG_TYPE_BACKOFF = 7,
130 DIG_TYPE_PWDB_FACTOR = 8,
131 DIG_TYPE_RX_GAIN_MIN = 9,
132 DIG_TYPE_RX_GAIN_MAX = 10,
133 DIG_TYPE_ENABLE = 20,
134 DIG_TYPE_DISABLE = 30,
135 DIG_OP_TYPE_MAX
136}dm_dig_op_e;
137
138typedef enum tag_dig_algorithm_definition
139{
140 DIG_ALGO_BY_FALSE_ALARM = 0,
141 DIG_ALGO_BY_RSSI = 1,
142 DIG_ALGO_MAX
143}dm_dig_alg_e;
144
145typedef enum tag_dig_dbgmode_definition
146{
147 DIG_DBG_OFF = 0,
148 DIG_DBG_ON = 1,
149 DIG_DBG_MAX
150}dm_dig_dbg_e;
151
152typedef enum tag_dig_connect_definition
153{
154 DIG_DISCONNECT = 0,
155 DIG_CONNECT = 1,
156 DIG_CONNECT_MAX
157}dm_dig_connect_e;
158
159typedef enum tag_dig_packetdetection_threshold_definition
160{
161 DIG_PD_AT_LOW_POWER = 0,
162 DIG_PD_AT_NORMAL_POWER = 1,
163 DIG_PD_AT_HIGH_POWER = 2,
164 DIG_PD_MAX
165}dm_dig_pd_th_e;
166
167typedef enum tag_dig_cck_cs_ratio_state_definition
168{
169 DIG_CS_RATIO_LOWER = 0,
170 DIG_CS_RATIO_HIGHER = 1,
171 DIG_CS_MAX
172}dm_dig_cs_ratio_e;
173typedef struct _Dynamic_Rx_Path_Selection_
174{
175 u8 Enable;
176 u8 DbgMode;
177 u8 cck_method;
178 u8 cck_Rx_path;
179
180 u8 SS_TH_low;
181 u8 diff_TH;
182 u8 disabledRF;
183 u8 reserved;
184
185 u8 rf_rssi[4];
186 u8 rf_enable_rssi_th[4];
187 long cck_pwdb_sta[4];
188}DRxPathSel;
189
190typedef enum tag_CCK_Rx_Path_Method_Definition
191{
192 CCK_Rx_Version_1 = 0,
193 CCK_Rx_Version_2= 1,
194 CCK_Rx_Version_MAX
195}DM_CCK_Rx_Path_Method;
196
197typedef enum tag_DM_DbgMode_Definition
198{
199 DM_DBG_OFF = 0,
200 DM_DBG_ON = 1,
201 DM_DBG_MAX
202}DM_DBG_E;
203
204typedef struct tag_Tx_Config_Cmd_Format
205{
206 u32 Op; /* Command packet type. */
207 u32 Length; /* Command packet length. */
208 u32 Value;
209}DCMD_TXCMD_T, *PDCMD_TXCMD_T;
210
211
212extern dig_t dm_digtable;
213extern DRxPathSel DM_RxPathSelTable;
214
215void init_hal_dm(struct r8192_priv *priv);
216void deinit_hal_dm(struct r8192_priv *priv);
217
218void hal_dm_watchdog(struct r8192_priv *priv);
219
220void init_rate_adaptive(struct r8192_priv *priv);
221void dm_txpower_trackingcallback(struct work_struct *work);
222void dm_rf_pathcheck_workitemcallback(struct work_struct *work);
223void dm_initialize_txpower_tracking(struct r8192_priv *priv);
224void dm_cck_txpower_adjust(struct r8192_priv *priv, bool binch14);
225
226
227#endif /*__R8192UDM_H__ */
228
diff --git a/drivers/staging/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/r8192E_hw.h
new file mode 100644
index 00000000000..24e7303e56a
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8192E_hw.h
@@ -0,0 +1,491 @@
1/*
2 This is part of rtl8187 OpenSource driver.
3 Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it>
4 Released under the terms of GPL (General Public Licence)
5
6 Parts of this driver are based on the GPL part of the
7 official Realtek driver.
8 Parts of this driver are based on the rtl8180 driver skeleton
9 from Patric Schenke & Andres Salomon.
10 Parts of this driver are based on the Intel Pro Wireless
11 2100 GPL driver.
12
13 We want to tanks the Authors of those projects
14 and the Ndiswrapper project Authors.
15*/
16
17/* Mariusz Matuszek added full registers definition with Realtek's name */
18
19/* this file contains register definitions for the rtl8187 MAC controller */
20#ifndef R8180_HW
21#define R8180_HW
22
23typedef enum _VERSION_8190{
24 VERSION_8190_BD=0x3,
25 VERSION_8190_BE
26}VERSION_8190,*PVERSION_8190;
27//added for different RF type
28typedef enum _RT_RF_TYPE_DEF
29{
30 RF_1T2R = 0,
31 RF_2T4R,
32
33 RF_819X_MAX_TYPE
34}RT_RF_TYPE_DEF;
35
36typedef enum _BaseBand_Config_Type{
37 BaseBand_Config_PHY_REG = 0, //Radio Path A
38 BaseBand_Config_AGC_TAB = 1, //Radio Path B
39}BaseBand_Config_Type, *PBaseBand_Config_Type;
40
41#define RTL8187_REQT_READ 0xc0
42#define RTL8187_REQT_WRITE 0x40
43#define RTL8187_REQ_GET_REGS 0x05
44#define RTL8187_REQ_SET_REGS 0x05
45
46#define R8180_MAX_RETRY 255
47#define MAX_TX_URB 5
48#define MAX_RX_URB 16
49#define RX_URB_SIZE 9100
50
51#define BB_ANTATTEN_CHAN14 0x0c
52#define BB_ANTENNA_B 0x40
53
54#define BB_HOST_BANG (1<<30)
55#define BB_HOST_BANG_EN (1<<2)
56#define BB_HOST_BANG_CLK (1<<1)
57#define BB_HOST_BANG_RW (1<<3)
58#define BB_HOST_BANG_DATA 1
59
60#define RTL8190_EEPROM_ID 0x8129
61#define EEPROM_VID 0x02
62#define EEPROM_DID 0x04
63#define EEPROM_NODE_ADDRESS_BYTE_0 0x0C
64
65#define EEPROM_TxPowerDiff 0x1F
66
67
68#define EEPROM_PwDiff 0x21 //0x21
69#define EEPROM_CrystalCap 0x22 //0x22
70
71
72
73#define EEPROM_TxPwIndex_CCK_V1 0x29 //0x29~0x2B
74#define EEPROM_TxPwIndex_OFDM_24G_V1 0x2C //0x2C~0x2E
75#define EEPROM_TxPwIndex_Ver 0x27 //0x27
76
77#define EEPROM_Default_TxPowerDiff 0x0
78#define EEPROM_Default_ThermalMeter 0x77
79#define EEPROM_Default_AntTxPowerDiff 0x0
80#define EEPROM_Default_TxPwDiff_CrystalCap 0x5
81#define EEPROM_Default_PwDiff 0x4
82#define EEPROM_Default_CrystalCap 0x5
83#define EEPROM_Default_TxPower 0x1010
84#define EEPROM_ICVersion_ChannelPlan 0x7C //0x7C:ChannelPlan, 0x7D:IC_Version
85#define EEPROM_Customer_ID 0x7B //0x7B:CustomerID
86
87#define EEPROM_RFInd_PowerDiff 0x28
88#define EEPROM_ThermalMeter 0x29
89#define EEPROM_TxPwDiff_CrystalCap 0x2A //0x2A~0x2B
90#define EEPROM_TxPwIndex_CCK 0x2C //0x23
91#define EEPROM_TxPwIndex_OFDM_24G 0x3A //0x24~0x26
92
93#define EEPROM_Default_TxPowerLevel 0x10
94
95#define EEPROM_IC_VER 0x7d //0x7D
96#define EEPROM_CRC 0x7e //0x7E~0x7F
97
98#define EEPROM_CID_DEFAULT 0x0
99#define EEPROM_CID_CAMEO 0x1
100#define EEPROM_CID_RUNTOP 0x2
101#define EEPROM_CID_Senao 0x3
102#define EEPROM_CID_TOSHIBA 0x4 // Toshiba setting, Merge by Jacken, 2008/01/31
103#define EEPROM_CID_NetCore 0x5
104#define EEPROM_CID_Nettronix 0x6
105#define EEPROM_CID_Pronet 0x7
106#define EEPROM_CID_DLINK 0x8
107#define EEPROM_CID_WHQL 0xFE //added by sherry for dtm, 20080728
108
109enum _RTL8192Pci_HW {
110 MAC0 = 0x000,
111 MAC1 = 0x001,
112 MAC2 = 0x002,
113 MAC3 = 0x003,
114 MAC4 = 0x004,
115 MAC5 = 0x005,
116 PCIF = 0x009, // PCI Function Register 0x0009h~0x000bh
117//----------------------------------------------------------------------------
118// 8190 PCIF bits (Offset 0x009-000b, 24bit)
119//----------------------------------------------------------------------------
120#define MXDMA2_16bytes 0x000
121#define MXDMA2_32bytes 0x001
122#define MXDMA2_64bytes 0x010
123#define MXDMA2_128bytes 0x011
124#define MXDMA2_256bytes 0x100
125#define MXDMA2_512bytes 0x101
126#define MXDMA2_1024bytes 0x110
127#define MXDMA2_NoLimit 0x7
128
129#define MULRW_SHIFT 3
130#define MXDMA2_RX_SHIFT 4
131#define MXDMA2_TX_SHIFT 0
132 PMR = 0x00c, // Power management register
133 EPROM_CMD = 0x00e,
134#define EPROM_CMD_RESERVED_MASK BIT5
135#define EPROM_CMD_9356SEL BIT4
136#define EPROM_CMD_OPERATING_MODE_SHIFT 6
137#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6))
138#define EPROM_CMD_CONFIG 0x3
139#define EPROM_CMD_NORMAL 0
140#define EPROM_CMD_LOAD 1
141#define EPROM_CMD_PROGRAM 2
142#define EPROM_CS_SHIFT 3
143#define EPROM_CK_SHIFT 2
144#define EPROM_W_SHIFT 1
145#define EPROM_R_SHIFT 0
146
147 AFR = 0x010,
148#define AFR_CardBEn (1<<0)
149#define AFR_CLKRUN_SEL (1<<1)
150#define AFR_FuncRegEn (1<<2)
151
152 ANAPAR = 0x17,
153#define BB_GLOBAL_RESET_BIT 0x1
154 BB_GLOBAL_RESET = 0x020, // BasebandGlobal Reset Register
155 BSSIDR = 0x02E, // BSSID Register
156 CMDR = 0x037, // Command register
157#define CR_RST 0x10
158#define CR_RE 0x08
159#define CR_TE 0x04
160#define CR_MulRW 0x01
161 SIFS = 0x03E, // SIFS register
162 TCR = 0x040, // Transmit Configuration Register
163 RCR = 0x044, // Receive Configuration Register
164//----------------------------------------------------------------------------
165//// 8190 (RCR) Receive Configuration Register (Offset 0x44~47, 32 bit)
166////----------------------------------------------------------------------------
167#define RCR_FILTER_MASK (BIT0|BIT1|BIT2|BIT3|BIT5|BIT12|BIT18|BIT19|BIT20|BIT21|BIT22|BIT23)
168#define RCR_ONLYERLPKT BIT31 // Early Receiving based on Packet Size.
169#define RCR_ENCS2 BIT30 // Enable Carrier Sense Detection Method 2
170#define RCR_ENCS1 BIT29 // Enable Carrier Sense Detection Method 1
171#define RCR_ENMBID BIT27 // Enable Multiple BssId.
172#define RCR_ACKTXBW (BIT24|BIT25) // TXBW Setting of ACK frames
173#define RCR_CBSSID BIT23 // Accept BSSID match packet
174#define RCR_APWRMGT BIT22 // Accept power management packet
175#define RCR_ADD3 BIT21 // Accept address 3 match packet
176#define RCR_AMF BIT20 // Accept management type frame
177#define RCR_ACF BIT19 // Accept control type frame
178#define RCR_ADF BIT18 // Accept data type frame
179#define RCR_RXFTH BIT13 // Rx FIFO Threshold
180#define RCR_AICV BIT12 // Accept ICV error packet
181#define RCR_ACRC32 BIT5 // Accept CRC32 error packet
182#define RCR_AB BIT3 // Accept broadcast packet
183#define RCR_AM BIT2 // Accept multicast packet
184#define RCR_APM BIT1 // Accept physical match packet
185#define RCR_AAP BIT0 // Accept all unicast packet
186#define RCR_MXDMA_OFFSET 8
187#define RCR_FIFO_OFFSET 13
188 SLOT_TIME = 0x049, // Slot Time Register
189 ACK_TIMEOUT = 0x04c, // Ack Timeout Register
190 PIFS_TIME = 0x04d, // PIFS time
191 USTIME = 0x04e, // Microsecond Tuning Register, Sets the microsecond time unit used by MAC clock.
192 EDCAPARA_BE = 0x050, // EDCA Parameter of AC BE
193 EDCAPARA_BK = 0x054, // EDCA Parameter of AC BK
194 EDCAPARA_VO = 0x058, // EDCA Parameter of AC VO
195 EDCAPARA_VI = 0x05C, // EDCA Parameter of AC VI
196#define AC_PARAM_TXOP_LIMIT_OFFSET 16
197#define AC_PARAM_ECW_MAX_OFFSET 12
198#define AC_PARAM_ECW_MIN_OFFSET 8
199#define AC_PARAM_AIFS_OFFSET 0
200 RFPC = 0x05F, // Rx FIFO Packet Count
201 CWRR = 0x060, // Contention Window Report Register
202 BCN_TCFG = 0x062, // Beacon Time Configuration
203#define BCN_TCFG_CW_SHIFT 8
204#define BCN_TCFG_IFS 0
205 BCN_INTERVAL = 0x070, // Beacon Interval (TU)
206 ATIMWND = 0x072, // ATIM Window Size (TU)
207 BCN_DRV_EARLY_INT = 0x074, // Driver Early Interrupt Time (TU). Time to send interrupt to notify to change beacon content before TBTT
208#define BCN_DRV_EARLY_INT_SWBCN_SHIFT 8
209#define BCN_DRV_EARLY_INT_TIME_SHIFT 0
210 BCN_DMATIME = 0x076, // Beacon DMA and ATIM interrupt time (US). Indicates the time before TBTT to perform beacon queue DMA
211 BCN_ERR_THRESH = 0x078, // Beacon Error Threshold
212 RWCAM = 0x0A0, //IN 8190 Data Sheet is called CAMcmd
213 //----------------------------------------------------------------------------
214 //// 8190 CAM Command Register (offset 0xA0, 4 byte)
215 ////----------------------------------------------------------------------------
216#define CAM_CM_SecCAMPolling BIT31 //Security CAM Polling
217#define CAM_CM_SecCAMClr BIT30 //Clear all bits in CAM
218#define CAM_CM_SecCAMWE BIT16 //Security CAM enable
219#define CAM_VALID BIT15
220#define CAM_NOTVALID 0x0000
221#define CAM_USEDK BIT5
222
223#define CAM_NONE 0x0
224#define CAM_WEP40 0x01
225#define CAM_TKIP 0x02
226#define CAM_AES 0x04
227#define CAM_WEP104 0x05
228
229#define TOTAL_CAM_ENTRY 32
230
231#define CAM_CONFIG_USEDK true
232#define CAM_CONFIG_NO_USEDK false
233#define CAM_WRITE BIT16
234#define CAM_READ 0x00000000
235#define CAM_POLLINIG BIT31
236#define SCR_UseDK 0x01
237 WCAMI = 0x0A4, // Software write CAM input content
238 RCAMO = 0x0A8, // Software read/write CAM config
239 SECR = 0x0B0, //Security Configuration Register
240#define SCR_TxUseDK BIT0 //Force Tx Use Default Key
241#define SCR_RxUseDK BIT1 //Force Rx Use Default Key
242#define SCR_TxEncEnable BIT2 //Enable Tx Encryption
243#define SCR_RxDecEnable BIT3 //Enable Rx Decryption
244#define SCR_SKByA2 BIT4 //Search kEY BY A2
245#define SCR_NoSKMC BIT5 //No Key Search for Multicast
246 SWREGULATOR = 0x0BD, // Switching Regulator
247 INTA_MASK = 0x0f4,
248//----------------------------------------------------------------------------
249// 8190 IMR/ISR bits (offset 0xfd, 8bits)
250//----------------------------------------------------------------------------
251#define IMR8190_DISABLED 0x0
252#define IMR_ATIMEND BIT28 // ATIM Window End Interrupt
253#define IMR_TBDOK BIT27 // Transmit Beacon OK Interrupt
254#define IMR_TBDER BIT26 // Transmit Beacon Error Interrupt
255#define IMR_TXFOVW BIT15 // Transmit FIFO Overflow
256#define IMR_TIMEOUT0 BIT14 // TimeOut0
257#define IMR_BcnInt BIT13 // Beacon DMA Interrupt 0
258#define IMR_RXFOVW BIT12 // Receive FIFO Overflow
259#define IMR_RDU BIT11 // Receive Descriptor Unavailable
260#define IMR_RXCMDOK BIT10 // Receive Command Packet OK
261#define IMR_BDOK BIT9 // Beacon Queue DMA OK Interrup
262#define IMR_HIGHDOK BIT8 // High Queue DMA OK Interrupt
263#define IMR_COMDOK BIT7 // Command Queue DMA OK Interrupt
264#define IMR_MGNTDOK BIT6 // Management Queue DMA OK Interrupt
265#define IMR_HCCADOK BIT5 // HCCA Queue DMA OK Interrupt
266#define IMR_BKDOK BIT4 // AC_BK DMA OK Interrupt
267#define IMR_BEDOK BIT3 // AC_BE DMA OK Interrupt
268#define IMR_VIDOK BIT2 // AC_VI DMA OK Interrupt
269#define IMR_VODOK BIT1 // AC_VO DMA Interrupt
270#define IMR_ROK BIT0 // Receive DMA OK Interrupt
271 ISR = 0x0f8, // Interrupt Status Register
272 TPPoll = 0x0fd, // Transmit priority polling register
273#define TPPoll_BKQ BIT0 // BK queue polling
274#define TPPoll_BEQ BIT1 // BE queue polling
275#define TPPoll_VIQ BIT2 // VI queue polling
276#define TPPoll_VOQ BIT3 // VO queue polling
277#define TPPoll_BQ BIT4 // Beacon queue polling
278#define TPPoll_CQ BIT5 // Command queue polling
279#define TPPoll_MQ BIT6 // Management queue polling
280#define TPPoll_HQ BIT7 // High queue polling
281#define TPPoll_HCCAQ BIT8 // HCCA queue polling
282#define TPPoll_StopBK BIT9 // Stop BK queue
283#define TPPoll_StopBE BIT10 // Stop BE queue
284#define TPPoll_StopVI BIT11 // Stop VI queue
285#define TPPoll_StopVO BIT12 // Stop VO queue
286#define TPPoll_StopMgt BIT13 // Stop Mgnt queue
287#define TPPoll_StopHigh BIT14 // Stop High queue
288#define TPPoll_StopHCCA BIT15 // Stop HCCA queue
289#define TPPoll_SHIFT 8 // Queue ID mapping
290
291 PSR = 0x0ff, // Page Select Register
292#define PSR_GEN 0x0 // Page 0 register general MAC Control
293#define PSR_CPU 0x1 // Page 1 register for CPU
294 CPU_GEN = 0x100, // CPU Reset Register
295 BB_RESET = 0x101, // Baseband Reset
296//----------------------------------------------------------------------------
297// 8190 CPU General Register (offset 0x100, 4 byte)
298//----------------------------------------------------------------------------
299#define CPU_CCK_LOOPBACK 0x00030000
300#define CPU_GEN_SYSTEM_RESET 0x00000001
301#define CPU_GEN_FIRMWARE_RESET 0x00000008
302#define CPU_GEN_BOOT_RDY 0x00000010
303#define CPU_GEN_FIRM_RDY 0x00000020
304#define CPU_GEN_PUT_CODE_OK 0x00000080
305#define CPU_GEN_BB_RST 0x00000100
306#define CPU_GEN_PWR_STB_CPU 0x00000004
307#define CPU_GEN_NO_LOOPBACK_MSK 0xFFF8FFFF // Set bit18,17,16 to 0. Set bit19
308#define CPU_GEN_NO_LOOPBACK_SET 0x00080000 // Set BIT19 to 1
309#define CPU_GEN_GPIO_UART 0x00007000
310
311 LED1Cfg = 0x154,// LED1 Configuration Register
312 LED0Cfg = 0x155,// LED0 Configuration Register
313
314 AcmAvg = 0x170, // ACM Average Period Register
315 AcmHwCtrl = 0x171, // ACM Hardware Control Register
316//----------------------------------------------------------------------------
317//
318// 8190 AcmHwCtrl bits (offset 0x171, 1 byte)
319//----------------------------------------------------------------------------
320#define AcmHw_HwEn BIT0
321#define AcmHw_BeqEn BIT1
322#define AcmHw_ViqEn BIT2
323#define AcmHw_VoqEn BIT3
324#define AcmHw_BeqStatus BIT4
325#define AcmHw_ViqStatus BIT5
326#define AcmHw_VoqStatus BIT6
327 AcmFwCtrl = 0x172, // ACM Firmware Control Register
328#define AcmFw_BeqStatus BIT0
329#define AcmFw_ViqStatus BIT1
330#define AcmFw_VoqStatus BIT2
331 VOAdmTime = 0x174, // VO Queue Admitted Time Register
332 VIAdmTime = 0x178, // VI Queue Admitted Time Register
333 BEAdmTime = 0x17C, // BE Queue Admitted Time Register
334 RQPN1 = 0x180, // Reserved Queue Page Number , Vo Vi, Be, Bk
335 RQPN2 = 0x184, // Reserved Queue Page Number, HCCA, Cmd, Mgnt, High
336 RQPN3 = 0x188, // Reserved Queue Page Number, Bcn, Public,
337 QPRR = 0x1E0, // Queue Page Report per TID
338 QPNR = 0x1F0, // Queue Packet Number report per TID
339/* there's 9 tx descriptor base address available */
340 BQDA = 0x200, // Beacon Queue Descriptor Address
341 HQDA = 0x204, // High Priority Queue Descriptor Address
342 CQDA = 0x208, // Command Queue Descriptor Address
343 MQDA = 0x20C, // Management Queue Descriptor Address
344 HCCAQDA = 0x210, // HCCA Queue Descriptor Address
345 VOQDA = 0x214, // VO Queue Descriptor Address
346 VIQDA = 0x218, // VI Queue Descriptor Address
347 BEQDA = 0x21C, // BE Queue Descriptor Address
348 BKQDA = 0x220, // BK Queue Descriptor Address
349/* there's 2 rx descriptor base address availalbe */
350 RCQDA = 0x224, // Receive command Queue Descriptor Address
351 RDQDA = 0x228, // Receive Queue Descriptor Start Address
352
353 MAR0 = 0x240, // Multicast filter.
354 MAR4 = 0x244,
355
356 CCX_PERIOD = 0x250, // CCX Measurement Period Register, in unit of TU.
357 CLM_RESULT = 0x251, // CCA Busy fraction register.
358 NHM_PERIOD = 0x252, // NHM Measurement Period register, in unit of TU.
359
360 NHM_THRESHOLD0 = 0x253, // Noise Histogram Meashorement0.
361 NHM_THRESHOLD1 = 0x254, // Noise Histogram Meashorement1.
362 NHM_THRESHOLD2 = 0x255, // Noise Histogram Meashorement2.
363 NHM_THRESHOLD3 = 0x256, // Noise Histogram Meashorement3.
364 NHM_THRESHOLD4 = 0x257, // Noise Histogram Meashorement4.
365 NHM_THRESHOLD5 = 0x258, // Noise Histogram Meashorement5.
366 NHM_THRESHOLD6 = 0x259, // Noise Histogram Meashorement6
367
368 MCTRL = 0x25A, // Measurement Control
369
370 NHM_RPI_COUNTER0 = 0x264, // Noise Histogram RPI counter0, the fraction of signal strength < NHM_THRESHOLD0.
371 NHM_RPI_COUNTER1 = 0x265, // Noise Histogram RPI counter1, the fraction of signal strength in (NHM_THRESHOLD0, NHM_THRESHOLD1].
372 NHM_RPI_COUNTER2 = 0x266, // Noise Histogram RPI counter2, the fraction of signal strength in (NHM_THRESHOLD1, NHM_THRESHOLD2].
373 NHM_RPI_COUNTER3 = 0x267, // Noise Histogram RPI counter3, the fraction of signal strength in (NHM_THRESHOLD2, NHM_THRESHOLD3].
374 NHM_RPI_COUNTER4 = 0x268, // Noise Histogram RPI counter4, the fraction of signal strength in (NHM_THRESHOLD3, NHM_THRESHOLD4].
375 NHM_RPI_COUNTER5 = 0x269, // Noise Histogram RPI counter5, the fraction of signal strength in (NHM_THRESHOLD4, NHM_THRESHOLD5].
376 NHM_RPI_COUNTER6 = 0x26A, // Noise Histogram RPI counter6, the fraction of signal strength in (NHM_THRESHOLD5, NHM_THRESHOLD6].
377 NHM_RPI_COUNTER7 = 0x26B, // Noise Histogram RPI counter7, the fraction of signal strength in (NHM_THRESHOLD6, NHM_THRESHOLD7].
378 WFCRC0 = 0x2f0,
379 WFCRC1 = 0x2f4,
380 WFCRC2 = 0x2f8,
381
382 BW_OPMODE = 0x300, // Bandwidth operation mode
383#define BW_OPMODE_11J BIT0
384#define BW_OPMODE_5G BIT1
385#define BW_OPMODE_20MHZ BIT2
386 IC_VERRSION = 0x301, //IC_VERSION
387 MSR = 0x303, // Media Status register
388#define MSR_LINK_MASK ((1<<0)|(1<<1))
389#define MSR_LINK_MANAGED 2
390#define MSR_LINK_NONE 0
391#define MSR_LINK_SHIFT 0
392#define MSR_LINK_ADHOC 1
393#define MSR_LINK_MASTER 3
394#define MSR_LINK_ENEDCA (1<<4)
395 RETRY_LIMIT = 0x304, // Retry Limit [15:8]-short, [7:0]-long
396#define RETRY_LIMIT_SHORT_SHIFT 8
397#define RETRY_LIMIT_LONG_SHIFT 0
398 TSFR = 0x308,
399 RRSR = 0x310, // Response Rate Set
400#define RRSR_RSC_OFFSET 21
401#define RRSR_SHORT_OFFSET 23
402#define RRSR_RSC_DUPLICATE 0x600000
403#define RRSR_RSC_UPSUBCHNL 0x400000
404#define RRSR_RSC_LOWSUBCHNL 0x200000
405#define RRSR_SHORT 0x800000
406#define RRSR_1M BIT0
407#define RRSR_2M BIT1
408#define RRSR_5_5M BIT2
409#define RRSR_11M BIT3
410#define RRSR_6M BIT4
411#define RRSR_9M BIT5
412#define RRSR_12M BIT6
413#define RRSR_18M BIT7
414#define RRSR_24M BIT8
415#define RRSR_36M BIT9
416#define RRSR_48M BIT10
417#define RRSR_54M BIT11
418#define RRSR_MCS0 BIT12
419#define RRSR_MCS1 BIT13
420#define RRSR_MCS2 BIT14
421#define RRSR_MCS3 BIT15
422#define RRSR_MCS4 BIT16
423#define RRSR_MCS5 BIT17
424#define RRSR_MCS6 BIT18
425#define RRSR_MCS7 BIT19
426#define BRSR_AckShortPmb BIT23 // CCK ACK: use Short Preamble or not
427 UFWP = 0x318,
428 RATR0 = 0x320, // Rate Adaptive Table register1
429//----------------------------------------------------------------------------
430// 8190 Rate Adaptive Table Register (offset 0x320, 4 byte)
431//----------------------------------------------------------------------------
432//CCK
433#define RATR_1M 0x00000001
434#define RATR_2M 0x00000002
435#define RATR_55M 0x00000004
436#define RATR_11M 0x00000008
437//OFDM
438#define RATR_6M 0x00000010
439#define RATR_9M 0x00000020
440#define RATR_12M 0x00000040
441#define RATR_18M 0x00000080
442#define RATR_24M 0x00000100
443#define RATR_36M 0x00000200
444#define RATR_48M 0x00000400
445#define RATR_54M 0x00000800
446//MCS 1 Spatial Stream
447#define RATR_MCS0 0x00001000
448#define RATR_MCS1 0x00002000
449#define RATR_MCS2 0x00004000
450#define RATR_MCS3 0x00008000
451#define RATR_MCS4 0x00010000
452#define RATR_MCS5 0x00020000
453#define RATR_MCS6 0x00040000
454#define RATR_MCS7 0x00080000
455//MCS 2 Spatial Stream
456#define RATR_MCS8 0x00100000
457#define RATR_MCS9 0x00200000
458#define RATR_MCS10 0x00400000
459#define RATR_MCS11 0x00800000
460#define RATR_MCS12 0x01000000
461#define RATR_MCS13 0x02000000
462#define RATR_MCS14 0x04000000
463#define RATR_MCS15 0x08000000
464// ALL CCK Rate
465#define RATE_ALL_CCK RATR_1M|RATR_2M|RATR_55M|RATR_11M
466#define RATE_ALL_OFDM_AG RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M|RATR_36M|RATR_48M|RATR_54M
467#define RATE_ALL_OFDM_1SS RATR_MCS0|RATR_MCS1|RATR_MCS2|RATR_MCS3 | \
468 RATR_MCS4|RATR_MCS5|RATR_MCS6 |RATR_MCS7
469#define RATE_ALL_OFDM_2SS RATR_MCS8|RATR_MCS9 |RATR_MCS10|RATR_MCS11| \
470 RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15
471
472
473 DRIVER_RSSI = 0x32c, // Driver tell Firmware current RSSI
474 MCS_TXAGC = 0x340, // MCS AGC
475 CCK_TXAGC = 0x348, // CCK AGC
476 MacBlkCtrl = 0x403, // Mac block on/off control register
477
478};
479
480#define GPI 0x108
481#define GPO 0x109
482#define GPE 0x10a
483
484#define ANAPAR_FOR_8192PciE 0x17 // Analog parameter register
485
486#define MSR_NOLINK 0x00
487#define MSR_ADHOC 0x01
488#define MSR_INFRA 0x02
489#define MSR_AP 0x03
490
491#endif
diff --git a/drivers/staging/rtl8192e/r8192E_wx.c b/drivers/staging/rtl8192e/r8192E_wx.c
new file mode 100644
index 00000000000..adad91b0b6b
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8192E_wx.c
@@ -0,0 +1,1163 @@
1/*
2 This file contains wireless extension handlers.
3
4 This is part of rtl8180 OpenSource driver.
5 Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it>
6 Released under the terms of GPL (General Public Licence)
7
8 Parts of this driver are based on the GPL part
9 of the official realtek driver.
10
11 Parts of this driver are based on the rtl8180 driver skeleton
12 from Patric Schenke & Andres Salomon.
13
14 Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
15
16 We want to tanks the Authors of those projects and the Ndiswrapper
17 project Authors.
18*/
19
20#include <linux/string.h>
21#include "r8192E.h"
22#include "r8192E_hw.h"
23#include "r8192E_wx.h"
24#ifdef ENABLE_DOT11D
25#include "ieee80211/dot11d.h"
26#endif
27
28#define RATE_COUNT 12
29static const u32 rtl8180_rates[] = {1000000,2000000,5500000,11000000,
30 6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000};
31
32
33#ifndef ENETDOWN
34#define ENETDOWN 1
35#endif
36static int r8192_wx_get_freq(struct net_device *dev,
37 struct iw_request_info *a,
38 union iwreq_data *wrqu, char *b)
39{
40 struct r8192_priv *priv = ieee80211_priv(dev);
41
42 return ieee80211_wx_get_freq(priv->ieee80211,a,wrqu,b);
43}
44
45
46static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
47 union iwreq_data *wrqu, char *b)
48{
49 struct r8192_priv *priv=ieee80211_priv(dev);
50
51 return ieee80211_wx_get_mode(priv->ieee80211,a,wrqu,b);
52}
53
54
55
56static int r8192_wx_get_rate(struct net_device *dev,
57 struct iw_request_info *info,
58 union iwreq_data *wrqu, char *extra)
59{
60 struct r8192_priv *priv = ieee80211_priv(dev);
61 return ieee80211_wx_get_rate(priv->ieee80211,info,wrqu,extra);
62}
63
64
65
66static int r8192_wx_set_rate(struct net_device *dev,
67 struct iw_request_info *info,
68 union iwreq_data *wrqu, char *extra)
69{
70 int ret;
71 struct r8192_priv *priv = ieee80211_priv(dev);
72
73 if (priv->bHwRadioOff)
74 return 0;
75
76 down(&priv->wx_sem);
77
78 ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra);
79
80 up(&priv->wx_sem);
81
82 return ret;
83}
84
85
86static int r8192_wx_set_rts(struct net_device *dev,
87 struct iw_request_info *info,
88 union iwreq_data *wrqu, char *extra)
89{
90 int ret;
91 struct r8192_priv *priv = ieee80211_priv(dev);
92
93 if (priv->bHwRadioOff)
94 return 0;
95
96 down(&priv->wx_sem);
97
98 ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra);
99
100 up(&priv->wx_sem);
101
102 return ret;
103}
104
105static int r8192_wx_get_rts(struct net_device *dev,
106 struct iw_request_info *info,
107 union iwreq_data *wrqu, char *extra)
108{
109 struct r8192_priv *priv = ieee80211_priv(dev);
110 return ieee80211_wx_get_rts(priv->ieee80211,info,wrqu,extra);
111}
112
113static int r8192_wx_set_power(struct net_device *dev,
114 struct iw_request_info *info,
115 union iwreq_data *wrqu, char *extra)
116{
117 int ret;
118 struct r8192_priv *priv = ieee80211_priv(dev);
119
120 if (priv->bHwRadioOff)
121 return 0;
122
123 down(&priv->wx_sem);
124
125 ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra);
126
127 up(&priv->wx_sem);
128
129 return ret;
130}
131
132static int r8192_wx_get_power(struct net_device *dev,
133 struct iw_request_info *info,
134 union iwreq_data *wrqu, char *extra)
135{
136 struct r8192_priv *priv = ieee80211_priv(dev);
137 return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra);
138}
139
140static int r8192_wx_set_rawtx(struct net_device *dev,
141 struct iw_request_info *info,
142 union iwreq_data *wrqu, char *extra)
143{
144 struct r8192_priv *priv = ieee80211_priv(dev);
145 int ret;
146
147 if (priv->bHwRadioOff)
148 return 0;
149
150 down(&priv->wx_sem);
151
152 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
153
154 up(&priv->wx_sem);
155
156 return ret;
157
158}
159
160static int r8192_wx_force_reset(struct net_device *dev,
161 struct iw_request_info *info,
162 union iwreq_data *wrqu, char *extra)
163{
164 struct r8192_priv *priv = ieee80211_priv(dev);
165
166 down(&priv->wx_sem);
167
168 printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra);
169 priv->force_reset = *extra;
170 up(&priv->wx_sem);
171 return 0;
172
173}
174
175
176static int r8192_wx_set_crcmon(struct net_device *dev,
177 struct iw_request_info *info,
178 union iwreq_data *wrqu, char *extra)
179{
180 struct r8192_priv *priv = ieee80211_priv(dev);
181 int *parms = (int *)extra;
182 int enable = (parms[0] > 0);
183 short prev = priv->crcmon;
184
185 if (priv->bHwRadioOff)
186 return 0;
187
188 down(&priv->wx_sem);
189
190 if(enable)
191 priv->crcmon=1;
192 else
193 priv->crcmon=0;
194
195 DMESG("bad CRC in monitor mode are %s",
196 priv->crcmon ? "accepted" : "rejected");
197
198 if(prev != priv->crcmon && priv->up){
199 //rtl8180_down(dev);
200 //rtl8180_up(dev);
201 }
202
203 up(&priv->wx_sem);
204
205 return 0;
206}
207
208static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
209 union iwreq_data *wrqu, char *b)
210{
211 struct r8192_priv *priv = ieee80211_priv(dev);
212 RT_RF_POWER_STATE rtState;
213 int ret;
214
215 if (priv->bHwRadioOff)
216 return 0;
217
218 rtState = priv->eRFPowerState;
219 down(&priv->wx_sem);
220#ifdef ENABLE_IPS
221 if(wrqu->mode == IW_MODE_ADHOC){
222
223 if (priv->PowerSaveControl.bInactivePs) {
224 if(rtState == eRfOff){
225 if(priv->RfOffReason > RF_CHANGE_BY_IPS)
226 {
227 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
228 up(&priv->wx_sem);
229 return -1;
230 }
231 else{
232 RT_TRACE(COMP_ERR, "%s(): IPSLeave\n",__FUNCTION__);
233 down(&priv->ieee80211->ips_sem);
234 IPSLeave(priv);
235 up(&priv->ieee80211->ips_sem);
236 }
237 }
238 }
239 }
240#endif
241 ret = ieee80211_wx_set_mode(priv->ieee80211,a,wrqu,b);
242
243 //rtl8187_set_rxconf(dev);
244
245 up(&priv->wx_sem);
246 return ret;
247}
248
249struct iw_range_with_scan_capa
250{
251 /* Informative stuff (to choose between different interface) */
252 __u32 throughput; /* To give an idea... */
253 /* In theory this value should be the maximum benchmarked
254 * TCP/IP throughput, because with most of these devices the
255 * bit rate is meaningless (overhead an co) to estimate how
256 * fast the connection will go and pick the fastest one.
257 * I suggest people to play with Netperf or any benchmark...
258 */
259
260 /* NWID (or domain id) */
261 __u32 min_nwid; /* Minimal NWID we are able to set */
262 __u32 max_nwid; /* Maximal NWID we are able to set */
263
264 /* Old Frequency (backward compat - moved lower ) */
265 __u16 old_num_channels;
266 __u8 old_num_frequency;
267
268 /* Scan capabilities */
269 __u8 scan_capa;
270};
271static int rtl8180_wx_get_range(struct net_device *dev,
272 struct iw_request_info *info,
273 union iwreq_data *wrqu, char *extra)
274{
275 struct iw_range *range = (struct iw_range *)extra;
276 struct iw_range_with_scan_capa* tmp = (struct iw_range_with_scan_capa*)range;
277 struct r8192_priv *priv = ieee80211_priv(dev);
278 u16 val;
279 int i;
280
281 wrqu->data.length = sizeof(*range);
282 memset(range, 0, sizeof(*range));
283
284 /* Let's try to keep this struct in the same order as in
285 * linux/include/wireless.h
286 */
287
288 /* TODO: See what values we can set, and remove the ones we can't
289 * set, or fill them with some default data.
290 */
291
292 /* ~5 Mb/s real (802.11b) */
293 range->throughput = 130 * 1000 * 1000;
294
295 // TODO: Not used in 802.11b?
296// range->min_nwid; /* Minimal NWID we are able to set */
297 // TODO: Not used in 802.11b?
298// range->max_nwid; /* Maximal NWID we are able to set */
299
300 /* Old Frequency (backward compat - moved lower ) */
301// range->old_num_channels;
302// range->old_num_frequency;
303// range->old_freq[6]; /* Filler to keep "version" at the same offset */
304
305 range->max_qual.qual = 100;
306 /* TODO: Find real max RSSI and stick here */
307 range->max_qual.level = 0;
308 range->max_qual.noise = -98;
309 range->max_qual.updated = 7; /* Updated all three */
310
311 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
312 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
313 range->avg_qual.level = 20 + -98;
314 range->avg_qual.noise = 0;
315 range->avg_qual.updated = 7; /* Updated all three */
316
317 range->num_bitrates = RATE_COUNT;
318
319 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
320 range->bitrate[i] = rtl8180_rates[i];
321 }
322
323 range->min_frag = MIN_FRAG_THRESHOLD;
324 range->max_frag = MAX_FRAG_THRESHOLD;
325
326 range->min_pmp=0;
327 range->max_pmp = 5000000;
328 range->min_pmt = 0;
329 range->max_pmt = 65535*1000;
330 range->pmp_flags = IW_POWER_PERIOD;
331 range->pmt_flags = IW_POWER_TIMEOUT;
332 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
333 range->we_version_compiled = WIRELESS_EXT;
334 range->we_version_source = 18;
335
336// range->retry_capa; /* What retry options are supported */
337// range->retry_flags; /* How to decode max/min retry limit */
338// range->r_time_flags; /* How to decode max/min retry life */
339// range->min_retry; /* Minimal number of retries */
340// range->max_retry; /* Maximal number of retries */
341// range->min_r_time; /* Minimal retry lifetime */
342// range->max_r_time; /* Maximal retry lifetime */
343
344
345 for (i = 0, val = 0; i < 14; i++) {
346
347 // Include only legal frequencies for some countries
348#ifdef ENABLE_DOT11D
349 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
350#else
351 if ((priv->ieee80211->channel_map)[i+1]) {
352#endif
353 range->freq[val].i = i + 1;
354 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
355 range->freq[val].e = 1;
356 val++;
357 } else {
358 // FIXME: do we need to set anything for channels
359 // we don't use ?
360 }
361
362 if (val == IW_MAX_FREQUENCIES)
363 break;
364 }
365 range->num_frequency = val;
366 range->num_channels = val;
367
368 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
369 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
370
371 tmp->scan_capa = 0x01;
372 return 0;
373}
374
375
376static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
377 union iwreq_data *wrqu, char *b)
378{
379 struct r8192_priv *priv = ieee80211_priv(dev);
380 struct ieee80211_device* ieee = priv->ieee80211;
381 RT_RF_POWER_STATE rtState;
382 int ret;
383
384 if (priv->bHwRadioOff)
385 return 0;
386
387 rtState = priv->eRFPowerState;
388
389 if(!priv->up) return -ENETDOWN;
390 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
391 return -EAGAIN;
392
393 if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
394 {
395 struct iw_scan_req* req = (struct iw_scan_req*)b;
396 if (req->essid_len)
397 {
398 //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
399 ieee->current_network.ssid_len = req->essid_len;
400 memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
401 //printk("=====>network ssid:%s\n", ieee->current_network.ssid);
402 }
403 }
404
405 down(&priv->wx_sem);
406#ifdef ENABLE_IPS
407 priv->ieee80211->actscanning = true;
408 if(priv->ieee80211->state != IEEE80211_LINKED){
409 if (priv->PowerSaveControl.bInactivePs) {
410 if(rtState == eRfOff){
411 if(priv->RfOffReason > RF_CHANGE_BY_IPS)
412 {
413 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
414 up(&priv->wx_sem);
415 return -1;
416 }
417 else{
418 //RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__);
419 down(&priv->ieee80211->ips_sem);
420 IPSLeave(priv);
421 up(&priv->ieee80211->ips_sem);
422 }
423 }
424 }
425 priv->ieee80211->scanning = 0;
426 ieee80211_softmac_scan_syncro(priv->ieee80211);
427 ret = 0;
428 }
429 else
430#else
431
432 if(priv->ieee80211->state != IEEE80211_LINKED){
433 priv->ieee80211->scanning = 0;
434 ieee80211_softmac_scan_syncro(priv->ieee80211);
435 ret = 0;
436 }
437 else
438#endif
439 ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
440
441 up(&priv->wx_sem);
442 return ret;
443}
444
445
446static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
447 union iwreq_data *wrqu, char *b)
448{
449
450 int ret;
451 struct r8192_priv *priv = ieee80211_priv(dev);
452
453 if (priv->bHwRadioOff)
454 return 0;
455
456 if(!priv->up) return -ENETDOWN;
457
458 down(&priv->wx_sem);
459
460 ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
461
462 up(&priv->wx_sem);
463
464 return ret;
465}
466
467static int r8192_wx_set_essid(struct net_device *dev,
468 struct iw_request_info *a,
469 union iwreq_data *wrqu, char *b)
470{
471 struct r8192_priv *priv = ieee80211_priv(dev);
472 RT_RF_POWER_STATE rtState;
473 int ret;
474
475 if (priv->bHwRadioOff)
476 return 0;
477
478 rtState = priv->eRFPowerState;
479 down(&priv->wx_sem);
480
481#ifdef ENABLE_IPS
482 down(&priv->ieee80211->ips_sem);
483 IPSLeave(priv);
484 up(&priv->ieee80211->ips_sem);
485#endif
486 ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
487
488 up(&priv->wx_sem);
489
490 return ret;
491}
492
493
494
495
496static int r8192_wx_get_essid(struct net_device *dev,
497 struct iw_request_info *a,
498 union iwreq_data *wrqu, char *b)
499{
500 int ret;
501 struct r8192_priv *priv = ieee80211_priv(dev);
502
503 down(&priv->wx_sem);
504
505 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
506
507 up(&priv->wx_sem);
508
509 return ret;
510}
511
512
513static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
514 union iwreq_data *wrqu, char *b)
515{
516 int ret;
517 struct r8192_priv *priv = ieee80211_priv(dev);
518
519 if (priv->bHwRadioOff)
520 return 0;
521
522 down(&priv->wx_sem);
523
524 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
525
526 up(&priv->wx_sem);
527 return ret;
528}
529
530static int r8192_wx_get_name(struct net_device *dev,
531 struct iw_request_info *info,
532 union iwreq_data *wrqu, char *extra)
533{
534 struct r8192_priv *priv = ieee80211_priv(dev);
535 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
536}
537
538
539static int r8192_wx_set_frag(struct net_device *dev,
540 struct iw_request_info *info,
541 union iwreq_data *wrqu, char *extra)
542{
543 struct r8192_priv *priv = ieee80211_priv(dev);
544
545 if (priv->bHwRadioOff)
546 return 0;
547
548 if (wrqu->frag.disabled)
549 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
550 else {
551 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
552 wrqu->frag.value > MAX_FRAG_THRESHOLD)
553 return -EINVAL;
554
555 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
556 }
557
558 return 0;
559}
560
561
562static int r8192_wx_get_frag(struct net_device *dev,
563 struct iw_request_info *info,
564 union iwreq_data *wrqu, char *extra)
565{
566 struct r8192_priv *priv = ieee80211_priv(dev);
567
568 wrqu->frag.value = priv->ieee80211->fts;
569 wrqu->frag.fixed = 0; /* no auto select */
570 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
571
572 return 0;
573}
574
575
576static int r8192_wx_set_wap(struct net_device *dev,
577 struct iw_request_info *info,
578 union iwreq_data *awrq,
579 char *extra)
580{
581
582 int ret;
583 struct r8192_priv *priv = ieee80211_priv(dev);
584// struct sockaddr *temp = (struct sockaddr *)awrq;
585
586 if (priv->bHwRadioOff)
587 return 0;
588
589 down(&priv->wx_sem);
590
591#ifdef ENABLE_IPS
592 down(&priv->ieee80211->ips_sem);
593 IPSLeave(priv);
594 up(&priv->ieee80211->ips_sem);
595#endif
596 ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
597
598 up(&priv->wx_sem);
599
600 return ret;
601
602}
603
604
605static int r8192_wx_get_wap(struct net_device *dev,
606 struct iw_request_info *info,
607 union iwreq_data *wrqu, char *extra)
608{
609 struct r8192_priv *priv = ieee80211_priv(dev);
610
611 return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
612}
613
614
615static int r8192_wx_get_enc(struct net_device *dev,
616 struct iw_request_info *info,
617 union iwreq_data *wrqu, char *key)
618{
619 struct r8192_priv *priv = ieee80211_priv(dev);
620
621 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
622}
623
624static int r8192_wx_set_enc(struct net_device *dev,
625 struct iw_request_info *info,
626 union iwreq_data *wrqu, char *key)
627{
628 struct r8192_priv *priv = ieee80211_priv(dev);
629 int ret;
630
631 struct ieee80211_device *ieee = priv->ieee80211;
632 //u32 TargetContent;
633 u32 hwkey[4]={0,0,0,0};
634 u8 mask=0xff;
635 u32 key_idx=0;
636 u8 zero_addr[4][6] ={{0x00,0x00,0x00,0x00,0x00,0x00},
637 {0x00,0x00,0x00,0x00,0x00,0x01},
638 {0x00,0x00,0x00,0x00,0x00,0x02},
639 {0x00,0x00,0x00,0x00,0x00,0x03} };
640 int i;
641
642 if (priv->bHwRadioOff)
643 return 0;
644
645 if(!priv->up) return -ENETDOWN;
646
647 priv->ieee80211->wx_set_enc = 1;
648#ifdef ENABLE_IPS
649 down(&priv->ieee80211->ips_sem);
650 IPSLeave(priv);
651 up(&priv->ieee80211->ips_sem);
652#endif
653
654 down(&priv->wx_sem);
655
656 RT_TRACE(COMP_SEC, "Setting SW wep key\n");
657 ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
658
659 up(&priv->wx_sem);
660
661 //sometimes, the length is zero while we do not type key value
662 if(wrqu->encoding.length!=0){
663
664 for(i=0 ; i<4 ; i++){
665 hwkey[i] |= key[4*i+0]&mask;
666 if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
667 if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
668 hwkey[i] |= (key[4*i+1]&mask)<<8;
669 hwkey[i] |= (key[4*i+2]&mask)<<16;
670 hwkey[i] |= (key[4*i+3]&mask)<<24;
671 }
672
673 #define CONF_WEP40 0x4
674 #define CONF_WEP104 0x14
675
676 switch(wrqu->encoding.flags & IW_ENCODE_INDEX){
677 case 0: key_idx = ieee->tx_keyidx; break;
678 case 1: key_idx = 0; break;
679 case 2: key_idx = 1; break;
680 case 3: key_idx = 2; break;
681 case 4: key_idx = 3; break;
682 default: break;
683 }
684
685 //printk("-------====>length:%d, key_idx:%d, flag:%x\n", wrqu->encoding.length, key_idx, wrqu->encoding.flags);
686 if(wrqu->encoding.length==0x5){
687 ieee->pairwise_key_type = KEY_TYPE_WEP40;
688 EnableHWSecurityConfig8192(priv);
689 setKey(priv, key_idx, key_idx, KEY_TYPE_WEP40,
690 zero_addr[key_idx], 0, hwkey);
691 }
692
693 else if(wrqu->encoding.length==0xd){
694 ieee->pairwise_key_type = KEY_TYPE_WEP104;
695 EnableHWSecurityConfig8192(priv);
696 setKey(priv, key_idx, key_idx, KEY_TYPE_WEP104,
697 zero_addr[key_idx], 0, hwkey);
698 }
699 else printk("wrong type in WEP, not WEP40 and WEP104\n");
700 }
701
702 priv->ieee80211->wx_set_enc = 0;
703
704 return ret;
705}
706
707
708static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
709 iwreq_data *wrqu, char *p){
710
711 struct r8192_priv *priv = ieee80211_priv(dev);
712 int *parms=(int*)p;
713 int mode=parms[0];
714
715 priv->ieee80211->active_scan = mode;
716
717 return 1;
718}
719
720
721
722static int r8192_wx_set_retry(struct net_device *dev,
723 struct iw_request_info *info,
724 union iwreq_data *wrqu, char *extra)
725{
726 struct r8192_priv *priv = ieee80211_priv(dev);
727 int err = 0;
728
729 if (priv->bHwRadioOff)
730 return 0;
731
732 down(&priv->wx_sem);
733
734 if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
735 wrqu->retry.disabled){
736 err = -EINVAL;
737 goto exit;
738 }
739 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
740 err = -EINVAL;
741 goto exit;
742 }
743
744 if(wrqu->retry.value > R8180_MAX_RETRY){
745 err= -EINVAL;
746 goto exit;
747 }
748 if (wrqu->retry.flags & IW_RETRY_MAX) {
749 priv->retry_rts = wrqu->retry.value;
750 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
751
752 }else {
753 priv->retry_data = wrqu->retry.value;
754 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
755 }
756
757 /* FIXME !
758 * We might try to write directly the TX config register
759 * or to restart just the (R)TX process.
760 * I'm unsure if whole reset is really needed
761 */
762
763 rtl8192_commit(priv);
764 /*
765 if(priv->up){
766 rtl8180_rtx_disable(dev);
767 rtl8180_rx_enable(dev);
768 rtl8180_tx_enable(dev);
769
770 }
771 */
772exit:
773 up(&priv->wx_sem);
774
775 return err;
776}
777
778static int r8192_wx_get_retry(struct net_device *dev,
779 struct iw_request_info *info,
780 union iwreq_data *wrqu, char *extra)
781{
782 struct r8192_priv *priv = ieee80211_priv(dev);
783
784
785 wrqu->retry.disabled = 0; /* can't be disabled */
786
787 if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
788 IW_RETRY_LIFETIME)
789 return -EINVAL;
790
791 if (wrqu->retry.flags & IW_RETRY_MAX) {
792 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
793 wrqu->retry.value = priv->retry_rts;
794 } else {
795 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN;
796 wrqu->retry.value = priv->retry_data;
797 }
798 //DMESG("returning %d",wrqu->retry.value);
799
800
801 return 0;
802}
803
804static int r8192_wx_get_sens(struct net_device *dev,
805 struct iw_request_info *info,
806 union iwreq_data *wrqu, char *extra)
807{
808 struct r8192_priv *priv = ieee80211_priv(dev);
809 if(priv->rf_set_sens == NULL)
810 return -1; /* we have not this support for this radio */
811 wrqu->sens.value = priv->sens;
812 return 0;
813}
814
815
816static int r8192_wx_set_sens(struct net_device *dev,
817 struct iw_request_info *info,
818 union iwreq_data *wrqu, char *extra)
819{
820
821 struct r8192_priv *priv = ieee80211_priv(dev);
822
823 short err = 0;
824
825 if (priv->bHwRadioOff)
826 return 0;
827
828 down(&priv->wx_sem);
829 //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
830 if(priv->rf_set_sens == NULL) {
831 err= -1; /* we have not this support for this radio */
832 goto exit;
833 }
834 if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
835 priv->sens = wrqu->sens.value;
836 else
837 err= -EINVAL;
838
839exit:
840 up(&priv->wx_sem);
841
842 return err;
843}
844
845static int r8192_wx_set_enc_ext(struct net_device *dev,
846 struct iw_request_info *info,
847 union iwreq_data *wrqu, char *extra)
848{
849 int ret=0;
850 struct r8192_priv *priv = ieee80211_priv(dev);
851 struct ieee80211_device* ieee = priv->ieee80211;
852
853 if (priv->bHwRadioOff)
854 return 0;
855
856 down(&priv->wx_sem);
857
858 priv->ieee80211->wx_set_enc = 1;
859
860#ifdef ENABLE_IPS
861 down(&priv->ieee80211->ips_sem);
862 IPSLeave(priv);
863 up(&priv->ieee80211->ips_sem);
864#endif
865
866 ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
867
868 {
869 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
870 u8 zero[6] = {0};
871 u32 key[4] = {0};
872 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
873 struct iw_point *encoding = &wrqu->encoding;
874 u8 idx = 0, alg = 0, group = 0;
875
876 if ((encoding->flags & IW_ENCODE_DISABLED) ||
877 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
878 {
879 ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
880 CamResetAllEntry(priv);
881 goto end_hw_sec;
882 }
883 alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; // as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4;
884 idx = encoding->flags & IW_ENCODE_INDEX;
885 if (idx)
886 idx --;
887 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
888
889 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40))
890 {
891 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
892 alg = KEY_TYPE_WEP104;
893 ieee->pairwise_key_type = alg;
894 EnableHWSecurityConfig8192(priv);
895 }
896 memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
897
898 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
899 {
900 if (ext->key_len == 13)
901 ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
902 setKey(priv, idx, idx, alg, zero, 0, key);
903 }
904 else if (group)
905 {
906 ieee->group_key_type = alg;
907 setKey(priv, idx, idx, alg, broadcast_addr, 0, key);
908 }
909 else //pairwise key
910 {
911 if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
912 write_nic_byte(priv, 0x173, 1); //fix aes bug
913 }
914 setKey(priv, 4, idx, alg,
915 (u8*)ieee->ap_mac_addr, 0, key);
916 }
917
918
919 }
920
921end_hw_sec:
922 priv->ieee80211->wx_set_enc = 0;
923 up(&priv->wx_sem);
924 return ret;
925
926}
927static int r8192_wx_set_auth(struct net_device *dev,
928 struct iw_request_info *info,
929 union iwreq_data *data, char *extra)
930{
931 int ret=0;
932 //printk("====>%s()\n", __FUNCTION__);
933 struct r8192_priv *priv = ieee80211_priv(dev);
934
935 if (priv->bHwRadioOff)
936 return 0;
937
938 down(&priv->wx_sem);
939 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
940 up(&priv->wx_sem);
941 return ret;
942}
943
944static int r8192_wx_set_mlme(struct net_device *dev,
945 struct iw_request_info *info,
946 union iwreq_data *wrqu, char *extra)
947{
948 //printk("====>%s()\n", __FUNCTION__);
949
950 int ret=0;
951 struct r8192_priv *priv = ieee80211_priv(dev);
952
953 if (priv->bHwRadioOff)
954 return 0;
955
956 down(&priv->wx_sem);
957 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
958 up(&priv->wx_sem);
959 return ret;
960}
961
962static int r8192_wx_set_gen_ie(struct net_device *dev,
963 struct iw_request_info *info,
964 union iwreq_data *data, char *extra)
965{
966 //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
967 int ret=0;
968 struct r8192_priv *priv = ieee80211_priv(dev);
969
970 if (priv->bHwRadioOff)
971 return 0;
972
973 down(&priv->wx_sem);
974 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
975 up(&priv->wx_sem);
976 //printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
977 return ret;
978}
979
980static int dummy(struct net_device *dev, struct iw_request_info *a,
981 union iwreq_data *wrqu,char *b)
982{
983 return -1;
984}
985
986// check ac/dc status with the help of user space application */
987static int r8192_wx_adapter_power_status(struct net_device *dev,
988 struct iw_request_info *info,
989 union iwreq_data *wrqu, char *extra)
990{
991 struct r8192_priv *priv = ieee80211_priv(dev);
992#ifdef ENABLE_LPS
993 PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
994 struct ieee80211_device* ieee = priv->ieee80211;
995#endif
996 down(&priv->wx_sem);
997
998#ifdef ENABLE_LPS
999 RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra == 6)?"DC power":"AC power");
1000 // ieee->ps shall not be set under DC mode, otherwise it conflict
1001 // with Leisure power save mode setting.
1002 //
1003 if(*extra || priv->force_lps) {
1004 priv->ps_force = false;
1005 pPSC->bLeisurePs = true;
1006 } else {
1007 //LZM for PS-Poll AID issue. 090429
1008 if(priv->ieee80211->state == IEEE80211_LINKED)
1009 LeisurePSLeave(priv->ieee80211);
1010
1011 priv->ps_force = true;
1012 pPSC->bLeisurePs = false;
1013 ieee->ps = *extra;
1014 }
1015
1016#endif
1017 up(&priv->wx_sem);
1018 return 0;
1019
1020}
1021
1022
1023static iw_handler r8192_wx_handlers[] =
1024{
1025 NULL, /* SIOCSIWCOMMIT */
1026 r8192_wx_get_name, /* SIOCGIWNAME */
1027 dummy, /* SIOCSIWNWID */
1028 dummy, /* SIOCGIWNWID */
1029 r8192_wx_set_freq, /* SIOCSIWFREQ */
1030 r8192_wx_get_freq, /* SIOCGIWFREQ */
1031 r8192_wx_set_mode, /* SIOCSIWMODE */
1032 r8192_wx_get_mode, /* SIOCGIWMODE */
1033 r8192_wx_set_sens, /* SIOCSIWSENS */
1034 r8192_wx_get_sens, /* SIOCGIWSENS */
1035 NULL, /* SIOCSIWRANGE */
1036 rtl8180_wx_get_range, /* SIOCGIWRANGE */
1037 NULL, /* SIOCSIWPRIV */
1038 NULL, /* SIOCGIWPRIV */
1039 NULL, /* SIOCSIWSTATS */
1040 NULL, /* SIOCGIWSTATS */
1041 dummy, /* SIOCSIWSPY */
1042 dummy, /* SIOCGIWSPY */
1043 NULL, /* SIOCGIWTHRSPY */
1044 NULL, /* SIOCWIWTHRSPY */
1045 r8192_wx_set_wap, /* SIOCSIWAP */
1046 r8192_wx_get_wap, /* SIOCGIWAP */
1047 r8192_wx_set_mlme, /* MLME-- */
1048 dummy, /* SIOCGIWAPLIST -- depricated */
1049 r8192_wx_set_scan, /* SIOCSIWSCAN */
1050 r8192_wx_get_scan, /* SIOCGIWSCAN */
1051 r8192_wx_set_essid, /* SIOCSIWESSID */
1052 r8192_wx_get_essid, /* SIOCGIWESSID */
1053 dummy, /* SIOCSIWNICKN */
1054 dummy, /* SIOCGIWNICKN */
1055 NULL, /* -- hole -- */
1056 NULL, /* -- hole -- */
1057 r8192_wx_set_rate, /* SIOCSIWRATE */
1058 r8192_wx_get_rate, /* SIOCGIWRATE */
1059 r8192_wx_set_rts, /* SIOCSIWRTS */
1060 r8192_wx_get_rts, /* SIOCGIWRTS */
1061 r8192_wx_set_frag, /* SIOCSIWFRAG */
1062 r8192_wx_get_frag, /* SIOCGIWFRAG */
1063 dummy, /* SIOCSIWTXPOW */
1064 dummy, /* SIOCGIWTXPOW */
1065 r8192_wx_set_retry, /* SIOCSIWRETRY */
1066 r8192_wx_get_retry, /* SIOCGIWRETRY */
1067 r8192_wx_set_enc, /* SIOCSIWENCODE */
1068 r8192_wx_get_enc, /* SIOCGIWENCODE */
1069 r8192_wx_set_power, /* SIOCSIWPOWER */
1070 r8192_wx_get_power, /* SIOCGIWPOWER */
1071 NULL, /*---hole---*/
1072 NULL, /*---hole---*/
1073 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */
1074 NULL, /* SIOCSIWGENIE */
1075 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */
1076 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */
1077 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
1078 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */
1079 NULL, /* SIOCSIWPMKSA */
1080 NULL, /*---hole---*/
1081
1082};
1083
1084
1085static const struct iw_priv_args r8192_private_args[] = {
1086
1087 {
1088 SIOCIWFIRSTPRIV + 0x0,
1089 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1090 },
1091
1092 {
1093 SIOCIWFIRSTPRIV + 0x1,
1094 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1095
1096 },
1097 {
1098 SIOCIWFIRSTPRIV + 0x2,
1099 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1100 }
1101 ,
1102 {
1103 SIOCIWFIRSTPRIV + 0x3,
1104 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
1105
1106 }
1107 ,
1108 {
1109 SIOCIWFIRSTPRIV + 0x4,
1110 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
1111 "set_power"
1112 }
1113
1114};
1115
1116
1117static iw_handler r8192_private_handler[] = {
1118 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
1119 r8192_wx_set_scan_type,
1120 r8192_wx_set_rawtx,
1121 r8192_wx_force_reset,
1122 r8192_wx_adapter_power_status,
1123};
1124
1125static struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
1126{
1127 struct r8192_priv *priv = ieee80211_priv(dev);
1128 struct ieee80211_device* ieee = priv->ieee80211;
1129 struct iw_statistics* wstats = &priv->wstats;
1130 int tmp_level = 0;
1131 int tmp_qual = 0;
1132 int tmp_noise = 0;
1133 if(ieee->state < IEEE80211_LINKED)
1134 {
1135 wstats->qual.qual = 0;
1136 wstats->qual.level = 0;
1137 wstats->qual.noise = 0;
1138 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1139 return wstats;
1140 }
1141
1142 tmp_level = (&ieee->current_network)->stats.rssi;
1143 tmp_qual = (&ieee->current_network)->stats.signal;
1144 tmp_noise = (&ieee->current_network)->stats.noise;
1145 //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1146
1147 wstats->qual.level = tmp_level;
1148 wstats->qual.qual = tmp_qual;
1149 wstats->qual.noise = tmp_noise;
1150 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1151 return wstats;
1152}
1153
1154
1155struct iw_handler_def r8192_wx_handlers_def={
1156 .standard = r8192_wx_handlers,
1157 .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
1158 .private = r8192_private_handler,
1159 .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
1160 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1161 .get_wireless_stats = r8192_get_wireless_stats,
1162 .private_args = (struct iw_priv_args *)r8192_private_args,
1163};
diff --git a/drivers/staging/rtl8192e/r8192E_wx.h b/drivers/staging/rtl8192e/r8192E_wx.h
new file mode 100644
index 00000000000..25f06c165d4
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8192E_wx.h
@@ -0,0 +1,18 @@
1/*
2 This is part of rtl8180 OpenSource driver - v 0.3
3 Copyright (C) Andrea Merello 2004 <andreamrl@tiscali.it>
4 Released under the terms of GPL (General Public Licence)
5
6 Parts of this driver are based on the GPL part of the official realtek driver
7 Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
8 Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
9
10 We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
11*/
12
13/* this file (will) contains wireless extension handlers*/
14
15#ifndef R8180_WX_H
16#define R8180_WX_H
17extern struct iw_handler_def r8192_wx_handlers_def;
18#endif
diff --git a/drivers/staging/rtl8192e/r8192_pm.c b/drivers/staging/rtl8192e/r8192_pm.c
new file mode 100644
index 00000000000..7bcc4a35099
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8192_pm.c
@@ -0,0 +1,123 @@
1/*
2 Power management interface routines.
3 Written by Mariusz Matuszek.
4 This code is currently just a placeholder for later work and
5 does not do anything useful.
6
7 This is part of rtl8180 OpenSource driver.
8 Copyright (C) Andrea Merello 2004 <andreamrl@tiscali.it>
9 Released under the terms of GPL (General Public Licence)
10*/
11
12#include "r8192E.h"
13#include "r8192E_hw.h"
14#include "r8192_pm.h"
15#include "r8190_rtl8256.h"
16
17int rtl8192E_save_state (struct pci_dev *dev, pm_message_t state)
18{
19 printk(KERN_NOTICE "r8192E save state call (state %u).\n", state.event);
20 return -EAGAIN;
21}
22
23
24int rtl8192E_suspend (struct pci_dev *pdev, pm_message_t state)
25{
26 struct net_device *dev = pci_get_drvdata(pdev);
27 struct r8192_priv *priv = ieee80211_priv(dev);
28 u32 ulRegRead;
29
30 RT_TRACE(COMP_POWER, "============> r8192E suspend call.\n");
31 if (!netif_running(dev))
32 goto out_pci_suspend;
33
34 if (dev->netdev_ops->ndo_stop)
35 dev->netdev_ops->ndo_stop(dev);
36
37 // Call MgntActSet_RF_State instead to prevent RF config race condition.
38 if(!priv->ieee80211->bSupportRemoteWakeUp) {
39 MgntActSet_RF_State(priv, eRfOff, RF_CHANGE_BY_INIT);
40 // 2006.11.30. System reset bit
41 ulRegRead = read_nic_dword(priv, CPU_GEN);
42 ulRegRead|=CPU_GEN_SYSTEM_RESET;
43 write_nic_dword(priv, CPU_GEN, ulRegRead);
44 } else {
45 //2008.06.03 for WOL
46 write_nic_dword(priv, WFCRC0, 0xffffffff);
47 write_nic_dword(priv, WFCRC1, 0xffffffff);
48 write_nic_dword(priv, WFCRC2, 0xffffffff);
49 //Write PMR register
50 write_nic_byte(priv, PMR, 0x5);
51 //Disable tx, enanble rx
52 write_nic_byte(priv, MacBlkCtrl, 0xa);
53 }
54
55out_pci_suspend:
56 RT_TRACE(COMP_POWER, "r8192E support WOL call??????????????????????\n");
57 if(priv->ieee80211->bSupportRemoteWakeUp) {
58 RT_TRACE(COMP_POWER, "r8192E support WOL call!!!!!!!!!!!!!!!!!!.\n");
59 }
60 netif_device_detach(dev);
61 pci_save_state(pdev);
62 pci_disable_device(pdev);
63 pci_enable_wake(pdev, pci_choose_state(pdev,state),
64 priv->ieee80211->bSupportRemoteWakeUp?1:0);
65 pci_set_power_state(pdev,pci_choose_state(pdev,state));
66
67 return 0;
68}
69
70int rtl8192E_resume (struct pci_dev *pdev)
71{
72 struct net_device *dev = pci_get_drvdata(pdev);
73 int err;
74 u32 val;
75
76 RT_TRACE(COMP_POWER, "================>r8192E resume call.\n");
77
78 pci_set_power_state(pdev, PCI_D0);
79
80 err = pci_enable_device(pdev);
81 if(err) {
82 printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
83 dev->name);
84 return err;
85 }
86
87 pci_restore_state(pdev);
88
89 /*
90 * Suspend/Resume resets the PCI configuration space, so we have to
91 * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
92 * from interfering with C3 CPU state. pci_restore_state won't help
93 * here since it only restores the first 64 bytes pci config header.
94 */
95 pci_read_config_dword(pdev, 0x40, &val);
96 if ((val & 0x0000ff00) != 0) {
97 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
98 }
99
100
101
102 pci_enable_wake(pdev, PCI_D0, 0);
103
104 if(!netif_running(dev))
105 goto out;
106
107 netif_device_attach(dev);
108
109 if (dev->netdev_ops->ndo_open)
110 dev->netdev_ops->ndo_open(dev);
111
112out:
113 RT_TRACE(COMP_POWER, "<================r8192E resume call.\n");
114 return 0;
115}
116
117
118int rtl8192E_enable_wake (struct pci_dev *dev, pm_message_t state, int enable)
119{
120 printk(KERN_NOTICE "r8192E enable wake call (state %u, enable %d).\n",
121 state.event, enable);
122 return -EAGAIN;
123}
diff --git a/drivers/staging/rtl8192e/r8192_pm.h b/drivers/staging/rtl8192e/r8192_pm.h
new file mode 100644
index 00000000000..4da9b464b41
--- /dev/null
+++ b/drivers/staging/rtl8192e/r8192_pm.h
@@ -0,0 +1,24 @@
1/*
2 Power management interface routines.
3 Written by Mariusz Matuszek.
4 This code is currently just a placeholder for later work and
5 does not do anything useful.
6
7 This is part of rtl8180 OpenSource driver.
8 Copyright (C) Andrea Merello 2004 <andreamrl@tiscali.it>
9 Released under the terms of GPL (General Public Licence)
10
11*/
12
13#ifndef R8192E_PM_H
14#define R8192E_PM_H
15
16#include <linux/types.h>
17#include <linux/pci.h>
18
19int rtl8192E_save_state (struct pci_dev *dev, pm_message_t state);
20int rtl8192E_suspend (struct pci_dev *dev, pm_message_t state);
21int rtl8192E_resume (struct pci_dev *dev);
22int rtl8192E_enable_wake (struct pci_dev *dev, pm_message_t state, int enable);
23
24#endif //R8192E_PM_H
diff --git a/drivers/staging/rtl8192e/r819xE_cmdpkt.c b/drivers/staging/rtl8192e/r819xE_cmdpkt.c
new file mode 100644
index 00000000000..756e0660bbe
--- /dev/null
+++ b/drivers/staging/rtl8192e/r819xE_cmdpkt.c
@@ -0,0 +1,444 @@
1/******************************************************************************
2
3 (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved.
4
5 Module: r819xusb_cmdpkt.c (RTL8190 TX/RX command packet handler Source C File)
6
7 Note: The module is responsible for handling TX and RX command packet.
8 1. TX : Send set and query configuration command packet.
9 2. RX : Receive tx feedback, beacon state, query configuration
10 command packet.
11
12 Function:
13
14 Export:
15
16 Abbrev:
17
18 History:
19 Data Who Remark
20
21 05/06/2008 amy Create initial version porting from windows driver.
22
23******************************************************************************/
24#include "r8192E.h"
25#include "r8192E_hw.h"
26#include "r819xE_cmdpkt.h"
27
28/*
29 * Driver internal module can call the API to send message to
30 * firmware side. For example, you can send a debug command packet.
31 * Or you can send a request for FW to modify RLX4181 LBUS HW bank.
32 * Otherwise, you can change MAC/PHT/RF register by firmware at
33 * run time. We do not support message more than one segment now.
34 */
35RT_STATUS cmpk_message_handle_tx(
36 struct r8192_priv *priv,
37 u8* code_virtual_address,
38 u32 packettype,
39 u32 buffer_len)
40{
41 RT_STATUS rt_status = RT_STATUS_SUCCESS;
42 u16 frag_threshold;
43 u16 frag_length = 0, frag_offset = 0;
44 rt_firmware *pfirmware = priv->pFirmware;
45 struct sk_buff *skb;
46 unsigned char *seg_ptr;
47 cb_desc *tcb_desc;
48 u8 bLastIniPkt;
49
50 PTX_FWINFO_8190PCI pTxFwInfo = NULL;
51 int i;
52
53 RT_TRACE(COMP_CMDPKT,"%s(),buffer_len is %d\n",__FUNCTION__,buffer_len);
54 firmware_init_param(priv);
55 //Fragmentation might be required
56 frag_threshold = pfirmware->cmdpacket_frag_thresold;
57 do {
58 if((buffer_len - frag_offset) > frag_threshold) {
59 frag_length = frag_threshold ;
60 bLastIniPkt = 0;
61
62 } else {
63 frag_length =(u16)(buffer_len - frag_offset);
64 bLastIniPkt = 1;
65
66 }
67
68 /* Allocate skb buffer to contain firmware info and tx descriptor info
69 * add 4 to avoid packet appending overflow.
70 * */
71 skb = dev_alloc_skb(frag_length + priv->ieee80211->tx_headroom + 4);
72 if(skb == NULL) {
73 rt_status = RT_STATUS_FAILURE;
74 goto Failed;
75 }
76
77 tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
78 tcb_desc->queue_index = TXCMD_QUEUE;
79 tcb_desc->bCmdOrInit = packettype;
80 tcb_desc->bLastIniPkt = bLastIniPkt;
81 tcb_desc->pkt_size = frag_length;
82
83 //seg_ptr = skb_put(skb, frag_length + priv->ieee80211->tx_headroom);
84 seg_ptr = skb_put(skb, priv->ieee80211->tx_headroom);
85
86 pTxFwInfo = (PTX_FWINFO_8190PCI)seg_ptr;
87 memset(pTxFwInfo,0,sizeof(TX_FWINFO_8190PCI));
88 memset(pTxFwInfo,0x12,8);
89
90 seg_ptr +=sizeof(TX_FWINFO_8190PCI);
91
92 /*
93 * Transform from little endian to big endian
94 * and pending zero
95 */
96 seg_ptr = skb_tail_pointer(skb);
97 for(i=0 ; i < frag_length; i+=4) {
98 *seg_ptr++ = ((i+0)<frag_length)?code_virtual_address[i+3]:0;
99 *seg_ptr++ = ((i+1)<frag_length)?code_virtual_address[i+2]:0;
100 *seg_ptr++ = ((i+2)<frag_length)?code_virtual_address[i+1]:0;
101 *seg_ptr++ = ((i+3)<frag_length)?code_virtual_address[i+0]:0;
102 }
103 skb_put(skb, i);
104 priv->ieee80211->softmac_hard_start_xmit(skb, priv->ieee80211);
105
106 code_virtual_address += frag_length;
107 frag_offset += frag_length;
108
109 }while(frag_offset < buffer_len);
110
111Failed:
112 return rt_status;
113}
114
115static void cmpk_count_txstatistic(struct r8192_priv *priv, cmpk_txfb_t *pstx_fb)
116{
117#ifdef ENABLE_PS
118 RT_RF_POWER_STATE rtState;
119
120 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
121
122 // When RF is off, we should not count the packet for hw/sw synchronize
123 // reason, ie. there may be a duration while sw switch is changed and hw
124 // switch is being changed. 2006.12.04, by shien chang.
125 if (rtState == eRfOff)
126 {
127 return;
128 }
129#endif
130
131#ifdef TODO
132 if(pAdapter->bInHctTest)
133 return;
134#endif
135 /* We can not know the packet length and transmit type: broadcast or uni
136 or multicast. So the relative statistics must be collected in tx
137 feedback info. */
138 if (pstx_fb->tok)
139 {
140 priv->stats.txoktotal++;
141
142 /* We can not make sure broadcast/multicast or unicast mode. */
143 if (pstx_fb->pkt_type != PACKET_MULTICAST &&
144 pstx_fb->pkt_type != PACKET_BROADCAST) {
145 priv->stats.txbytesunicast += pstx_fb->pkt_length;
146 }
147 }
148}
149
150
151
152/*
153 * The function is responsible for extract the message inside TX
154 * feedbck message from firmware. It will contain dedicated info in
155 * ws-06-0063-rtl8190-command-packet-specification. Please
156 * refer to chapter "TX Feedback Element". We have to read 20 bytes
157 * in the command packet.
158 */
159static void cmpk_handle_tx_feedback(struct r8192_priv *priv, u8 *pmsg)
160{
161 cmpk_txfb_t rx_tx_fb; /* */
162
163 priv->stats.txfeedback++;
164
165 memcpy((u8*)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t));
166 /* Use tx feedback info to count TX statistics. */
167 cmpk_count_txstatistic(priv, &rx_tx_fb);
168}
169
170
171/*
172 * The function is responsible for extract the message from
173 * firmware. It will contain dedicated info in
174 * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
175 * Please refer to chapter "Interrupt Status Element".
176 */
177static void cmpk_handle_interrupt_status(struct r8192_priv *priv, u8 *pmsg)
178{
179 cmpk_intr_sta_t rx_intr_status; /* */
180
181 DMESG("---> cmpk_Handle_Interrupt_Status()\n");
182
183 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
184 /* It seems that FW use big endian(MIPS) and DRV use little endian in
185 windows OS. So we have to read the content byte by byte or transfer
186 endian type before copy the message copy. */
187 //rx_bcn_state.Element_ID = pMsg[0];
188 //rx_bcn_state.Length = pMsg[1];
189 rx_intr_status.length = pmsg[1];
190 if (rx_intr_status.length != (sizeof(cmpk_intr_sta_t) - 2))
191 {
192 DMESG("cmpk_Handle_Interrupt_Status: wrong length!\n");
193 return;
194 }
195
196
197 // Statistics of beacon for ad-hoc mode.
198 if( priv->ieee80211->iw_mode == IW_MODE_ADHOC)
199 {
200 //2 maybe need endian transform?
201 rx_intr_status.interrupt_status = *((u32 *)(pmsg + 4));
202 //rx_intr_status.InterruptStatus = N2H4BYTE(*((UINT32 *)(pMsg + 4)));
203
204 DMESG("interrupt status = 0x%x\n", rx_intr_status.interrupt_status);
205
206 if (rx_intr_status.interrupt_status & ISR_TxBcnOk)
207 {
208 priv->ieee80211->bibsscoordinator = true;
209 priv->stats.txbeaconokint++;
210 }
211 else if (rx_intr_status.interrupt_status & ISR_TxBcnErr)
212 {
213 priv->ieee80211->bibsscoordinator = false;
214 priv->stats.txbeaconerr++;
215 }
216 }
217
218 // Other informations in interrupt status we need?
219
220
221 DMESG("<---- cmpk_handle_interrupt_status()\n");
222
223}
224
225
226/*
227 * The function is responsible for extract the message from
228 * firmware. It will contain dedicated info in
229 * ws-06-0063-rtl8190-command-packet-specification. Please
230 * refer to chapter "Beacon State Element".
231 */
232static void cmpk_handle_query_config_rx(struct r8192_priv *priv, u8 *pmsg)
233{
234 cmpk_query_cfg_t rx_query_cfg; /* */
235
236 /* 0. Display received message. */
237 //cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
238
239 /* 1. Extract TX feedback info from RFD to temp structure buffer. */
240 /* It seems that FW use big endian(MIPS) and DRV use little endian in
241 windows OS. So we have to read the content byte by byte or transfer
242 endian type before copy the message copy. */
243 //rx_query_cfg.Element_ID = pMsg[0];
244 //rx_query_cfg.Length = pMsg[1];
245 rx_query_cfg.cfg_action = (pmsg[4] & 0x80000000)>>31;
246 rx_query_cfg.cfg_type = (pmsg[4] & 0x60) >> 5;
247 rx_query_cfg.cfg_size = (pmsg[4] & 0x18) >> 3;
248 rx_query_cfg.cfg_page = (pmsg[6] & 0x0F) >> 0;
249 rx_query_cfg.cfg_offset = pmsg[7];
250 rx_query_cfg.value = (pmsg[8] << 24) | (pmsg[9] << 16) |
251 (pmsg[10] << 8) | (pmsg[11] << 0);
252 rx_query_cfg.mask = (pmsg[12] << 24) | (pmsg[13] << 16) |
253 (pmsg[14] << 8) | (pmsg[15] << 0);
254
255}
256
257
258/*
259 * Count aggregated tx status from firmwar of one type rx command
260 * packet element id = RX_TX_STATUS.
261 */
262static void cmpk_count_tx_status(struct r8192_priv *priv, cmpk_tx_status_t *pstx_status)
263{
264
265#ifdef ENABLE_PS
266
267 RT_RF_POWER_STATE rtstate;
268
269 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
270
271 // When RF is off, we should not count the packet for hw/sw synchronize
272 // reason, ie. there may be a duration while sw switch is changed and hw
273 // switch is being changed. 2006.12.04, by shien chang.
274 if (rtState == eRfOff)
275 {
276 return;
277 }
278#endif
279
280 priv->stats.txfeedbackok += pstx_status->txok;
281 priv->stats.txoktotal += pstx_status->txok;
282
283 priv->stats.txbytesunicast += pstx_status->txuclength;
284}
285
286
287
288/*
289 * Firmware add a new tx feedback status to reduce rx command
290 * packet buffer operation load.
291 */
292static void cmpk_handle_tx_status(struct r8192_priv *priv, u8 *pmsg)
293{
294 cmpk_tx_status_t rx_tx_sts; /* */
295
296 memcpy((void*)&rx_tx_sts, (void*)pmsg, sizeof(cmpk_tx_status_t));
297 /* 2. Use tx feedback info to count TX statistics. */
298 cmpk_count_tx_status(priv, &rx_tx_sts);
299
300}
301
302
303/* Firmware add a new tx rate history */
304static void cmpk_handle_tx_rate_history(struct r8192_priv *priv, u8 *pmsg)
305{
306 u8 i;
307 u16 length = sizeof(cmpk_tx_rahis_t);
308 u32 *ptemp;
309
310#ifdef ENABLE_PS
311 pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
312
313 // When RF is off, we should not count the packet for hw/sw synchronize
314 // reason, ie. there may be a duration while sw switch is changed and hw
315 // switch is being changed. 2006.12.04, by shien chang.
316 if (rtState == eRfOff)
317 {
318 return;
319 }
320#endif
321
322 ptemp = (u32 *)pmsg;
323
324 //
325 // Do endian transfer to word alignment(16 bits) for windows system.
326 // You must do different endian transfer for linux and MAC OS
327 //
328 for (i = 0; i < (length/4); i++)
329 {
330 u16 temp1, temp2;
331
332 temp1 = ptemp[i]&0x0000FFFF;
333 temp2 = ptemp[i]>>16;
334 ptemp[i] = (temp1<<16)|temp2;
335 }
336}
337
338
339/*
340 * In the function, we will capture different RX command packet
341 * info. Every RX command packet element has different message
342 * length and meaning in content. We only support three type of RX
343 * command packet now. Please refer to document
344 * ws-06-0063-rtl8190-command-packet-specification.
345 */
346u32 cmpk_message_handle_rx(struct r8192_priv *priv, struct ieee80211_rx_stats *pstats)
347{
348// u32 debug_level = DBG_LOUD;
349 int total_length;
350 u8 cmd_length, exe_cnt = 0;
351 u8 element_id;
352 u8 *pcmd_buff;
353
354 RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx()\n");
355
356 /* 0. Check inpt arguments. If is is a command queue message or pointer is
357 null. */
358 if (/*(prfd->queue_id != CMPK_RX_QUEUE_ID) || */(pstats== NULL))
359 {
360 /* Print error message. */
361 /*RT_TRACE(COMP_SEND, DebugLevel,
362 ("\n\r[CMPK]-->Err queue id or pointer"));*/
363 return 0; /* This is not a command packet. */
364 }
365
366 /* 1. Read received command packet message length from RFD. */
367 total_length = pstats->Length;
368
369 /* 2. Read virtual address from RFD. */
370 pcmd_buff = pstats->virtual_address;
371
372 /* 3. Read command pakcet element id and length. */
373 element_id = pcmd_buff[0];
374 /*RT_TRACE(COMP_SEND, DebugLevel,
375 ("\n\r[CMPK]-->element ID=%d Len=%d", element_id, total_length));*/
376
377 /* 4. Check every received command packet conent according to different
378 element type. Because FW may aggregate RX command packet to minimize
379 transmit time between DRV and FW.*/
380 // Add a counter to prevent to locked in the loop too long
381 while (total_length > 0 || exe_cnt++ >100)
382 {
383 /* 2007/01/17 MH We support aggregation of different cmd in the same packet. */
384 element_id = pcmd_buff[0];
385
386 switch(element_id)
387 {
388 case RX_TX_FEEDBACK:
389
390 RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_FEEDBACK\n");
391 cmpk_handle_tx_feedback(priv, pcmd_buff);
392 cmd_length = CMPK_RX_TX_FB_SIZE;
393 break;
394
395 case RX_INTERRUPT_STATUS:
396
397 RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_INTERRUPT_STATUS\n");
398 cmpk_handle_interrupt_status(priv, pcmd_buff);
399 cmd_length = sizeof(cmpk_intr_sta_t);
400 break;
401
402 case BOTH_QUERY_CONFIG:
403
404 RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():BOTH_QUERY_CONFIG\n");
405 cmpk_handle_query_config_rx(priv, pcmd_buff);
406 cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
407 break;
408
409 case RX_TX_STATUS:
410
411 RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_STATUS\n");
412 cmpk_handle_tx_status(priv, pcmd_buff);
413 cmd_length = CMPK_RX_TX_STS_SIZE;
414 break;
415
416 case RX_TX_PER_PKT_FEEDBACK:
417 // You must at lease add a switch case element here,
418 // Otherwise, we will jump to default case.
419 //DbgPrint("CCX Test\r\n");
420 RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_PER_PKT_FEEDBACK\n");
421 cmd_length = CMPK_RX_TX_FB_SIZE;
422 break;
423
424 case RX_TX_RATE_HISTORY:
425 //DbgPrint(" rx tx rate history\r\n");
426
427 RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_HISTORY\n");
428 cmpk_handle_tx_rate_history(priv, pcmd_buff);
429 cmd_length = CMPK_TX_RAHIS_SIZE;
430 break;
431
432 default:
433
434 RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():unknown CMD Element\n");
435 return 1; /* This is a command packet. */
436 }
437
438 total_length -= cmd_length;
439 pcmd_buff += cmd_length;
440 } /* while (total_length > 0) */
441 return 1; /* This is a command packet. */
442
443 RT_TRACE(COMP_EVENTS, "<----cmpk_message_handle_rx()\n");
444}
diff --git a/drivers/staging/rtl8192e/r819xE_cmdpkt.h b/drivers/staging/rtl8192e/r819xE_cmdpkt.h
new file mode 100644
index 00000000000..312e4f84ded
--- /dev/null
+++ b/drivers/staging/rtl8192e/r819xE_cmdpkt.h
@@ -0,0 +1,207 @@
1#ifndef R819XUSB_CMDPKT_H
2#define R819XUSB_CMDPKT_H
3/* Different command packet have dedicated message length and definition. */
4#define CMPK_RX_TX_FB_SIZE sizeof(cmpk_txfb_t) //20
5#define CMPK_TX_SET_CONFIG_SIZE sizeof(cmpk_set_cfg_t) //16
6#define CMPK_BOTH_QUERY_CONFIG_SIZE sizeof(cmpk_set_cfg_t) //16
7#define CMPK_RX_TX_STS_SIZE sizeof(cmpk_tx_status_t)//
8#define CMPK_RX_DBG_MSG_SIZE sizeof(cmpk_rx_dbginfo_t)//
9#define CMPK_TX_RAHIS_SIZE sizeof(cmpk_tx_rahis_t)
10
11/* 2008/05/08 amy For USB constant. */
12#define ISR_TxBcnOk BIT27 // Transmit Beacon OK
13#define ISR_TxBcnErr BIT26 // Transmit Beacon Error
14#define ISR_BcnTimerIntr BIT13 // Beacon Timer Interrupt
15
16#if 0
17/* Define packet type. */
18typedef enum tag_packet_type
19{
20 PACKET_BROADCAST,
21 PACKET_MULTICAST,
22 PACKET_UNICAST,
23 PACKET_TYPE_MAX
24}cmpk_pkt_type_e;
25#endif
26
27/* Define element ID of command packet. */
28
29/*------------------------------Define structure----------------------------*/
30/* Define different command packet structure. */
31/* 1. RX side: TX feedback packet. */
32typedef struct tag_cmd_pkt_tx_feedback
33{
34 // DWORD 0
35 u8 element_id; /* Command packet type. */
36 u8 length; /* Command packet length. */
37 /* 2007/07/05 MH Change tx feedback info field. */
38 /*------TX Feedback Info Field */
39 u8 TID:4; /* */
40 u8 fail_reason:3; /* */
41 u8 tok:1; /* Transmit ok. */
42 u8 reserve1:4; /* */
43 u8 pkt_type:2; /* */
44 u8 bandwidth:1; /* */
45 u8 qos_pkt:1; /* */
46
47 // DWORD 1
48 u8 reserve2; /* */
49 /*------TX Feedback Info Field */
50 u8 retry_cnt; /* */
51 u16 pkt_id; /* */
52
53 // DWORD 3
54 u16 seq_num; /* */
55 u8 s_rate; /* Start rate. */
56 u8 f_rate; /* Final rate. */
57
58 // DWORD 4
59 u8 s_rts_rate; /* */
60 u8 f_rts_rate; /* */
61 u16 pkt_length; /* */
62
63 // DWORD 5
64 u16 reserve3; /* */
65 u16 duration; /* */
66}cmpk_txfb_t;
67
68/* 2. RX side: Interrupt status packet. It includes Beacon State,
69 Beacon Timer Interrupt and other useful informations in MAC ISR Reg. */
70typedef struct tag_cmd_pkt_interrupt_status
71{
72 u8 element_id; /* Command packet type. */
73 u8 length; /* Command packet length. */
74 u16 reserve;
75 u32 interrupt_status; /* Interrupt Status. */
76}cmpk_intr_sta_t;
77
78
79/* 3. TX side: Set configuration packet. */
80typedef struct tag_cmd_pkt_set_configuration
81{
82 u8 element_id; /* Command packet type. */
83 u8 length; /* Command packet length. */
84 u16 reserve1; /* */
85 u8 cfg_reserve1:3;
86 u8 cfg_size:2; /* Configuration info. */
87 u8 cfg_type:2; /* Configuration info. */
88 u8 cfg_action:1; /* Configuration info. */
89 u8 cfg_reserve2; /* Configuration info. */
90 u8 cfg_page:4; /* Configuration info. */
91 u8 cfg_reserve3:4; /* Configuration info. */
92 u8 cfg_offset; /* Configuration info. */
93 u32 value; /* */
94 u32 mask; /* */
95}cmpk_set_cfg_t;
96
97/* 4. Both side : TX/RX query configuraton packet. The query structure is the
98 same as set configuration. */
99#define cmpk_query_cfg_t cmpk_set_cfg_t
100
101/* 5. Multi packet feedback status. */
102typedef struct tag_tx_stats_feedback // PJ quick rxcmd 09042007
103{
104 // For endian transfer --> Driver will not the same as firmware structure.
105 // DW 0
106 u16 reserve1;
107 u8 length; // Command packet length
108 u8 element_id; // Command packet type
109
110 // DW 1
111 u16 txfail; // Tx Fail count
112 u16 txok; // Tx ok count
113
114 // DW 2
115 u16 txmcok; // tx multicast
116 u16 txretry; // Tx Retry count
117
118 // DW 3
119 u16 txucok; // tx unicast
120 u16 txbcok; // tx broadcast
121
122 // DW 4
123 u16 txbcfail; //
124 u16 txmcfail; //
125
126 // DW 5
127 u16 reserve2; //
128 u16 txucfail; //
129
130 // DW 6-8
131 u32 txmclength;
132 u32 txbclength;
133 u32 txuclength;
134
135 // DW 9
136 u16 reserve3_23;
137 u8 reserve3_1;
138 u8 rate;
139}__attribute__((packed)) cmpk_tx_status_t;
140
141/* 6. Debug feedback message. */
142/* 2007/10/23 MH Define RX debug message */
143typedef struct tag_rx_debug_message_feedback
144{
145 // For endian transfer --> for driver
146 // DW 0
147 u16 reserve1;
148 u8 length; // Command packet length
149 u8 element_id; // Command packet type
150
151 // DW 1-??
152 // Variable debug message.
153
154}cmpk_rx_dbginfo_t;
155
156/* 2008/03/20 MH Define transmit rate history. For big endian format. */
157typedef struct tag_tx_rate_history
158{
159 // For endian transfer --> for driver
160 // DW 0
161 u8 element_id; // Command packet type
162 u8 length; // Command packet length
163 u16 reserved1;
164
165 // DW 1-2 CCK rate counter
166 u16 cck[4];
167
168 // DW 3-6
169 u16 ofdm[8];
170
171 // DW 7-14
172 //UINT16 MCS_BW0_SG0[16];
173
174 // DW 15-22
175 //UINT16 MCS_BW1_SG0[16];
176
177 // DW 23-30
178 //UINT16 MCS_BW0_SG1[16];
179
180 // DW 31-38
181 //UINT16 MCS_BW1_SG1[16];
182
183 // DW 7-14 BW=0 SG=0
184 // DW 15-22 BW=1 SG=0
185 // DW 23-30 BW=0 SG=1
186 // DW 31-38 BW=1 SG=1
187 u16 ht_mcs[4][16];
188
189}__attribute__((packed)) cmpk_tx_rahis_t;
190
191typedef enum tag_command_packet_directories
192{
193 RX_TX_FEEDBACK = 0,
194 RX_INTERRUPT_STATUS = 1,
195 TX_SET_CONFIG = 2,
196 BOTH_QUERY_CONFIG = 3,
197 RX_TX_STATUS = 4,
198 RX_DBGINFO_FEEDBACK = 5,
199 RX_TX_PER_PKT_FEEDBACK = 6,
200 RX_TX_RATE_HISTORY = 7,
201 RX_CMD_ELE_MAX
202}cmpk_element_e;
203
204u32 cmpk_message_handle_rx(struct r8192_priv *priv, struct ieee80211_rx_stats *pstats);
205
206
207#endif
diff --git a/drivers/staging/rtl8192e/r819xE_firmware.c b/drivers/staging/rtl8192e/r819xE_firmware.c
new file mode 100644
index 00000000000..d9e8b5a0890
--- /dev/null
+++ b/drivers/staging/rtl8192e/r819xE_firmware.c
@@ -0,0 +1,351 @@
1/*
2 * Procedure: Init boot code/firmware code/data session
3 *
4 * Description: This routine will initialize firmware. If any error occurs
5 * during the initialization process, the routine shall terminate
6 * immediately and return fail.
7 */
8
9#include "r8192E.h"
10#include "r8192E_hw.h"
11
12#include <linux/firmware.h>
13
14/* It should be double word alignment */
15#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4 * (v / 4) - 8)
16
17enum firmware_init_step {
18 FW_INIT_STEP0_BOOT = 0,
19 FW_INIT_STEP1_MAIN = 1,
20 FW_INIT_STEP2_DATA = 2,
21};
22
23enum opt_rst_type {
24 OPT_SYSTEM_RESET = 0,
25 OPT_FIRMWARE_RESET = 1,
26};
27
28void firmware_init_param(struct r8192_priv *priv)
29{
30 rt_firmware *pfirmware = priv->pFirmware;
31
32 pfirmware->cmdpacket_frag_thresold =
33 GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE);
34}
35
36/*
37 * segment the img and use the ptr and length to remember info on each segment
38 */
39static bool fw_download_code(struct r8192_priv *priv, u8 *code_virtual_address,
40 u32 buffer_len)
41{
42 bool rt_status = true;
43 u16 frag_threshold;
44 u16 frag_length, frag_offset = 0;
45 int i;
46
47 rt_firmware *pfirmware = priv->pFirmware;
48 struct sk_buff *skb;
49 unsigned char *seg_ptr;
50 cb_desc *tcb_desc;
51 u8 bLastIniPkt;
52
53 firmware_init_param(priv);
54
55 /* Fragmentation might be required */
56 frag_threshold = pfirmware->cmdpacket_frag_thresold;
57 do {
58 if ((buffer_len - frag_offset) > frag_threshold) {
59 frag_length = frag_threshold ;
60 bLastIniPkt = 0;
61 } else {
62 frag_length = buffer_len - frag_offset;
63 bLastIniPkt = 1;
64 }
65
66 /*
67 * Allocate skb buffer to contain firmware info and tx
68 * descriptor info add 4 to avoid packet appending overflow.
69 */
70 skb = dev_alloc_skb(frag_length + 4);
71 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
72 tcb_desc->queue_index = TXCMD_QUEUE;
73 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
74 tcb_desc->bLastIniPkt = bLastIniPkt;
75
76 seg_ptr = skb->data;
77
78 /*
79 * Transform from little endian to big endian and pending zero
80 */
81 for (i = 0; i < frag_length; i += 4) {
82 *seg_ptr++ = ((i+0) < frag_length) ?
83 code_virtual_address[i+3] : 0;
84
85 *seg_ptr++ = ((i+1) < frag_length) ?
86 code_virtual_address[i+2] : 0;
87
88 *seg_ptr++ = ((i+2) < frag_length) ?
89 code_virtual_address[i+1] : 0;
90
91 *seg_ptr++ = ((i+3) < frag_length) ?
92 code_virtual_address[i+0] : 0;
93 }
94 tcb_desc->txbuf_size = (u16)i;
95 skb_put(skb, i);
96 priv->ieee80211->softmac_hard_start_xmit(skb, priv->ieee80211);
97
98 code_virtual_address += frag_length;
99 frag_offset += frag_length;
100
101 } while (frag_offset < buffer_len);
102
103 return rt_status;
104}
105
106/*
107 * Check whether main code is download OK. If OK, turn on CPU
108 *
109 * CPU register locates in different page against general
110 * register. Switch to CPU register in the begin and switch
111 * back before return
112 */
113static bool CPUcheck_maincodeok_turnonCPU(struct r8192_priv *priv)
114{
115 unsigned long timeout;
116 bool rt_status = true;
117 u32 CPU_status = 0;
118
119 /* Check whether put code OK */
120 timeout = jiffies + msecs_to_jiffies(20);
121 while (time_before(jiffies, timeout)) {
122 CPU_status = read_nic_dword(priv, CPU_GEN);
123
124 if (CPU_status & CPU_GEN_PUT_CODE_OK)
125 break;
126 msleep(2);
127 }
128
129 if (!(CPU_status & CPU_GEN_PUT_CODE_OK)) {
130 RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
131 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
132 } else {
133 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
134 }
135
136 /* Turn On CPU */
137 CPU_status = read_nic_dword(priv, CPU_GEN);
138 write_nic_byte(priv, CPU_GEN,
139 (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff));
140 mdelay(1);
141
142 /* Check whether CPU boot OK */
143 timeout = jiffies + msecs_to_jiffies(20);
144 while (time_before(jiffies, timeout)) {
145 CPU_status = read_nic_dword(priv, CPU_GEN);
146
147 if (CPU_status & CPU_GEN_BOOT_RDY)
148 break;
149 msleep(2);
150 }
151
152 if (!(CPU_status & CPU_GEN_BOOT_RDY))
153 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
154 else
155 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
156
157 return rt_status;
158
159CPUCheckMainCodeOKAndTurnOnCPU_Fail:
160 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
161 rt_status = FALSE;
162 return rt_status;
163}
164
165static bool CPUcheck_firmware_ready(struct r8192_priv *priv)
166{
167 unsigned long timeout;
168 bool rt_status = true;
169 u32 CPU_status = 0;
170
171 /* Check Firmware Ready */
172 timeout = jiffies + msecs_to_jiffies(20);
173 while (time_before(jiffies, timeout)) {
174 CPU_status = read_nic_dword(priv, CPU_GEN);
175
176 if (CPU_status & CPU_GEN_FIRM_RDY)
177 break;
178 msleep(2);
179 }
180
181 if (!(CPU_status & CPU_GEN_FIRM_RDY))
182 goto CPUCheckFirmwareReady_Fail;
183 else
184 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
185
186 return rt_status;
187
188CPUCheckFirmwareReady_Fail:
189 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
190 rt_status = false;
191 return rt_status;
192
193}
194
195bool init_firmware(struct r8192_priv *priv)
196{
197 bool rt_status = true;
198 u32 file_length = 0;
199 u8 *mapped_file = NULL;
200 u32 init_step = 0;
201 enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
202 enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
203
204 rt_firmware *pfirmware = priv->pFirmware;
205 const struct firmware *fw_entry;
206 const char *fw_name[3] = { "RTL8192E/boot.img",
207 "RTL8192E/main.img",
208 "RTL8192E/data.img"};
209 int rc;
210
211 RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
212
213 if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
214 /* it is called by reset */
215 rst_opt = OPT_SYSTEM_RESET;
216 starting_state = FW_INIT_STEP0_BOOT;
217 /* TODO: system reset */
218
219 } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
220 /* it is called by Initialize */
221 rst_opt = OPT_FIRMWARE_RESET;
222 starting_state = FW_INIT_STEP2_DATA;
223 } else {
224 RT_TRACE(COMP_FIRMWARE,
225 "PlatformInitFirmware: undefined firmware state\n");
226 }
227
228 /*
229 * Download boot, main, and data image for System reset.
230 * Download data image for firmware reseta
231 */
232 for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA;
233 init_step++) {
234 /*
235 * Open Image file, and map file to contineous memory if open file success.
236 * or read image file from array. Default load from IMG file
237 */
238 if (rst_opt == OPT_SYSTEM_RESET) {
239 if (pfirmware->firmware_buf_size[init_step] == 0) {
240 rc = request_firmware(&fw_entry,
241 fw_name[init_step], &priv->pdev->dev);
242
243 if (rc < 0) {
244 RT_TRACE(COMP_FIRMWARE, "request firmware fail!\n");
245 goto download_firmware_fail;
246 }
247
248 if (fw_entry->size > sizeof(pfirmware->firmware_buf[init_step])) {
249 RT_TRACE(COMP_FIRMWARE,
250 "img file size exceed the container buffer fail!\n");
251 goto download_firmware_fail;
252 }
253
254 if (init_step != FW_INIT_STEP1_MAIN) {
255 memcpy(pfirmware->firmware_buf[init_step],
256 fw_entry->data, fw_entry->size);
257 pfirmware->firmware_buf_size[init_step] = fw_entry->size;
258
259 } else {
260 memset(pfirmware->firmware_buf[init_step], 0, 128);
261 memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data,
262 fw_entry->size);
263 pfirmware->firmware_buf_size[init_step] = fw_entry->size+128;
264 }
265
266 if (rst_opt == OPT_SYSTEM_RESET)
267 release_firmware(fw_entry);
268 }
269 mapped_file = pfirmware->firmware_buf[init_step];
270 file_length = pfirmware->firmware_buf_size[init_step];
271
272 } else if (rst_opt == OPT_FIRMWARE_RESET) {
273 /* we only need to download data.img here */
274 mapped_file = pfirmware->firmware_buf[init_step];
275 file_length = pfirmware->firmware_buf_size[init_step];
276 }
277
278 /* Download image file */
279 /* The firmware download process is just as following,
280 * 1. that is each packet will be segmented and inserted to the
281 * wait queue.
282 * 2. each packet segment will be put in the skb_buff packet.
283 * 3. each skb_buff packet data content will already include
284 * the firmware info and Tx descriptor info
285 */
286 rt_status = fw_download_code(priv, mapped_file, file_length);
287 if (rt_status != TRUE)
288 goto download_firmware_fail;
289
290 switch (init_step) {
291 case FW_INIT_STEP0_BOOT:
292 /* Download boot
293 * initialize command descriptor.
294 * will set polling bit when firmware code is also
295 * configured
296 */
297 pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
298 /* mdelay(1000); */
299 /*
300 * To initialize IMEM, CPU move code from 0x80000080,
301 * hence, we send 0x80 byte packet
302 */
303 break;
304
305 case FW_INIT_STEP1_MAIN:
306 /* Download firmware code.
307 * Wait until Boot Ready and Turn on CPU */
308 pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
309
310 /* Check Put Code OK and Turn On CPU */
311 rt_status = CPUcheck_maincodeok_turnonCPU(priv);
312 if (rt_status != TRUE) {
313 RT_TRACE(COMP_FIRMWARE,
314 "CPUcheck_maincodeok_turnonCPU fail!\n");
315 goto download_firmware_fail;
316 }
317
318 pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
319 break;
320
321 case FW_INIT_STEP2_DATA:
322 /* download initial data code */
323 pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
324 mdelay(1);
325
326 rt_status = CPUcheck_firmware_ready(priv);
327 if (rt_status != TRUE) {
328 RT_TRACE(COMP_FIRMWARE,
329 "CPUcheck_firmware_ready fail(%d)!\n",
330 rt_status);
331 goto download_firmware_fail;
332 }
333
334 /* wait until data code is initialized ready.*/
335 pfirmware->firmware_status = FW_STATUS_5_READY;
336 break;
337 }
338 }
339
340 RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
341 return rt_status;
342
343download_firmware_fail:
344 RT_TRACE(COMP_ERR, "ERR in %s() step %d\n", __func__, init_step);
345 rt_status = false;
346 return rt_status;
347}
348
349MODULE_FIRMWARE("RTL8192E/boot.img");
350MODULE_FIRMWARE("RTL8192E/main.img");
351MODULE_FIRMWARE("RTL8192E/data.img");
diff --git a/drivers/staging/rtl8192e/r819xE_phy.c b/drivers/staging/rtl8192e/r819xE_phy.c
new file mode 100644
index 00000000000..9e7828ef1cb
--- /dev/null
+++ b/drivers/staging/rtl8192e/r819xE_phy.c
@@ -0,0 +1,2225 @@
1#include "r8192E.h"
2#include "r8192E_hw.h"
3#include "r819xE_phyreg.h"
4#include "r8190_rtl8256.h"
5#include "r819xE_phy.h"
6#include "r8192E_dm.h"
7#ifdef ENABLE_DOT11D
8#include "ieee80211/dot11d.h"
9#endif
10static const u32 RF_CHANNEL_TABLE_ZEBRA[] = {
11 0,
12 0x085c, //2412 1
13 0x08dc, //2417 2
14 0x095c, //2422 3
15 0x09dc, //2427 4
16 0x0a5c, //2432 5
17 0x0adc, //2437 6
18 0x0b5c, //2442 7
19 0x0bdc, //2447 8
20 0x0c5c, //2452 9
21 0x0cdc, //2457 10
22 0x0d5c, //2462 11
23 0x0ddc, //2467 12
24 0x0e5c, //2472 13
25 0x0f72, //2484
26};
27
28static u32 Rtl8192PciEMACPHY_Array[] = {
290x03c,0xffff0000,0x00000f0f,
300x340,0xffffffff,0x161a1a1a,
310x344,0xffffffff,0x12121416,
320x348,0x0000ffff,0x00001818,
330x12c,0xffffffff,0x04000802,
340x318,0x00000fff,0x00000100,
35};
36static u32 Rtl8192PciEMACPHY_Array_PG[] = {
370x03c,0xffff0000,0x00000f0f,
380xe00,0xffffffff,0x06090909,
390xe04,0xffffffff,0x00030306,
400xe08,0x0000ff00,0x00000000,
410xe10,0xffffffff,0x0a0c0d0f,
420xe14,0xffffffff,0x06070809,
430xe18,0xffffffff,0x0a0c0d0f,
440xe1c,0xffffffff,0x06070809,
450x12c,0xffffffff,0x04000802,
460x318,0x00000fff,0x00000800,
47};
48static u32 Rtl8192PciEAGCTAB_Array[AGCTAB_ArrayLength] = {
490xc78,0x7d000001,
500xc78,0x7d010001,
510xc78,0x7d020001,
520xc78,0x7d030001,
530xc78,0x7d040001,
540xc78,0x7d050001,
550xc78,0x7c060001,
560xc78,0x7b070001,
570xc78,0x7a080001,
580xc78,0x79090001,
590xc78,0x780a0001,
600xc78,0x770b0001,
610xc78,0x760c0001,
620xc78,0x750d0001,
630xc78,0x740e0001,
640xc78,0x730f0001,
650xc78,0x72100001,
660xc78,0x71110001,
670xc78,0x70120001,
680xc78,0x6f130001,
690xc78,0x6e140001,
700xc78,0x6d150001,
710xc78,0x6c160001,
720xc78,0x6b170001,
730xc78,0x6a180001,
740xc78,0x69190001,
750xc78,0x681a0001,
760xc78,0x671b0001,
770xc78,0x661c0001,
780xc78,0x651d0001,
790xc78,0x641e0001,
800xc78,0x491f0001,
810xc78,0x48200001,
820xc78,0x47210001,
830xc78,0x46220001,
840xc78,0x45230001,
850xc78,0x44240001,
860xc78,0x43250001,
870xc78,0x28260001,
880xc78,0x27270001,
890xc78,0x26280001,
900xc78,0x25290001,
910xc78,0x242a0001,
920xc78,0x232b0001,
930xc78,0x222c0001,
940xc78,0x212d0001,
950xc78,0x202e0001,
960xc78,0x0a2f0001,
970xc78,0x08300001,
980xc78,0x06310001,
990xc78,0x05320001,
1000xc78,0x04330001,
1010xc78,0x03340001,
1020xc78,0x02350001,
1030xc78,0x01360001,
1040xc78,0x00370001,
1050xc78,0x00380001,
1060xc78,0x00390001,
1070xc78,0x003a0001,
1080xc78,0x003b0001,
1090xc78,0x003c0001,
1100xc78,0x003d0001,
1110xc78,0x003e0001,
1120xc78,0x003f0001,
1130xc78,0x7d400001,
1140xc78,0x7d410001,
1150xc78,0x7d420001,
1160xc78,0x7d430001,
1170xc78,0x7d440001,
1180xc78,0x7d450001,
1190xc78,0x7c460001,
1200xc78,0x7b470001,
1210xc78,0x7a480001,
1220xc78,0x79490001,
1230xc78,0x784a0001,
1240xc78,0x774b0001,
1250xc78,0x764c0001,
1260xc78,0x754d0001,
1270xc78,0x744e0001,
1280xc78,0x734f0001,
1290xc78,0x72500001,
1300xc78,0x71510001,
1310xc78,0x70520001,
1320xc78,0x6f530001,
1330xc78,0x6e540001,
1340xc78,0x6d550001,
1350xc78,0x6c560001,
1360xc78,0x6b570001,
1370xc78,0x6a580001,
1380xc78,0x69590001,
1390xc78,0x685a0001,
1400xc78,0x675b0001,
1410xc78,0x665c0001,
1420xc78,0x655d0001,
1430xc78,0x645e0001,
1440xc78,0x495f0001,
1450xc78,0x48600001,
1460xc78,0x47610001,
1470xc78,0x46620001,
1480xc78,0x45630001,
1490xc78,0x44640001,
1500xc78,0x43650001,
1510xc78,0x28660001,
1520xc78,0x27670001,
1530xc78,0x26680001,
1540xc78,0x25690001,
1550xc78,0x246a0001,
1560xc78,0x236b0001,
1570xc78,0x226c0001,
1580xc78,0x216d0001,
1590xc78,0x206e0001,
1600xc78,0x0a6f0001,
1610xc78,0x08700001,
1620xc78,0x06710001,
1630xc78,0x05720001,
1640xc78,0x04730001,
1650xc78,0x03740001,
1660xc78,0x02750001,
1670xc78,0x01760001,
1680xc78,0x00770001,
1690xc78,0x00780001,
1700xc78,0x00790001,
1710xc78,0x007a0001,
1720xc78,0x007b0001,
1730xc78,0x007c0001,
1740xc78,0x007d0001,
1750xc78,0x007e0001,
1760xc78,0x007f0001,
1770xc78,0x2e00001e,
1780xc78,0x2e01001e,
1790xc78,0x2e02001e,
1800xc78,0x2e03001e,
1810xc78,0x2e04001e,
1820xc78,0x2e05001e,
1830xc78,0x3006001e,
1840xc78,0x3407001e,
1850xc78,0x3908001e,
1860xc78,0x3c09001e,
1870xc78,0x3f0a001e,
1880xc78,0x420b001e,
1890xc78,0x440c001e,
1900xc78,0x450d001e,
1910xc78,0x460e001e,
1920xc78,0x460f001e,
1930xc78,0x4710001e,
1940xc78,0x4811001e,
1950xc78,0x4912001e,
1960xc78,0x4a13001e,
1970xc78,0x4b14001e,
1980xc78,0x4b15001e,
1990xc78,0x4c16001e,
2000xc78,0x4d17001e,
2010xc78,0x4e18001e,
2020xc78,0x4f19001e,
2030xc78,0x4f1a001e,
2040xc78,0x501b001e,
2050xc78,0x511c001e,
2060xc78,0x521d001e,
2070xc78,0x521e001e,
2080xc78,0x531f001e,
2090xc78,0x5320001e,
2100xc78,0x5421001e,
2110xc78,0x5522001e,
2120xc78,0x5523001e,
2130xc78,0x5624001e,
2140xc78,0x5725001e,
2150xc78,0x5726001e,
2160xc78,0x5827001e,
2170xc78,0x5828001e,
2180xc78,0x5929001e,
2190xc78,0x592a001e,
2200xc78,0x5a2b001e,
2210xc78,0x5b2c001e,
2220xc78,0x5c2d001e,
2230xc78,0x5c2e001e,
2240xc78,0x5d2f001e,
2250xc78,0x5e30001e,
2260xc78,0x5f31001e,
2270xc78,0x6032001e,
2280xc78,0x6033001e,
2290xc78,0x6134001e,
2300xc78,0x6235001e,
2310xc78,0x6336001e,
2320xc78,0x6437001e,
2330xc78,0x6438001e,
2340xc78,0x6539001e,
2350xc78,0x663a001e,
2360xc78,0x673b001e,
2370xc78,0x673c001e,
2380xc78,0x683d001e,
2390xc78,0x693e001e,
2400xc78,0x6a3f001e,
241};
242static u32 Rtl8192PciEPHY_REGArray[PHY_REGArrayLength] = {
2430x0, };
244static u32 Rtl8192PciEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength] = {
2450x800,0x00000000,
2460x804,0x00000001,
2470x808,0x0000fc00,
2480x80c,0x0000001c,
2490x810,0x801010aa,
2500x814,0x008514d0,
2510x818,0x00000040,
2520x81c,0x00000000,
2530x820,0x00000004,
2540x824,0x00690000,
2550x828,0x00000004,
2560x82c,0x00e90000,
2570x830,0x00000004,
2580x834,0x00690000,
2590x838,0x00000004,
2600x83c,0x00e90000,
2610x840,0x00000000,
2620x844,0x00000000,
2630x848,0x00000000,
2640x84c,0x00000000,
2650x850,0x00000000,
2660x854,0x00000000,
2670x858,0x65a965a9,
2680x85c,0x65a965a9,
2690x860,0x001f0010,
2700x864,0x007f0010,
2710x868,0x001f0010,
2720x86c,0x007f0010,
2730x870,0x0f100f70,
2740x874,0x0f100f70,
2750x878,0x00000000,
2760x87c,0x00000000,
2770x880,0x6870e36c,
2780x884,0xe3573600,
2790x888,0x4260c340,
2800x88c,0x0000ff00,
2810x890,0x00000000,
2820x894,0xfffffffe,
2830x898,0x4c42382f,
2840x89c,0x00656056,
2850x8b0,0x00000000,
2860x8e0,0x00000000,
2870x8e4,0x00000000,
2880x900,0x00000000,
2890x904,0x00000023,
2900x908,0x00000000,
2910x90c,0x31121311,
2920xa00,0x00d0c7d8,
2930xa04,0x811f0008,
2940xa08,0x80cd8300,
2950xa0c,0x2e62740f,
2960xa10,0x95009b78,
2970xa14,0x11145008,
2980xa18,0x00881117,
2990xa1c,0x89140fa0,
3000xa20,0x1a1b0000,
3010xa24,0x090e1317,
3020xa28,0x00000204,
3030xa2c,0x00000000,
3040xc00,0x00000040,
3050xc04,0x00005433,
3060xc08,0x000000e4,
3070xc0c,0x6c6c6c6c,
3080xc10,0x08800000,
3090xc14,0x40000100,
3100xc18,0x08000000,
3110xc1c,0x40000100,
3120xc20,0x08000000,
3130xc24,0x40000100,
3140xc28,0x08000000,
3150xc2c,0x40000100,
3160xc30,0x6de9ac44,
3170xc34,0x465c52cd,
3180xc38,0x497f5994,
3190xc3c,0x0a969764,
3200xc40,0x1f7c403f,
3210xc44,0x000100b7,
3220xc48,0xec020000,
3230xc4c,0x00000300,
3240xc50,0x69543420,
3250xc54,0x433c0094,
3260xc58,0x69543420,
3270xc5c,0x433c0094,
3280xc60,0x69543420,
3290xc64,0x433c0094,
3300xc68,0x69543420,
3310xc6c,0x433c0094,
3320xc70,0x2c7f000d,
3330xc74,0x0186175b,
3340xc78,0x0000001f,
3350xc7c,0x00b91612,
3360xc80,0x40000100,
3370xc84,0x20000000,
3380xc88,0x40000100,
3390xc8c,0x20200000,
3400xc90,0x40000100,
3410xc94,0x00000000,
3420xc98,0x40000100,
3430xc9c,0x00000000,
3440xca0,0x00492492,
3450xca4,0x00000000,
3460xca8,0x00000000,
3470xcac,0x00000000,
3480xcb0,0x00000000,
3490xcb4,0x00000000,
3500xcb8,0x00000000,
3510xcbc,0x00492492,
3520xcc0,0x00000000,
3530xcc4,0x00000000,
3540xcc8,0x00000000,
3550xccc,0x00000000,
3560xcd0,0x00000000,
3570xcd4,0x00000000,
3580xcd8,0x64b22427,
3590xcdc,0x00766932,
3600xce0,0x00222222,
3610xd00,0x00000750,
3620xd04,0x00000403,
3630xd08,0x0000907f,
3640xd0c,0x00000001,
3650xd10,0xa0633333,
3660xd14,0x33333c63,
3670xd18,0x6a8f5b6b,
3680xd1c,0x00000000,
3690xd20,0x00000000,
3700xd24,0x00000000,
3710xd28,0x00000000,
3720xd2c,0xcc979975,
3730xd30,0x00000000,
3740xd34,0x00000000,
3750xd38,0x00000000,
3760xd3c,0x00027293,
3770xd40,0x00000000,
3780xd44,0x00000000,
3790xd48,0x00000000,
3800xd4c,0x00000000,
3810xd50,0x6437140a,
3820xd54,0x024dbd02,
3830xd58,0x00000000,
3840xd5c,0x04032064,
3850xe00,0x161a1a1a,
3860xe04,0x12121416,
3870xe08,0x00001800,
3880xe0c,0x00000000,
3890xe10,0x161a1a1a,
3900xe14,0x12121416,
3910xe18,0x161a1a1a,
3920xe1c,0x12121416,
393};
394static u32 Rtl8192PciERadioA_Array[RadioA_ArrayLength] = {
3950x019,0x00000003,
3960x000,0x000000bf,
3970x001,0x00000ee0,
3980x002,0x0000004c,
3990x003,0x000007f1,
4000x004,0x00000975,
4010x005,0x00000c58,
4020x006,0x00000ae6,
4030x007,0x000000ca,
4040x008,0x00000e1c,
4050x009,0x000007f0,
4060x00a,0x000009d0,
4070x00b,0x000001ba,
4080x00c,0x00000240,
4090x00e,0x00000020,
4100x00f,0x00000990,
4110x012,0x00000806,
4120x014,0x000005ab,
4130x015,0x00000f80,
4140x016,0x00000020,
4150x017,0x00000597,
4160x018,0x0000050a,
4170x01a,0x00000f80,
4180x01b,0x00000f5e,
4190x01c,0x00000008,
4200x01d,0x00000607,
4210x01e,0x000006cc,
4220x01f,0x00000000,
4230x020,0x000001a5,
4240x01f,0x00000001,
4250x020,0x00000165,
4260x01f,0x00000002,
4270x020,0x000000c6,
4280x01f,0x00000003,
4290x020,0x00000086,
4300x01f,0x00000004,
4310x020,0x00000046,
4320x01f,0x00000005,
4330x020,0x000001e6,
4340x01f,0x00000006,
4350x020,0x000001a6,
4360x01f,0x00000007,
4370x020,0x00000166,
4380x01f,0x00000008,
4390x020,0x000000c7,
4400x01f,0x00000009,
4410x020,0x00000087,
4420x01f,0x0000000a,
4430x020,0x000000f7,
4440x01f,0x0000000b,
4450x020,0x000000d7,
4460x01f,0x0000000c,
4470x020,0x000000b7,
4480x01f,0x0000000d,
4490x020,0x00000097,
4500x01f,0x0000000e,
4510x020,0x00000077,
4520x01f,0x0000000f,
4530x020,0x00000057,
4540x01f,0x00000010,
4550x020,0x00000037,
4560x01f,0x00000011,
4570x020,0x000000fb,
4580x01f,0x00000012,
4590x020,0x000000db,
4600x01f,0x00000013,
4610x020,0x000000bb,
4620x01f,0x00000014,
4630x020,0x000000ff,
4640x01f,0x00000015,
4650x020,0x000000e3,
4660x01f,0x00000016,
4670x020,0x000000c3,
4680x01f,0x00000017,
4690x020,0x000000a3,
4700x01f,0x00000018,
4710x020,0x00000083,
4720x01f,0x00000019,
4730x020,0x00000063,
4740x01f,0x0000001a,
4750x020,0x00000043,
4760x01f,0x0000001b,
4770x020,0x00000023,
4780x01f,0x0000001c,
4790x020,0x00000003,
4800x01f,0x0000001d,
4810x020,0x000001e3,
4820x01f,0x0000001e,
4830x020,0x000001c3,
4840x01f,0x0000001f,
4850x020,0x000001a3,
4860x01f,0x00000020,
4870x020,0x00000183,
4880x01f,0x00000021,
4890x020,0x00000163,
4900x01f,0x00000022,
4910x020,0x00000143,
4920x01f,0x00000023,
4930x020,0x00000123,
4940x01f,0x00000024,
4950x020,0x00000103,
4960x023,0x00000203,
4970x024,0x00000100,
4980x00b,0x000001ba,
4990x02c,0x000003d7,
5000x02d,0x00000ff0,
5010x000,0x00000037,
5020x004,0x00000160,
5030x007,0x00000080,
5040x002,0x0000088d,
5050x0fe,0x00000000,
5060x0fe,0x00000000,
5070x016,0x00000200,
5080x016,0x00000380,
5090x016,0x00000020,
5100x016,0x000001a0,
5110x000,0x000000bf,
5120x00d,0x0000001f,
5130x00d,0x00000c9f,
5140x002,0x0000004d,
5150x000,0x00000cbf,
5160x004,0x00000975,
5170x007,0x00000700,
518};
519static u32 Rtl8192PciERadioB_Array[RadioB_ArrayLength] = {
5200x019,0x00000003,
5210x000,0x000000bf,
5220x001,0x000006e0,
5230x002,0x0000004c,
5240x003,0x000007f1,
5250x004,0x00000975,
5260x005,0x00000c58,
5270x006,0x00000ae6,
5280x007,0x000000ca,
5290x008,0x00000e1c,
5300x000,0x000000b7,
5310x00a,0x00000850,
5320x000,0x000000bf,
5330x00b,0x000001ba,
5340x00c,0x00000240,
5350x00e,0x00000020,
5360x015,0x00000f80,
5370x016,0x00000020,
5380x017,0x00000597,
5390x018,0x0000050a,
5400x01a,0x00000e00,
5410x01b,0x00000f5e,
5420x01d,0x00000607,
5430x01e,0x000006cc,
5440x00b,0x000001ba,
5450x023,0x00000203,
5460x024,0x00000100,
5470x000,0x00000037,
5480x004,0x00000160,
5490x016,0x00000200,
5500x016,0x00000380,
5510x016,0x00000020,
5520x016,0x000001a0,
5530x00d,0x00000ccc,
5540x000,0x000000bf,
5550x002,0x0000004d,
5560x000,0x00000cbf,
5570x004,0x00000975,
5580x007,0x00000700,
559};
560static u32 Rtl8192PciERadioC_Array[RadioC_ArrayLength] = {
5610x0, };
562static u32 Rtl8192PciERadioD_Array[RadioD_ArrayLength] = {
5630x0, };
564
565/*************************Define local function prototype**********************/
566
567static u32 phy_FwRFSerialRead(struct r8192_priv *priv, RF90_RADIO_PATH_E eRFPath, u32 Offset);
568static void phy_FwRFSerialWrite(struct r8192_priv *priv, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data);
569
570/*************************Define local function prototype**********************/
571/******************************************************************************
572 *function: This function read BB parameters from Header file we gen,
573 * and do register read/write
574 * input: u32 dwBitMask //taget bit pos in the addr to be modified
575 * output: none
576 * return: u32 return the shift bit bit position of the mask
577 * ****************************************************************************/
578static u32 rtl8192_CalculateBitShift(u32 dwBitMask)
579{
580 u32 i;
581 for (i=0; i<=31; i++)
582 {
583 if (((dwBitMask>>i)&0x1) == 1)
584 break;
585 }
586 return i;
587}
588/******************************************************************************
589 *function: This function check different RF type to execute legal judgement. If RF Path is illegal, we will return false.
590 * input: none
591 * output: none
592 * return: 0(illegal, false), 1(legal,true)
593 * ***************************************************************************/
594u8 rtl8192_phy_CheckIsLegalRFPath(struct r8192_priv *priv, u32 eRFPath)
595{
596 u8 ret = 1;
597
598 if (priv->rf_type == RF_2T4R)
599 ret = 0;
600 else if (priv->rf_type == RF_1T2R)
601 {
602 if (eRFPath == RF90_PATH_A || eRFPath == RF90_PATH_B)
603 ret = 1;
604 else if (eRFPath == RF90_PATH_C || eRFPath == RF90_PATH_D)
605 ret = 0;
606 }
607
608 return ret;
609}
610/******************************************************************************
611 *function: This function set specific bits to BB register
612 * input: net_device dev
613 * u32 dwRegAddr //target addr to be modified
614 * u32 dwBitMask //taget bit pos in the addr to be modified
615 * u32 dwData //value to be write
616 * output: none
617 * return: none
618 * notice:
619 * ****************************************************************************/
620void rtl8192_setBBreg(struct r8192_priv *priv, u32 dwRegAddr, u32 dwBitMask, u32 dwData)
621{
622 u32 OriginalValue, BitShift, NewValue;
623
624 if(dwBitMask!= bMaskDWord)
625 {//if not "double word" write
626 OriginalValue = read_nic_dword(priv, dwRegAddr);
627 BitShift = rtl8192_CalculateBitShift(dwBitMask);
628 NewValue = (((OriginalValue) & (~dwBitMask)) | (dwData << BitShift));
629 write_nic_dword(priv, dwRegAddr, NewValue);
630 }else
631 write_nic_dword(priv, dwRegAddr, dwData);
632}
633/******************************************************************************
634 *function: This function reads specific bits from BB register
635 * input: net_device dev
636 * u32 dwRegAddr //target addr to be readback
637 * u32 dwBitMask //taget bit pos in the addr to be readback
638 * output: none
639 * return: u32 Data //the readback register value
640 * notice:
641 * ****************************************************************************/
642u32 rtl8192_QueryBBReg(struct r8192_priv *priv, u32 dwRegAddr, u32 dwBitMask)
643{
644 u32 OriginalValue, BitShift;
645
646 OriginalValue = read_nic_dword(priv, dwRegAddr);
647 BitShift = rtl8192_CalculateBitShift(dwBitMask);
648 return (OriginalValue & dwBitMask) >> BitShift;
649}
650/******************************************************************************
651 *function: This function read register from RF chip
652 * input: net_device dev
653 * RF90_RADIO_PATH_E eRFPath //radio path of A/B/C/D
654 * u32 Offset //target address to be read
655 * output: none
656 * return: u32 readback value
657 * notice: There are three types of serial operations:(1) Software serial write.(2)Hardware LSSI-Low Speed Serial Interface.(3)Hardware HSSI-High speed serial write. Driver here need to implement (1) and (2)---need more spec for this information.
658 * ****************************************************************************/
659static u32 rtl8192_phy_RFSerialRead(struct r8192_priv *priv,
660 RF90_RADIO_PATH_E eRFPath, u32 Offset)
661{
662 u32 ret = 0;
663 u32 NewOffset = 0;
664 BB_REGISTER_DEFINITION_T* pPhyReg = &priv->PHYRegDef[eRFPath];
665 //rtl8192_setBBreg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData, 0);
666 //make sure RF register offset is correct
667 Offset &= 0x3f;
668
669 //switch page for 8256 RF IC
670 //analog to digital off, for protection
671 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
672 if (Offset >= 31)
673 {
674 priv->RfReg0Value[eRFPath] |= 0x140;
675 //Switch to Reg_Mode2 for Reg 31-45
676 rtl8192_setBBreg(priv, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16) );
677 //modify offset
678 NewOffset = Offset -30;
679 }
680 else if (Offset >= 16)
681 {
682 priv->RfReg0Value[eRFPath] |= 0x100;
683 priv->RfReg0Value[eRFPath] &= (~0x40);
684 //Switch to Reg_Mode 1 for Reg16-30
685 rtl8192_setBBreg(priv, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16) );
686
687 NewOffset = Offset - 15;
688 }
689 else
690 NewOffset = Offset;
691
692 //put desired read addr to LSSI control Register
693 rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2, bLSSIReadAddress, NewOffset);
694 //Issue a posedge trigger
695 //
696 rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x0);
697 rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x1);
698
699
700 // TODO: we should not delay such a long time. Ask help from SD3
701 msleep(1);
702
703 ret = rtl8192_QueryBBReg(priv, pPhyReg->rfLSSIReadBack, bLSSIReadBackData);
704
705
706 // Switch back to Reg_Mode0;
707 priv->RfReg0Value[eRFPath] &= 0xebf;
708
709 rtl8192_setBBreg(
710 priv,
711 pPhyReg->rf3wireOffset,
712 bMaskDWord,
713 (priv->RfReg0Value[eRFPath] << 16));
714
715 //analog to digital on
716 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
717
718 return ret;
719}
720
721/******************************************************************************
722 *function: This function write data to RF register
723 * input: net_device dev
724 * RF90_RADIO_PATH_E eRFPath //radio path of A/B/C/D
725 * u32 Offset //target address to be written
726 * u32 Data //The new register data to be written
727 * output: none
728 * return: none
729 * notice: For RF8256 only.
730 ===========================================================
731 *Reg Mode RegCTL[1] RegCTL[0] Note
732 * (Reg00[12]) (Reg00[10])
733 *===========================================================
734 *Reg_Mode0 0 x Reg 0 ~15(0x0 ~ 0xf)
735 *------------------------------------------------------------------
736 *Reg_Mode1 1 0 Reg 16 ~30(0x1 ~ 0xf)
737 *------------------------------------------------------------------
738 * Reg_Mode2 1 1 Reg 31 ~ 45(0x1 ~ 0xf)
739 *------------------------------------------------------------------
740 * ****************************************************************************/
741static void rtl8192_phy_RFSerialWrite(struct r8192_priv *priv,
742 RF90_RADIO_PATH_E eRFPath, u32 Offset,
743 u32 Data)
744{
745 u32 DataAndAddr = 0, NewOffset = 0;
746 BB_REGISTER_DEFINITION_T *pPhyReg = &priv->PHYRegDef[eRFPath];
747
748 Offset &= 0x3f;
749
750 //analog to digital off, for protection
751 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
752
753 if (Offset >= 31)
754 {
755 priv->RfReg0Value[eRFPath] |= 0x140;
756 rtl8192_setBBreg(priv, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath] << 16));
757 NewOffset = Offset - 30;
758 }
759 else if (Offset >= 16)
760 {
761 priv->RfReg0Value[eRFPath] |= 0x100;
762 priv->RfReg0Value[eRFPath] &= (~0x40);
763 rtl8192_setBBreg(priv, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16));
764 NewOffset = Offset - 15;
765 }
766 else
767 NewOffset = Offset;
768
769 // Put write addr in [5:0] and write data in [31:16]
770 DataAndAddr = (Data<<16) | (NewOffset&0x3f);
771
772 // Write Operation
773 rtl8192_setBBreg(priv, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
774
775
776 if(Offset==0x0)
777 priv->RfReg0Value[eRFPath] = Data;
778
779 // Switch back to Reg_Mode0;
780 if(Offset != 0)
781 {
782 priv->RfReg0Value[eRFPath] &= 0xebf;
783 rtl8192_setBBreg(
784 priv,
785 pPhyReg->rf3wireOffset,
786 bMaskDWord,
787 (priv->RfReg0Value[eRFPath] << 16));
788 }
789 //analog to digital on
790 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
791}
792
793/******************************************************************************
794 *function: This function set specific bits to RF register
795 * input: RF90_RADIO_PATH_E eRFPath //radio path of A/B/C/D
796 * u32 RegAddr //target addr to be modified
797 * u32 BitMask //taget bit pos in the addr to be modified
798 * u32 Data //value to be write
799 * output: none
800 * return: none
801 * notice:
802 * ****************************************************************************/
803void rtl8192_phy_SetRFReg(struct r8192_priv *priv, RF90_RADIO_PATH_E eRFPath,
804 u32 RegAddr, u32 BitMask, u32 Data)
805{
806 u32 Original_Value, BitShift, New_Value;
807// u8 time = 0;
808
809 if (!rtl8192_phy_CheckIsLegalRFPath(priv, eRFPath))
810 return;
811 if (priv->eRFPowerState != eRfOn && !priv->being_init_adapter)
812 return;
813 //down(&priv->rf_sem);
814
815 RT_TRACE(COMP_PHY, "FW RF CTRL is not ready now\n");
816 if (priv->Rf_Mode == RF_OP_By_FW)
817 {
818 if (BitMask != bMask12Bits) // RF data is 12 bits only
819 {
820 Original_Value = phy_FwRFSerialRead(priv, eRFPath, RegAddr);
821 BitShift = rtl8192_CalculateBitShift(BitMask);
822 New_Value = (((Original_Value) & (~BitMask)) | (Data<< BitShift));
823
824 phy_FwRFSerialWrite(priv, eRFPath, RegAddr, New_Value);
825 }else
826 phy_FwRFSerialWrite(priv, eRFPath, RegAddr, Data);
827 udelay(200);
828
829 }
830 else
831 {
832 if (BitMask != bMask12Bits) // RF data is 12 bits only
833 {
834 Original_Value = rtl8192_phy_RFSerialRead(priv, eRFPath, RegAddr);
835 BitShift = rtl8192_CalculateBitShift(BitMask);
836 New_Value = (((Original_Value) & (~BitMask)) | (Data<< BitShift));
837
838 rtl8192_phy_RFSerialWrite(priv, eRFPath, RegAddr, New_Value);
839 }else
840 rtl8192_phy_RFSerialWrite(priv, eRFPath, RegAddr, Data);
841 }
842 //up(&priv->rf_sem);
843}
844
845/******************************************************************************
846 *function: This function reads specific bits from RF register
847 * input: net_device dev
848 * u32 RegAddr //target addr to be readback
849 * u32 BitMask //taget bit pos in the addr to be readback
850 * output: none
851 * return: u32 Data //the readback register value
852 * notice:
853 * ****************************************************************************/
854u32 rtl8192_phy_QueryRFReg(struct r8192_priv *priv, RF90_RADIO_PATH_E eRFPath,
855 u32 RegAddr, u32 BitMask)
856{
857 u32 Original_Value, Readback_Value, BitShift;
858
859 if (!rtl8192_phy_CheckIsLegalRFPath(priv, eRFPath))
860 return 0;
861 if (priv->eRFPowerState != eRfOn && !priv->being_init_adapter)
862 return 0;
863 down(&priv->rf_sem);
864 if (priv->Rf_Mode == RF_OP_By_FW)
865 {
866 Original_Value = phy_FwRFSerialRead(priv, eRFPath, RegAddr);
867 udelay(200);
868 }
869 else
870 {
871 Original_Value = rtl8192_phy_RFSerialRead(priv, eRFPath, RegAddr);
872
873 }
874 BitShift = rtl8192_CalculateBitShift(BitMask);
875 Readback_Value = (Original_Value & BitMask) >> BitShift;
876 up(&priv->rf_sem);
877// udelay(200);
878 return Readback_Value;
879}
880
881/******************************************************************************
882 *function: We support firmware to execute RF-R/W.
883 * input: dev
884 * output: none
885 * return: none
886 * notice:
887 * ***************************************************************************/
888static u32 phy_FwRFSerialRead(struct r8192_priv *priv,
889 RF90_RADIO_PATH_E eRFPath, u32 Offset)
890{
891 u32 Data = 0;
892 u8 time = 0;
893 //DbgPrint("FW RF CTRL\n\r");
894 /* 2007/11/02 MH Firmware RF Write control. By Francis' suggestion, we can
895 not execute the scheme in the initial step. Otherwise, RF-R/W will waste
896 much time. This is only for site survey. */
897 // 1. Read operation need not insert data. bit 0-11
898 //Data &= bMask12Bits;
899 // 2. Write RF register address. Bit 12-19
900 Data |= ((Offset&0xFF)<<12);
901 // 3. Write RF path. bit 20-21
902 Data |= ((eRFPath&0x3)<<20);
903 // 4. Set RF read indicator. bit 22=0
904 //Data |= 0x00000;
905 // 5. Trigger Fw to operate the command. bit 31
906 Data |= 0x80000000;
907 // 6. We can not execute read operation if bit 31 is 1.
908 while (read_nic_dword(priv, QPNR)&0x80000000)
909 {
910 // If FW can not finish RF-R/W for more than ?? times. We must reset FW.
911 if (time++ < 100)
912 {
913 //DbgPrint("FW not finish RF-R Time=%d\n\r", time);
914 udelay(10);
915 }
916 else
917 break;
918 }
919 // 7. Execute read operation.
920 write_nic_dword(priv, QPNR, Data);
921 // 8. Check if firmawre send back RF content.
922 while (read_nic_dword(priv, QPNR)&0x80000000)
923 {
924 // If FW can not finish RF-R/W for more than ?? times. We must reset FW.
925 if (time++ < 100)
926 {
927 //DbgPrint("FW not finish RF-W Time=%d\n\r", time);
928 udelay(10);
929 }
930 else
931 return 0;
932 }
933 return read_nic_dword(priv, RF_DATA);
934}
935
936/******************************************************************************
937 *function: We support firmware to execute RF-R/W.
938 * input: dev
939 * output: none
940 * return: none
941 * notice:
942 * ***************************************************************************/
943static void phy_FwRFSerialWrite(struct r8192_priv *priv,
944 RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data)
945{
946 u8 time = 0;
947
948 //DbgPrint("N FW RF CTRL RF-%d OF%02x DATA=%03x\n\r", eRFPath, Offset, Data);
949 /* 2007/11/02 MH Firmware RF Write control. By Francis' suggestion, we can
950 not execute the scheme in the initial step. Otherwise, RF-R/W will waste
951 much time. This is only for site survey. */
952
953 // 1. Set driver write bit and 12 bit data. bit 0-11
954 //Data &= bMask12Bits; // Done by uper layer.
955 // 2. Write RF register address. bit 12-19
956 Data |= ((Offset&0xFF)<<12);
957 // 3. Write RF path. bit 20-21
958 Data |= ((eRFPath&0x3)<<20);
959 // 4. Set RF write indicator. bit 22=1
960 Data |= 0x400000;
961 // 5. Trigger Fw to operate the command. bit 31=1
962 Data |= 0x80000000;
963
964 // 6. Write operation. We can not write if bit 31 is 1.
965 while (read_nic_dword(priv, QPNR)&0x80000000)
966 {
967 // If FW can not finish RF-R/W for more than ?? times. We must reset FW.
968 if (time++ < 100)
969 {
970 //DbgPrint("FW not finish RF-W Time=%d\n\r", time);
971 udelay(10);
972 }
973 else
974 break;
975 }
976 // 7. No matter check bit. We always force the write. Because FW will
977 // not accept the command.
978 write_nic_dword(priv, QPNR, Data);
979 /* 2007/11/02 MH Acoording to test, we must delay 20us to wait firmware
980 to finish RF write operation. */
981 /* 2008/01/17 MH We support delay in firmware side now. */
982 //delay_us(20);
983
984}
985
986
987/******************************************************************************
988 *function: This function read BB parameters from Header file we gen,
989 * and do register read/write
990 * input: dev
991 * output: none
992 * return: none
993 * notice: BB parameters may change all the time, so please make
994 * sure it has been synced with the newest.
995 * ***************************************************************************/
996void rtl8192_phy_configmac(struct r8192_priv *priv)
997{
998 u32 dwArrayLen = 0, i = 0;
999 u32* pdwArray = NULL;
1000#ifdef TO_DO_LIST
1001if(Adapter->bInHctTest)
1002 {
1003 RT_TRACE(COMP_PHY, "Rtl819XMACPHY_ArrayDTM\n");
1004 dwArrayLen = MACPHY_ArrayLengthDTM;
1005 pdwArray = Rtl819XMACPHY_ArrayDTM;
1006 }
1007 else if(priv->bTXPowerDataReadFromEEPORM)
1008#endif
1009 if(priv->bTXPowerDataReadFromEEPORM)
1010 {
1011 RT_TRACE(COMP_PHY, "Rtl819XMACPHY_Array_PG\n");
1012 dwArrayLen = MACPHY_Array_PGLength;
1013 pdwArray = Rtl819XMACPHY_Array_PG;
1014
1015 }
1016 else
1017 {
1018 RT_TRACE(COMP_PHY,"Read rtl819XMACPHY_Array\n");
1019 dwArrayLen = MACPHY_ArrayLength;
1020 pdwArray = Rtl819XMACPHY_Array;
1021 }
1022 for(i = 0; i<dwArrayLen; i=i+3){
1023 RT_TRACE(COMP_DBG, "The Rtl8190MACPHY_Array[0] is %x Rtl8190MACPHY_Array[1] is %x Rtl8190MACPHY_Array[2] is %x\n",
1024 pdwArray[i], pdwArray[i+1], pdwArray[i+2]);
1025 if(pdwArray[i] == 0x318)
1026 {
1027 pdwArray[i+2] = 0x00000800;
1028 //DbgPrint("ptrArray[i], ptrArray[i+1], ptrArray[i+2] = %x, %x, %x\n",
1029 // ptrArray[i], ptrArray[i+1], ptrArray[i+2]);
1030 }
1031 rtl8192_setBBreg(priv, pdwArray[i], pdwArray[i+1], pdwArray[i+2]);
1032 }
1033}
1034
1035/******************************************************************************
1036 *function: This function do dirty work
1037 * input: dev
1038 * output: none
1039 * return: none
1040 * notice: BB parameters may change all the time, so please make
1041 * sure it has been synced with the newest.
1042 * ***************************************************************************/
1043
1044void rtl8192_phyConfigBB(struct r8192_priv *priv, u8 ConfigType)
1045{
1046 int i;
1047 //u8 ArrayLength;
1048 u32* Rtl819XPHY_REGArray_Table = NULL;
1049 u32* Rtl819XAGCTAB_Array_Table = NULL;
1050 u16 AGCTAB_ArrayLen, PHY_REGArrayLen = 0;
1051#ifdef TO_DO_LIST
1052 u32 *rtl8192PhyRegArrayTable = NULL, *rtl8192AgcTabArrayTable = NULL;
1053 if(Adapter->bInHctTest)
1054 {
1055 AGCTAB_ArrayLen = AGCTAB_ArrayLengthDTM;
1056 Rtl819XAGCTAB_Array_Table = Rtl819XAGCTAB_ArrayDTM;
1057
1058 if(priv->RF_Type == RF_2T4R)
1059 {
1060 PHY_REGArrayLen = PHY_REGArrayLengthDTM;
1061 Rtl819XPHY_REGArray_Table = Rtl819XPHY_REGArrayDTM;
1062 }
1063 else if (priv->RF_Type == RF_1T2R)
1064 {
1065 PHY_REGArrayLen = PHY_REG_1T2RArrayLengthDTM;
1066 Rtl819XPHY_REGArray_Table = Rtl819XPHY_REG_1T2RArrayDTM;
1067 }
1068 }
1069 else
1070#endif
1071 {
1072 AGCTAB_ArrayLen = AGCTAB_ArrayLength;
1073 Rtl819XAGCTAB_Array_Table = Rtl819XAGCTAB_Array;
1074 if(priv->rf_type == RF_2T4R)
1075 {
1076 PHY_REGArrayLen = PHY_REGArrayLength;
1077 Rtl819XPHY_REGArray_Table = Rtl819XPHY_REGArray;
1078 }
1079 else if (priv->rf_type == RF_1T2R)
1080 {
1081 PHY_REGArrayLen = PHY_REG_1T2RArrayLength;
1082 Rtl819XPHY_REGArray_Table = Rtl819XPHY_REG_1T2RArray;
1083 }
1084 }
1085
1086 if (ConfigType == BaseBand_Config_PHY_REG)
1087 {
1088 for (i=0; i<PHY_REGArrayLen; i+=2)
1089 {
1090 rtl8192_setBBreg(priv, Rtl819XPHY_REGArray_Table[i], bMaskDWord, Rtl819XPHY_REGArray_Table[i+1]);
1091 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]);
1092 }
1093 }
1094 else if (ConfigType == BaseBand_Config_AGC_TAB)
1095 {
1096 for (i=0; i<AGCTAB_ArrayLen; i+=2)
1097 {
1098 rtl8192_setBBreg(priv, Rtl819XAGCTAB_Array_Table[i], bMaskDWord, Rtl819XAGCTAB_Array_Table[i+1]);
1099 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]);
1100 }
1101 }
1102}
1103/******************************************************************************
1104 *function: This function initialize Register definition offset for Radio Path
1105 * A/B/C/D
1106 * input: net_device dev
1107 * output: none
1108 * return: none
1109 * notice: Initialization value here is constant and it should never be changed
1110 * ***************************************************************************/
1111static void rtl8192_InitBBRFRegDef(struct r8192_priv *priv)
1112{
1113// RF Interface Sowrtware Control
1114 priv->PHYRegDef[RF90_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; // 16 LSBs if read 32-bit from 0x870
1115 priv->PHYRegDef[RF90_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; // 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872)
1116 priv->PHYRegDef[RF90_PATH_C].rfintfs = rFPGA0_XCD_RFInterfaceSW;// 16 LSBs if read 32-bit from 0x874
1117 priv->PHYRegDef[RF90_PATH_D].rfintfs = rFPGA0_XCD_RFInterfaceSW;// 16 MSBs if read 32-bit from 0x874 (16-bit for 0x876)
1118
1119 // RF Interface Readback Value
1120 priv->PHYRegDef[RF90_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB; // 16 LSBs if read 32-bit from 0x8E0
1121 priv->PHYRegDef[RF90_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB;// 16 MSBs if read 32-bit from 0x8E0 (16-bit for 0x8E2)
1122 priv->PHYRegDef[RF90_PATH_C].rfintfi = rFPGA0_XCD_RFInterfaceRB;// 16 LSBs if read 32-bit from 0x8E4
1123 priv->PHYRegDef[RF90_PATH_D].rfintfi = rFPGA0_XCD_RFInterfaceRB;// 16 MSBs if read 32-bit from 0x8E4 (16-bit for 0x8E6)
1124
1125 // RF Interface Output (and Enable)
1126 priv->PHYRegDef[RF90_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; // 16 LSBs if read 32-bit from 0x860
1127 priv->PHYRegDef[RF90_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; // 16 LSBs if read 32-bit from 0x864
1128 priv->PHYRegDef[RF90_PATH_C].rfintfo = rFPGA0_XC_RFInterfaceOE;// 16 LSBs if read 32-bit from 0x868
1129 priv->PHYRegDef[RF90_PATH_D].rfintfo = rFPGA0_XD_RFInterfaceOE;// 16 LSBs if read 32-bit from 0x86C
1130
1131 // RF Interface (Output and) Enable
1132 priv->PHYRegDef[RF90_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; // 16 MSBs if read 32-bit from 0x860 (16-bit for 0x862)
1133 priv->PHYRegDef[RF90_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; // 16 MSBs if read 32-bit from 0x864 (16-bit for 0x866)
1134 priv->PHYRegDef[RF90_PATH_C].rfintfe = rFPGA0_XC_RFInterfaceOE;// 16 MSBs if read 32-bit from 0x86A (16-bit for 0x86A)
1135 priv->PHYRegDef[RF90_PATH_D].rfintfe = rFPGA0_XD_RFInterfaceOE;// 16 MSBs if read 32-bit from 0x86C (16-bit for 0x86E)
1136
1137 //Addr of LSSI. Wirte RF register by driver
1138 priv->PHYRegDef[RF90_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; //LSSI Parameter
1139 priv->PHYRegDef[RF90_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter;
1140 priv->PHYRegDef[RF90_PATH_C].rf3wireOffset = rFPGA0_XC_LSSIParameter;
1141 priv->PHYRegDef[RF90_PATH_D].rf3wireOffset = rFPGA0_XD_LSSIParameter;
1142
1143 // RF parameter
1144 priv->PHYRegDef[RF90_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter; //BB Band Select
1145 priv->PHYRegDef[RF90_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter;
1146 priv->PHYRegDef[RF90_PATH_C].rfLSSI_Select = rFPGA0_XCD_RFParameter;
1147 priv->PHYRegDef[RF90_PATH_D].rfLSSI_Select = rFPGA0_XCD_RFParameter;
1148
1149 // Tx AGC Gain Stage (same for all path. Should we remove this?)
1150 priv->PHYRegDef[RF90_PATH_A].rfTxGainStage = rFPGA0_TxGainStage; //Tx gain stage
1151 priv->PHYRegDef[RF90_PATH_B].rfTxGainStage = rFPGA0_TxGainStage; //Tx gain stage
1152 priv->PHYRegDef[RF90_PATH_C].rfTxGainStage = rFPGA0_TxGainStage; //Tx gain stage
1153 priv->PHYRegDef[RF90_PATH_D].rfTxGainStage = rFPGA0_TxGainStage; //Tx gain stage
1154
1155 // Tranceiver A~D HSSI Parameter-1
1156 priv->PHYRegDef[RF90_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1; //wire control parameter1
1157 priv->PHYRegDef[RF90_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1; //wire control parameter1
1158 priv->PHYRegDef[RF90_PATH_C].rfHSSIPara1 = rFPGA0_XC_HSSIParameter1; //wire control parameter1
1159 priv->PHYRegDef[RF90_PATH_D].rfHSSIPara1 = rFPGA0_XD_HSSIParameter1; //wire control parameter1
1160
1161 // Tranceiver A~D HSSI Parameter-2
1162 priv->PHYRegDef[RF90_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; //wire control parameter2
1163 priv->PHYRegDef[RF90_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; //wire control parameter2
1164 priv->PHYRegDef[RF90_PATH_C].rfHSSIPara2 = rFPGA0_XC_HSSIParameter2; //wire control parameter2
1165 priv->PHYRegDef[RF90_PATH_D].rfHSSIPara2 = rFPGA0_XD_HSSIParameter2; //wire control parameter1
1166
1167 // RF switch Control
1168 priv->PHYRegDef[RF90_PATH_A].rfSwitchControl = rFPGA0_XAB_SwitchControl; //TR/Ant switch control
1169 priv->PHYRegDef[RF90_PATH_B].rfSwitchControl = rFPGA0_XAB_SwitchControl;
1170 priv->PHYRegDef[RF90_PATH_C].rfSwitchControl = rFPGA0_XCD_SwitchControl;
1171 priv->PHYRegDef[RF90_PATH_D].rfSwitchControl = rFPGA0_XCD_SwitchControl;
1172
1173 // AGC control 1
1174 priv->PHYRegDef[RF90_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1;
1175 priv->PHYRegDef[RF90_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1;
1176 priv->PHYRegDef[RF90_PATH_C].rfAGCControl1 = rOFDM0_XCAGCCore1;
1177 priv->PHYRegDef[RF90_PATH_D].rfAGCControl1 = rOFDM0_XDAGCCore1;
1178
1179 // AGC control 2
1180 priv->PHYRegDef[RF90_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2;
1181 priv->PHYRegDef[RF90_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2;
1182 priv->PHYRegDef[RF90_PATH_C].rfAGCControl2 = rOFDM0_XCAGCCore2;
1183 priv->PHYRegDef[RF90_PATH_D].rfAGCControl2 = rOFDM0_XDAGCCore2;
1184
1185 // RX AFE control 1
1186 priv->PHYRegDef[RF90_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance;
1187 priv->PHYRegDef[RF90_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance;
1188 priv->PHYRegDef[RF90_PATH_C].rfRxIQImbalance = rOFDM0_XCRxIQImbalance;
1189 priv->PHYRegDef[RF90_PATH_D].rfRxIQImbalance = rOFDM0_XDRxIQImbalance;
1190
1191 // RX AFE control 1
1192 priv->PHYRegDef[RF90_PATH_A].rfRxAFE = rOFDM0_XARxAFE;
1193 priv->PHYRegDef[RF90_PATH_B].rfRxAFE = rOFDM0_XBRxAFE;
1194 priv->PHYRegDef[RF90_PATH_C].rfRxAFE = rOFDM0_XCRxAFE;
1195 priv->PHYRegDef[RF90_PATH_D].rfRxAFE = rOFDM0_XDRxAFE;
1196
1197 // Tx AFE control 1
1198 priv->PHYRegDef[RF90_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance;
1199 priv->PHYRegDef[RF90_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance;
1200 priv->PHYRegDef[RF90_PATH_C].rfTxIQImbalance = rOFDM0_XCTxIQImbalance;
1201 priv->PHYRegDef[RF90_PATH_D].rfTxIQImbalance = rOFDM0_XDTxIQImbalance;
1202
1203 // Tx AFE control 2
1204 priv->PHYRegDef[RF90_PATH_A].rfTxAFE = rOFDM0_XATxAFE;
1205 priv->PHYRegDef[RF90_PATH_B].rfTxAFE = rOFDM0_XBTxAFE;
1206 priv->PHYRegDef[RF90_PATH_C].rfTxAFE = rOFDM0_XCTxAFE;
1207 priv->PHYRegDef[RF90_PATH_D].rfTxAFE = rOFDM0_XDTxAFE;
1208
1209 // Tranceiver LSSI Readback
1210 priv->PHYRegDef[RF90_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack;
1211 priv->PHYRegDef[RF90_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack;
1212 priv->PHYRegDef[RF90_PATH_C].rfLSSIReadBack = rFPGA0_XC_LSSIReadBack;
1213 priv->PHYRegDef[RF90_PATH_D].rfLSSIReadBack = rFPGA0_XD_LSSIReadBack;
1214
1215}
1216/******************************************************************************
1217 *function: This function is to write register and then readback to make sure whether BB and RF is OK
1218 * input: net_device dev
1219 * HW90_BLOCK_E CheckBlock
1220 * RF90_RADIO_PATH_E eRFPath //only used when checkblock is HW90_BLOCK_RF
1221 * output: none
1222 * return: return whether BB and RF is ok(0:OK; 1:Fail)
1223 * notice: This function may be removed in the ASIC
1224 * ***************************************************************************/
1225RT_STATUS rtl8192_phy_checkBBAndRF(struct r8192_priv *priv,
1226 HW90_BLOCK_E CheckBlock,
1227 RF90_RADIO_PATH_E eRFPath)
1228{
1229// BB_REGISTER_DEFINITION_T *pPhyReg = &priv->PHYRegDef[eRFPath];
1230 RT_STATUS ret = RT_STATUS_SUCCESS;
1231 u32 i, CheckTimes = 4, dwRegRead = 0;
1232 u32 WriteAddr[4];
1233 u32 WriteData[] = {0xfffff027, 0xaa55a02f, 0x00000027, 0x55aa502f};
1234 // Initialize register address offset to be checked
1235 WriteAddr[HW90_BLOCK_MAC] = 0x100;
1236 WriteAddr[HW90_BLOCK_PHY0] = 0x900;
1237 WriteAddr[HW90_BLOCK_PHY1] = 0x800;
1238 WriteAddr[HW90_BLOCK_RF] = 0x3;
1239 RT_TRACE(COMP_PHY, "=======>%s(), CheckBlock:%d\n", __FUNCTION__, CheckBlock);
1240 for(i=0 ; i < CheckTimes ; i++)
1241 {
1242
1243 //
1244 // Write Data to register and readback
1245 //
1246 switch(CheckBlock)
1247 {
1248 case HW90_BLOCK_MAC:
1249 RT_TRACE(COMP_ERR, "PHY_CheckBBRFOK(): Never Write 0x100 here!\n");
1250 break;
1251
1252 case HW90_BLOCK_PHY0:
1253 case HW90_BLOCK_PHY1:
1254 write_nic_dword(priv, WriteAddr[CheckBlock], WriteData[i]);
1255 dwRegRead = read_nic_dword(priv, WriteAddr[CheckBlock]);
1256 break;
1257
1258 case HW90_BLOCK_RF:
1259 WriteData[i] &= 0xfff;
1260 rtl8192_phy_SetRFReg(priv, eRFPath, WriteAddr[HW90_BLOCK_RF], bMask12Bits, WriteData[i]);
1261 // TODO: we should not delay for such a long time. Ask SD3
1262 mdelay(10);
1263 dwRegRead = rtl8192_phy_QueryRFReg(priv, eRFPath, WriteAddr[HW90_BLOCK_RF], bMaskDWord);
1264 mdelay(10);
1265 break;
1266
1267 default:
1268 ret = RT_STATUS_FAILURE;
1269 break;
1270 }
1271
1272
1273 //
1274 // Check whether readback data is correct
1275 //
1276 if(dwRegRead != WriteData[i])
1277 {
1278 RT_TRACE(COMP_ERR, "====>error=====dwRegRead: %x, WriteData: %x\n", dwRegRead, WriteData[i]);
1279 ret = RT_STATUS_FAILURE;
1280 break;
1281 }
1282 }
1283
1284 return ret;
1285}
1286
1287
1288/******************************************************************************
1289 *function: This function initialize BB&RF
1290 * input: net_device dev
1291 * output: none
1292 * return: none
1293 * notice: Initialization value may change all the time, so please make
1294 * sure it has been synced with the newest.
1295 * ***************************************************************************/
1296static RT_STATUS rtl8192_BB_Config_ParaFile(struct r8192_priv *priv)
1297{
1298 RT_STATUS rtStatus = RT_STATUS_SUCCESS;
1299
1300 u8 bRegValue = 0, eCheckItem = 0;
1301 u32 dwRegValue = 0;
1302 /**************************************
1303 //<1>Initialize BaseBand
1304 **************************************/
1305
1306 /*--set BB Global Reset--*/
1307 bRegValue = read_nic_byte(priv, BB_GLOBAL_RESET);
1308 write_nic_byte(priv, BB_GLOBAL_RESET,(bRegValue|BB_GLOBAL_RESET_BIT));
1309
1310 /*---set BB reset Active---*/
1311 dwRegValue = read_nic_dword(priv, CPU_GEN);
1312 write_nic_dword(priv, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST)));
1313
1314 /*----Ckeck FPGAPHY0 and PHY1 board is OK----*/
1315 // TODO: this function should be removed on ASIC , Emily 2007.2.2
1316 for(eCheckItem=(HW90_BLOCK_E)HW90_BLOCK_PHY0; eCheckItem<=HW90_BLOCK_PHY1; eCheckItem++)
1317 {
1318 rtStatus = rtl8192_phy_checkBBAndRF(priv, (HW90_BLOCK_E)eCheckItem, (RF90_RADIO_PATH_E)0); //don't care RF path
1319 if(rtStatus != RT_STATUS_SUCCESS)
1320 {
1321 RT_TRACE((COMP_ERR | COMP_PHY), "PHY_RF8256_Config():Check PHY%d Fail!!\n", eCheckItem-1);
1322 return rtStatus;
1323 }
1324 }
1325 /*---- Set CCK and OFDM Block "OFF"----*/
1326 rtl8192_setBBreg(priv, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0);
1327 /*----BB Register Initilazation----*/
1328 //==m==>Set PHY REG From Header<==m==
1329 rtl8192_phyConfigBB(priv, BaseBand_Config_PHY_REG);
1330
1331 /*----Set BB reset de-Active----*/
1332 dwRegValue = read_nic_dword(priv, CPU_GEN);
1333 write_nic_dword(priv, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST));
1334
1335 /*----BB AGC table Initialization----*/
1336 //==m==>Set PHY REG From Header<==m==
1337 rtl8192_phyConfigBB(priv, BaseBand_Config_AGC_TAB);
1338
1339 if (priv->card_8192_version > VERSION_8190_BD)
1340 {
1341 if(priv->rf_type == RF_2T4R)
1342 {
1343 // Antenna gain offset from B/C/D to A
1344 dwRegValue = ( priv->AntennaTxPwDiff[2]<<8 |
1345 priv->AntennaTxPwDiff[1]<<4 |
1346 priv->AntennaTxPwDiff[0]);
1347 }
1348 else
1349 dwRegValue = 0x0; //Antenna gain offset doesn't make sense in RF 1T2R.
1350 rtl8192_setBBreg(priv, rFPGA0_TxGainStage,
1351 (bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue);
1352
1353
1354 //XSTALLCap
1355 dwRegValue = priv->CrystalCap;
1356 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, bXtalCap92x, dwRegValue);
1357 }
1358
1359 // Check if the CCK HighPower is turned ON.
1360 // This is used to calculate PWDB.
1361// priv->bCckHighPower = (u8)(rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter2, 0x200));
1362 return rtStatus;
1363}
1364/******************************************************************************
1365 *function: This function initialize BB&RF
1366 * input: net_device dev
1367 * output: none
1368 * return: none
1369 * notice: Initialization value may change all the time, so please make
1370 * sure it has been synced with the newest.
1371 * ***************************************************************************/
1372RT_STATUS rtl8192_BBConfig(struct r8192_priv *priv)
1373{
1374 rtl8192_InitBBRFRegDef(priv);
1375 //config BB&RF. As hardCode based initialization has not been well
1376 //implemented, so use file first.FIXME:should implement it for hardcode?
1377 return rtl8192_BB_Config_ParaFile(priv);
1378}
1379
1380/******************************************************************************
1381 *function: This function obtains the initialization value of Tx power Level offset
1382 * input: net_device dev
1383 * output: none
1384 * return: none
1385 * ***************************************************************************/
1386void rtl8192_phy_getTxPower(struct r8192_priv *priv)
1387{
1388 priv->MCSTxPowerLevelOriginalOffset[0] =
1389 read_nic_dword(priv, rTxAGC_Rate18_06);
1390 priv->MCSTxPowerLevelOriginalOffset[1] =
1391 read_nic_dword(priv, rTxAGC_Rate54_24);
1392 priv->MCSTxPowerLevelOriginalOffset[2] =
1393 read_nic_dword(priv, rTxAGC_Mcs03_Mcs00);
1394 priv->MCSTxPowerLevelOriginalOffset[3] =
1395 read_nic_dword(priv, rTxAGC_Mcs07_Mcs04);
1396 priv->MCSTxPowerLevelOriginalOffset[4] =
1397 read_nic_dword(priv, rTxAGC_Mcs11_Mcs08);
1398 priv->MCSTxPowerLevelOriginalOffset[5] =
1399 read_nic_dword(priv, rTxAGC_Mcs15_Mcs12);
1400
1401 // read rx initial gain
1402 priv->DefaultInitialGain[0] = read_nic_byte(priv, rOFDM0_XAAGCCore1);
1403 priv->DefaultInitialGain[1] = read_nic_byte(priv, rOFDM0_XBAGCCore1);
1404 priv->DefaultInitialGain[2] = read_nic_byte(priv, rOFDM0_XCAGCCore1);
1405 priv->DefaultInitialGain[3] = read_nic_byte(priv, rOFDM0_XDAGCCore1);
1406 RT_TRACE(COMP_INIT, "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n",
1407 priv->DefaultInitialGain[0], priv->DefaultInitialGain[1],
1408 priv->DefaultInitialGain[2], priv->DefaultInitialGain[3]);
1409
1410 // read framesync
1411 priv->framesync = read_nic_byte(priv, rOFDM0_RxDetector3);
1412 priv->framesyncC34 = read_nic_dword(priv, rOFDM0_RxDetector2);
1413 RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x\n",
1414 rOFDM0_RxDetector3, priv->framesync);
1415 // read SIFS (save the value read fome MACPHY_REG.txt)
1416 priv->SifsTime = read_nic_word(priv, SIFS);
1417}
1418
1419/******************************************************************************
1420 *function: This function obtains the initialization value of Tx power Level offset
1421 * input: net_device dev
1422 * output: none
1423 * return: none
1424 * ***************************************************************************/
1425void rtl8192_phy_setTxPower(struct r8192_priv *priv, u8 channel)
1426{
1427 u8 powerlevel = 0,powerlevelOFDM24G = 0;
1428 char ant_pwr_diff;
1429 u32 u4RegValue;
1430
1431 if(priv->epromtype == EPROM_93c46)
1432 {
1433 powerlevel = priv->TxPowerLevelCCK[channel-1];
1434 powerlevelOFDM24G = priv->TxPowerLevelOFDM24G[channel-1];
1435 }
1436 else if(priv->epromtype == EPROM_93c56)
1437 {
1438 if(priv->rf_type == RF_1T2R)
1439 {
1440 powerlevel = priv->TxPowerLevelCCK_C[channel-1];
1441 powerlevelOFDM24G = priv->TxPowerLevelOFDM24G_C[channel-1];
1442 }
1443 else if(priv->rf_type == RF_2T4R)
1444 {
1445 // Mainly we use RF-A Tx Power to write the Tx Power registers, but the RF-C Tx
1446 // Power must be calculated by the antenna diff.
1447 // So we have to rewrite Antenna gain offset register here.
1448 powerlevel = priv->TxPowerLevelCCK_A[channel-1];
1449 powerlevelOFDM24G = priv->TxPowerLevelOFDM24G_A[channel-1];
1450
1451 ant_pwr_diff = priv->TxPowerLevelOFDM24G_C[channel-1]
1452 -priv->TxPowerLevelOFDM24G_A[channel-1];
1453 ant_pwr_diff &= 0xf;
1454
1455 priv->AntennaTxPwDiff[2] = 0;// RF-D, don't care
1456 priv->AntennaTxPwDiff[1] = (u8)(ant_pwr_diff);// RF-C
1457 priv->AntennaTxPwDiff[0] = 0;// RF-B, don't care
1458
1459 // Antenna gain offset from B/C/D to A
1460 u4RegValue = ( priv->AntennaTxPwDiff[2]<<8 |
1461 priv->AntennaTxPwDiff[1]<<4 |
1462 priv->AntennaTxPwDiff[0]);
1463
1464 rtl8192_setBBreg(priv, rFPGA0_TxGainStage,
1465 (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue);
1466 }
1467 }
1468#ifdef TODO
1469 //
1470 // CCX 2 S31, AP control of client transmit power:
1471 // 1. We shall not exceed Cell Power Limit as possible as we can.
1472 // 2. Tolerance is +/- 5dB.
1473 // 3. 802.11h Power Contraint takes higher precedence over CCX Cell Power Limit.
1474 //
1475 // TODO:
1476 // 1. 802.11h power contraint
1477 //
1478 // 071011, by rcnjko.
1479 //
1480 if( pMgntInfo->OpMode == RT_OP_MODE_INFRASTRUCTURE &&
1481 pMgntInfo->bWithCcxCellPwr &&
1482 channel == pMgntInfo->dot11CurrentChannelNumber)
1483 {
1484 u8 CckCellPwrIdx = DbmToTxPwrIdx(Adapter, WIRELESS_MODE_B, pMgntInfo->CcxCellPwr);
1485 u8 LegacyOfdmCellPwrIdx = DbmToTxPwrIdx(Adapter, WIRELESS_MODE_G, pMgntInfo->CcxCellPwr);
1486 u8 OfdmCellPwrIdx = DbmToTxPwrIdx(Adapter, WIRELESS_MODE_N_24G, pMgntInfo->CcxCellPwr);
1487
1488 RT_TRACE(COMP_TXAGC, DBG_LOUD,
1489 ("CCX Cell Limit: %d dbm => CCK Tx power index : %d, Legacy OFDM Tx power index : %d, OFDM Tx power index: %d\n",
1490 pMgntInfo->CcxCellPwr, CckCellPwrIdx, LegacyOfdmCellPwrIdx, OfdmCellPwrIdx));
1491 RT_TRACE(COMP_TXAGC, DBG_LOUD,
1492 ("EEPROM channel(%d) => CCK Tx power index: %d, Legacy OFDM Tx power index : %d, OFDM Tx power index: %d\n",
1493 channel, powerlevel, powerlevelOFDM24G + pHalData->LegacyHTTxPowerDiff, powerlevelOFDM24G));
1494
1495 // CCK
1496 if(powerlevel > CckCellPwrIdx)
1497 powerlevel = CckCellPwrIdx;
1498 // Legacy OFDM, HT OFDM
1499 if(powerlevelOFDM24G + pHalData->LegacyHTTxPowerDiff > OfdmCellPwrIdx)
1500 {
1501 if((OfdmCellPwrIdx - pHalData->LegacyHTTxPowerDiff) > 0)
1502 {
1503 powerlevelOFDM24G = OfdmCellPwrIdx - pHalData->LegacyHTTxPowerDiff;
1504 }
1505 else
1506 {
1507 LegacyOfdmCellPwrIdx = 0;
1508 }
1509 }
1510
1511 RT_TRACE(COMP_TXAGC, DBG_LOUD,
1512 ("Altered CCK Tx power index : %d, Legacy OFDM Tx power index: %d, OFDM Tx power index: %d\n",
1513 powerlevel, powerlevelOFDM24G + pHalData->LegacyHTTxPowerDiff, powerlevelOFDM24G));
1514 }
1515
1516 pHalData->CurrentCckTxPwrIdx = powerlevel;
1517 pHalData->CurrentOfdm24GTxPwrIdx = powerlevelOFDM24G;
1518#endif
1519 PHY_SetRF8256CCKTxPower(priv, powerlevel); //need further implement
1520 PHY_SetRF8256OFDMTxPower(priv, powerlevelOFDM24G);
1521}
1522
1523/******************************************************************************
1524 *function: This function check Rf chip to do RF config
1525 * input: net_device dev
1526 * output: none
1527 * return: only 8256 is supported
1528 * ***************************************************************************/
1529RT_STATUS rtl8192_phy_RFConfig(struct r8192_priv *priv)
1530{
1531 return PHY_RF8256_Config(priv);
1532}
1533
1534/******************************************************************************
1535 *function: This function update Initial gain
1536 * input: net_device dev
1537 * output: none
1538 * return: As Windows has not implemented this, wait for complement
1539 * ***************************************************************************/
1540void rtl8192_phy_updateInitGain(struct r8192_priv *priv)
1541{
1542}
1543
1544/******************************************************************************
1545 *function: This function read RF parameters from general head file, and do RF 3-wire
1546 * input: net_device dev
1547 * output: none
1548 * return: return code show if RF configuration is successful(0:pass, 1:fail)
1549 * Note: Delay may be required for RF configuration
1550 * ***************************************************************************/
1551u8 rtl8192_phy_ConfigRFWithHeaderFile(struct r8192_priv *priv,
1552 RF90_RADIO_PATH_E eRFPath)
1553{
1554
1555 int i;
1556 //u32* pRFArray;
1557 u8 ret = 0;
1558
1559 switch(eRFPath){
1560 case RF90_PATH_A:
1561 for(i = 0;i<RadioA_ArrayLength; i=i+2){
1562
1563 if(Rtl819XRadioA_Array[i] == 0xfe){
1564 msleep(100);
1565 continue;
1566 }
1567 rtl8192_phy_SetRFReg(priv, eRFPath, Rtl819XRadioA_Array[i], bMask12Bits, Rtl819XRadioA_Array[i+1]);
1568 //msleep(1);
1569
1570 }
1571 break;
1572 case RF90_PATH_B:
1573 for(i = 0;i<RadioB_ArrayLength; i=i+2){
1574
1575 if(Rtl819XRadioB_Array[i] == 0xfe){
1576 msleep(100);
1577 continue;
1578 }
1579 rtl8192_phy_SetRFReg(priv, eRFPath, Rtl819XRadioB_Array[i], bMask12Bits, Rtl819XRadioB_Array[i+1]);
1580 //msleep(1);
1581
1582 }
1583 break;
1584 case RF90_PATH_C:
1585 for(i = 0;i<RadioC_ArrayLength; i=i+2){
1586
1587 if(Rtl819XRadioC_Array[i] == 0xfe){
1588 msleep(100);
1589 continue;
1590 }
1591 rtl8192_phy_SetRFReg(priv, eRFPath, Rtl819XRadioC_Array[i], bMask12Bits, Rtl819XRadioC_Array[i+1]);
1592 //msleep(1);
1593
1594 }
1595 break;
1596 case RF90_PATH_D:
1597 for(i = 0;i<RadioD_ArrayLength; i=i+2){
1598
1599 if(Rtl819XRadioD_Array[i] == 0xfe){
1600 msleep(100);
1601 continue;
1602 }
1603 rtl8192_phy_SetRFReg(priv, eRFPath, Rtl819XRadioD_Array[i], bMask12Bits, Rtl819XRadioD_Array[i+1]);
1604 //msleep(1);
1605
1606 }
1607 break;
1608 default:
1609 break;
1610 }
1611
1612 return ret;
1613
1614}
1615/******************************************************************************
1616 *function: This function set Tx Power of the channel
1617 * input: struct net_device *dev
1618 * u8 channel
1619 * output: none
1620 * return: none
1621 * Note:
1622 * ***************************************************************************/
1623static void rtl8192_SetTxPowerLevel(struct r8192_priv *priv, u8 channel)
1624{
1625 u8 powerlevel = priv->TxPowerLevelCCK[channel-1];
1626 u8 powerlevelOFDM24G = priv->TxPowerLevelOFDM24G[channel-1];
1627
1628 PHY_SetRF8256CCKTxPower(priv, powerlevel);
1629 PHY_SetRF8256OFDMTxPower(priv, powerlevelOFDM24G);
1630}
1631
1632/****************************************************************************************
1633 *function: This function set command table variable(struct SwChnlCmd).
1634 * input: SwChnlCmd* CmdTable //table to be set.
1635 * u32 CmdTableIdx //variable index in table to be set
1636 * u32 CmdTableSz //table size.
1637 * SwChnlCmdID CmdID //command ID to set.
1638 * u32 Para1
1639 * u32 Para2
1640 * u32 msDelay
1641 * output:
1642 * return: true if finished, false otherwise
1643 * Note:
1644 * ************************************************************************************/
1645static u8 rtl8192_phy_SetSwChnlCmdArray(
1646 SwChnlCmd* CmdTable,
1647 u32 CmdTableIdx,
1648 u32 CmdTableSz,
1649 SwChnlCmdID CmdID,
1650 u32 Para1,
1651 u32 Para2,
1652 u32 msDelay
1653 )
1654{
1655 SwChnlCmd* pCmd;
1656
1657 if(CmdTable == NULL)
1658 {
1659 RT_TRACE(COMP_ERR, "phy_SetSwChnlCmdArray(): CmdTable cannot be NULL.\n");
1660 return false;
1661 }
1662 if(CmdTableIdx >= CmdTableSz)
1663 {
1664 RT_TRACE(COMP_ERR, "phy_SetSwChnlCmdArray(): Access invalid index, please check size of the table, CmdTableIdx:%d, CmdTableSz:%d\n",
1665 CmdTableIdx, CmdTableSz);
1666 return false;
1667 }
1668
1669 pCmd = CmdTable + CmdTableIdx;
1670 pCmd->CmdID = CmdID;
1671 pCmd->Para1 = Para1;
1672 pCmd->Para2 = Para2;
1673 pCmd->msDelay = msDelay;
1674
1675 return true;
1676}
1677/******************************************************************************
1678 *function: This function set channel step by step
1679 * input: struct net_device *dev
1680 * u8 channel
1681 * u8* stage //3 stages
1682 * u8* step //
1683 * u32* delay //whether need to delay
1684 * output: store new stage, step and delay for next step(combine with function above)
1685 * return: true if finished, false otherwise
1686 * Note: Wait for simpler function to replace it //wb
1687 * ***************************************************************************/
1688static u8 rtl8192_phy_SwChnlStepByStep(struct r8192_priv *priv, u8 channel,
1689 u8* stage, u8* step, u32* delay)
1690{
1691// PCHANNEL_ACCESS_SETTING pChnlAccessSetting;
1692 SwChnlCmd PreCommonCmd[MAX_PRECMD_CNT];
1693 u32 PreCommonCmdCnt;
1694 SwChnlCmd PostCommonCmd[MAX_POSTCMD_CNT];
1695 u32 PostCommonCmdCnt;
1696 SwChnlCmd RfDependCmd[MAX_RFDEPENDCMD_CNT];
1697 u32 RfDependCmdCnt;
1698 SwChnlCmd *CurrentCmd = NULL;
1699 //RF90_RADIO_PATH_E eRFPath;
1700 u8 eRFPath;
1701// u32 RfRetVal;
1702// u8 RetryCnt;
1703
1704 RT_TRACE(COMP_TRACE, "====>%s()====stage:%d, step:%d, channel:%d\n", __FUNCTION__, *stage, *step, channel);
1705// RT_ASSERT(IsLegalChannel(Adapter, channel), ("illegal channel: %d\n", channel));
1706
1707#ifdef ENABLE_DOT11D
1708 if (!IsLegalChannel(priv->ieee80211, channel))
1709 {
1710 RT_TRACE(COMP_ERR, "=============>set to illegal channel:%d\n", channel);
1711 return true; //return true to tell upper caller function this channel setting is finished! Or it will in while loop.
1712 }
1713#endif
1714
1715 //for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
1716 //for(eRFPath = 0; eRFPath <RF90_PATH_MAX; eRFPath++)
1717 {
1718 //if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
1719 // return false;
1720 // <1> Fill up pre common command.
1721 PreCommonCmdCnt = 0;
1722 rtl8192_phy_SetSwChnlCmdArray(PreCommonCmd, PreCommonCmdCnt++, MAX_PRECMD_CNT,
1723 CmdID_SetTxPowerLevel, 0, 0, 0);
1724 rtl8192_phy_SetSwChnlCmdArray(PreCommonCmd, PreCommonCmdCnt++, MAX_PRECMD_CNT,
1725 CmdID_End, 0, 0, 0);
1726
1727 // <2> Fill up post common command.
1728 PostCommonCmdCnt = 0;
1729
1730 rtl8192_phy_SetSwChnlCmdArray(PostCommonCmd, PostCommonCmdCnt++, MAX_POSTCMD_CNT,
1731 CmdID_End, 0, 0, 0);
1732
1733 // <3> Fill up RF dependent command.
1734 RfDependCmdCnt = 0;
1735
1736 // TEST!! This is not the table for 8256!!
1737 if (!(channel >= 1 && channel <= 14))
1738 {
1739 RT_TRACE(COMP_ERR, "illegal channel for Zebra 8256: %d\n", channel);
1740 return false;
1741 }
1742 rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
1743 CmdID_RF_WriteReg, rZebra1_Channel, channel, 10);
1744 rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
1745 CmdID_End, 0, 0, 0);
1746
1747 do{
1748 switch(*stage)
1749 {
1750 case 0:
1751 CurrentCmd=&PreCommonCmd[*step];
1752 break;
1753 case 1:
1754 CurrentCmd=&RfDependCmd[*step];
1755 break;
1756 case 2:
1757 CurrentCmd=&PostCommonCmd[*step];
1758 break;
1759 }
1760
1761 if(CurrentCmd->CmdID==CmdID_End)
1762 {
1763 if((*stage)==2)
1764 {
1765 return true;
1766 }
1767 else
1768 {
1769 (*stage)++;
1770 (*step)=0;
1771 continue;
1772 }
1773 }
1774
1775 switch(CurrentCmd->CmdID)
1776 {
1777 case CmdID_SetTxPowerLevel:
1778 if(priv->card_8192_version > (u8)VERSION_8190_BD) //xiong: consider it later!
1779 rtl8192_SetTxPowerLevel(priv, channel);
1780 break;
1781 case CmdID_WritePortUlong:
1782 write_nic_dword(priv, CurrentCmd->Para1, CurrentCmd->Para2);
1783 break;
1784 case CmdID_WritePortUshort:
1785 write_nic_word(priv, CurrentCmd->Para1, (u16)CurrentCmd->Para2);
1786 break;
1787 case CmdID_WritePortUchar:
1788 write_nic_byte(priv, CurrentCmd->Para1, (u8)CurrentCmd->Para2);
1789 break;
1790 case CmdID_RF_WriteReg:
1791 for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
1792 rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, CurrentCmd->Para1, bMask12Bits, CurrentCmd->Para2<<7);
1793 break;
1794 default:
1795 break;
1796 }
1797
1798 break;
1799 }while(true);
1800 }/*for(Number of RF paths)*/
1801
1802 (*delay)=CurrentCmd->msDelay;
1803 (*step)++;
1804 return false;
1805}
1806
1807/******************************************************************************
1808 *function: This function does acturally set channel work
1809 * input: struct net_device *dev
1810 * u8 channel
1811 * output: none
1812 * return: noin
1813 * Note: We should not call this function directly
1814 * ***************************************************************************/
1815static void rtl8192_phy_FinishSwChnlNow(struct r8192_priv *priv, u8 channel)
1816{
1817 u32 delay = 0;
1818
1819 while (!rtl8192_phy_SwChnlStepByStep(priv, channel, &priv->SwChnlStage, &priv->SwChnlStep, &delay))
1820 {
1821 if(delay>0)
1822 msleep(delay);//or mdelay? need further consideration
1823 if(!priv->up)
1824 break;
1825 }
1826}
1827/******************************************************************************
1828 *function: Callback routine of the work item for switch channel.
1829 * input:
1830 *
1831 * output: none
1832 * return: noin
1833 * ***************************************************************************/
1834void rtl8192_SwChnl_WorkItem(struct r8192_priv *priv)
1835{
1836 RT_TRACE(COMP_TRACE, "==> SwChnlCallback819xUsbWorkItem()\n");
1837
1838 RT_TRACE(COMP_TRACE, "=====>--%s(), set chan:%d, priv:%p\n", __FUNCTION__, priv->chan, priv);
1839
1840 rtl8192_phy_FinishSwChnlNow(priv, priv->chan);
1841
1842 RT_TRACE(COMP_TRACE, "<== SwChnlCallback819xUsbWorkItem()\n");
1843}
1844
1845/******************************************************************************
1846 *function: This function scheduled actural workitem to set channel
1847 * input: net_device dev
1848 * u8 channel //channel to set
1849 * output: none
1850 * return: return code show if workitem is scheduled(1:pass, 0:fail)
1851 * Note: Delay may be required for RF configuration
1852 * ***************************************************************************/
1853u8 rtl8192_phy_SwChnl(struct ieee80211_device *ieee80211, u8 channel)
1854{
1855 struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
1856
1857 RT_TRACE(COMP_PHY, "=====>%s()\n", __FUNCTION__);
1858 if(!priv->up)
1859 return false;
1860 if(priv->SwChnlInProgress)
1861 return false;
1862
1863// if(pHalData->SetBWModeInProgress)
1864// return;
1865
1866 //--------------------------------------------
1867 switch(priv->ieee80211->mode)
1868 {
1869 case WIRELESS_MODE_A:
1870 case WIRELESS_MODE_N_5G:
1871 if (channel<=14){
1872 RT_TRACE(COMP_ERR, "WIRELESS_MODE_A but channel<=14\n");
1873 return false;
1874 }
1875 break;
1876 case WIRELESS_MODE_B:
1877 if (channel>14){
1878 RT_TRACE(COMP_ERR, "WIRELESS_MODE_B but channel>14\n");
1879 return false;
1880 }
1881 break;
1882 case WIRELESS_MODE_G:
1883 case WIRELESS_MODE_N_24G:
1884 if (channel>14){
1885 RT_TRACE(COMP_ERR, "WIRELESS_MODE_G but channel>14\n");
1886 return false;
1887 }
1888 break;
1889 }
1890 //--------------------------------------------
1891
1892 priv->SwChnlInProgress = true;
1893 if(channel == 0)
1894 channel = 1;
1895
1896 priv->chan=channel;
1897
1898 priv->SwChnlStage=0;
1899 priv->SwChnlStep=0;
1900 if (priv->up)
1901 rtl8192_SwChnl_WorkItem(priv);
1902
1903 priv->SwChnlInProgress = false;
1904 return true;
1905}
1906
1907static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct r8192_priv *priv)
1908{
1909 switch(priv->CurrentChannelBW)
1910 {
1911 /* 20 MHz channel*/
1912 case HT_CHANNEL_WIDTH_20:
1913 //added by vivi, cck,tx power track, 20080703
1914 priv->CCKPresentAttentuation =
1915 priv->CCKPresentAttentuation_20Mdefault + priv->CCKPresentAttentuation_difference;
1916
1917 if(priv->CCKPresentAttentuation > (CCKTxBBGainTableLength-1))
1918 priv->CCKPresentAttentuation = CCKTxBBGainTableLength-1;
1919 if(priv->CCKPresentAttentuation < 0)
1920 priv->CCKPresentAttentuation = 0;
1921
1922 RT_TRACE(COMP_POWER_TRACKING, "20M, priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
1923
1924 if(priv->ieee80211->current_network.channel== 14 && !priv->bcck_in_ch14)
1925 {
1926 priv->bcck_in_ch14 = TRUE;
1927 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
1928 }
1929 else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
1930 {
1931 priv->bcck_in_ch14 = FALSE;
1932 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
1933 }
1934 else
1935 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
1936 break;
1937
1938 /* 40 MHz channel*/
1939 case HT_CHANNEL_WIDTH_20_40:
1940 //added by vivi, cck,tx power track, 20080703
1941 priv->CCKPresentAttentuation =
1942 priv->CCKPresentAttentuation_40Mdefault + priv->CCKPresentAttentuation_difference;
1943
1944 RT_TRACE(COMP_POWER_TRACKING, "40M, priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
1945 if(priv->CCKPresentAttentuation > (CCKTxBBGainTableLength-1))
1946 priv->CCKPresentAttentuation = CCKTxBBGainTableLength-1;
1947 if(priv->CCKPresentAttentuation < 0)
1948 priv->CCKPresentAttentuation = 0;
1949
1950 if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
1951 {
1952 priv->bcck_in_ch14 = TRUE;
1953 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
1954 }
1955 else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
1956 {
1957 priv->bcck_in_ch14 = FALSE;
1958 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
1959 }
1960 else
1961 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
1962 break;
1963 }
1964}
1965
1966static void CCK_Tx_Power_Track_BW_Switch_ThermalMeter(struct r8192_priv *priv)
1967{
1968 if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
1969 priv->bcck_in_ch14 = TRUE;
1970 else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
1971 priv->bcck_in_ch14 = FALSE;
1972
1973 //write to default index and tx power track will be done in dm.
1974 switch(priv->CurrentChannelBW)
1975 {
1976 /* 20 MHz channel*/
1977 case HT_CHANNEL_WIDTH_20:
1978 if(priv->Record_CCK_20Mindex == 0)
1979 priv->Record_CCK_20Mindex = 6; //set default value.
1980 priv->CCK_index = priv->Record_CCK_20Mindex;//6;
1981 RT_TRACE(COMP_POWER_TRACKING, "20MHz, CCK_Tx_Power_Track_BW_Switch_ThermalMeter(),CCK_index = %d\n", priv->CCK_index);
1982 break;
1983
1984 /* 40 MHz channel*/
1985 case HT_CHANNEL_WIDTH_20_40:
1986 priv->CCK_index = priv->Record_CCK_40Mindex;//0;
1987 RT_TRACE(COMP_POWER_TRACKING, "40MHz, CCK_Tx_Power_Track_BW_Switch_ThermalMeter(), CCK_index = %d\n", priv->CCK_index);
1988 break;
1989 }
1990 dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
1991}
1992
1993static void CCK_Tx_Power_Track_BW_Switch(struct r8192_priv *priv)
1994{
1995
1996 //if(pHalData->bDcut == TRUE)
1997 if(priv->IC_Cut >= IC_VersionCut_D)
1998 CCK_Tx_Power_Track_BW_Switch_TSSI(priv);
1999 else
2000 CCK_Tx_Power_Track_BW_Switch_ThermalMeter(priv);
2001}
2002
2003
2004//
2005/******************************************************************************
2006 *function: Callback routine of the work item for set bandwidth mode.
2007 * input: struct net_device *dev
2008 * HT_CHANNEL_WIDTH Bandwidth //20M or 40M
2009 * HT_EXTCHNL_OFFSET Offset //Upper, Lower, or Don't care
2010 * output: none
2011 * return: none
2012 * Note: I doubt whether SetBWModeInProgress flag is necessary as we can
2013 * test whether current work in the queue or not.//do I?
2014 * ***************************************************************************/
2015void rtl8192_SetBWModeWorkItem(struct r8192_priv *priv)
2016{
2017 u8 regBwOpMode;
2018
2019 RT_TRACE(COMP_SWBW, "==>rtl8192_SetBWModeWorkItem() Switch to %s bandwidth\n",
2020 priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20?"20MHz":"40MHz")
2021
2022
2023 if(!priv->up)
2024 {
2025 priv->SetBWModeInProgress= false;
2026 return;
2027 }
2028 //<1>Set MAC register
2029 regBwOpMode = read_nic_byte(priv, BW_OPMODE);
2030
2031 switch(priv->CurrentChannelBW)
2032 {
2033 case HT_CHANNEL_WIDTH_20:
2034 regBwOpMode |= BW_OPMODE_20MHZ;
2035 // 2007/02/07 Mark by Emily because we have not verify whether this register works
2036 write_nic_byte(priv, BW_OPMODE, regBwOpMode);
2037 break;
2038
2039 case HT_CHANNEL_WIDTH_20_40:
2040 regBwOpMode &= ~BW_OPMODE_20MHZ;
2041 // 2007/02/07 Mark by Emily because we have not verify whether this register works
2042 write_nic_byte(priv, BW_OPMODE, regBwOpMode);
2043 break;
2044
2045 default:
2046 RT_TRACE(COMP_ERR, "SetChannelBandwidth819xUsb(): unknown Bandwidth: %#X\n",priv->CurrentChannelBW);
2047 break;
2048 }
2049
2050 //<2>Set PHY related register
2051 switch(priv->CurrentChannelBW)
2052 {
2053 case HT_CHANNEL_WIDTH_20:
2054 // Add by Vivi 20071119
2055 rtl8192_setBBreg(priv, rFPGA0_RFMOD, bRFMOD, 0x0);
2056 rtl8192_setBBreg(priv, rFPGA1_RFMOD, bRFMOD, 0x0);
2057// rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1);
2058
2059 // Correct the tx power for CCK rate in 20M. Suggest by YN, 20071207
2060// write_nic_dword(dev, rCCK0_TxFilter1, 0x1a1b0000);
2061// write_nic_dword(dev, rCCK0_TxFilter2, 0x090e1317);
2062// write_nic_dword(dev, rCCK0_DebugPort, 0x00000204);
2063 if(!priv->btxpower_tracking)
2064 {
2065 write_nic_dword(priv, rCCK0_TxFilter1, 0x1a1b0000);
2066 write_nic_dword(priv, rCCK0_TxFilter2, 0x090e1317);
2067 write_nic_dword(priv, rCCK0_DebugPort, 0x00000204);
2068 }
2069 else
2070 CCK_Tx_Power_Track_BW_Switch(priv);
2071
2072 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x00100000, 1);
2073 break;
2074 case HT_CHANNEL_WIDTH_20_40:
2075 // Add by Vivi 20071119
2076 rtl8192_setBBreg(priv, rFPGA0_RFMOD, bRFMOD, 0x1);
2077 rtl8192_setBBreg(priv, rFPGA1_RFMOD, bRFMOD, 0x1);
2078 //rtl8192_setBBreg(dev, rCCK0_System, bCCKSideBand, (priv->nCur40MhzPrimeSC>>1));
2079 //rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0);
2080 //rtl8192_setBBreg(dev, rOFDM1_LSTF, 0xC00, priv->nCur40MhzPrimeSC);
2081
2082 // Correct the tx power for CCK rate in 40M. Suggest by YN, 20071207
2083 //write_nic_dword(dev, rCCK0_TxFilter1, 0x35360000);
2084 //write_nic_dword(dev, rCCK0_TxFilter2, 0x121c252e);
2085 //write_nic_dword(dev, rCCK0_DebugPort, 0x00000409);
2086 if(!priv->btxpower_tracking)
2087 {
2088 write_nic_dword(priv, rCCK0_TxFilter1, 0x35360000);
2089 write_nic_dword(priv, rCCK0_TxFilter2, 0x121c252e);
2090 write_nic_dword(priv, rCCK0_DebugPort, 0x00000409);
2091 }
2092 else
2093 CCK_Tx_Power_Track_BW_Switch(priv);
2094
2095 // Set Control channel to upper or lower. These settings are required only for 40MHz
2096 rtl8192_setBBreg(priv, rCCK0_System, bCCKSideBand, (priv->nCur40MhzPrimeSC>>1));
2097 rtl8192_setBBreg(priv, rOFDM1_LSTF, 0xC00, priv->nCur40MhzPrimeSC);
2098
2099
2100 rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x00100000, 0);
2101 break;
2102 default:
2103 RT_TRACE(COMP_ERR, "SetChannelBandwidth819xUsb(): unknown Bandwidth: %#X\n" ,priv->CurrentChannelBW);
2104 break;
2105
2106 }
2107 //Skip over setting of J-mode in BB register here. Default value is "None J mode". Emily 20070315
2108
2109 //<3>Set RF related register
2110 PHY_SetRF8256Bandwidth(priv, priv->CurrentChannelBW);
2111
2112 atomic_dec(&(priv->ieee80211->atm_swbw));
2113 priv->SetBWModeInProgress= false;
2114
2115 RT_TRACE(COMP_SWBW, "<==SetBWMode819xUsb()\n");
2116}
2117
2118/******************************************************************************
2119 *function: This function schedules bandwidth switch work.
2120 * input: struct net_device *dev
2121 * HT_CHANNEL_WIDTH Bandwidth //20M or 40M
2122 * HT_EXTCHNL_OFFSET Offset //Upper, Lower, or Don't care
2123 * output: none
2124 * return: none
2125 * Note: I doubt whether SetBWModeInProgress flag is necessary as we can
2126 * test whether current work in the queue or not.//do I?
2127 * ***************************************************************************/
2128void rtl8192_SetBWMode(struct ieee80211_device *ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset)
2129{
2130 struct r8192_priv *priv = ieee80211_priv(ieee->dev);
2131
2132
2133 if(priv->SetBWModeInProgress)
2134 return;
2135
2136 atomic_inc(&(priv->ieee80211->atm_swbw));
2137 priv->SetBWModeInProgress= true;
2138
2139 priv->CurrentChannelBW = Bandwidth;
2140
2141 if(Offset==HT_EXTCHNL_OFFSET_LOWER)
2142 priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_UPPER;
2143 else if(Offset==HT_EXTCHNL_OFFSET_UPPER)
2144 priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_LOWER;
2145 else
2146 priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2147
2148 //queue_work(priv->priv_wq, &(priv->SetBWModeWorkItem));
2149 // schedule_work(&(priv->SetBWModeWorkItem));
2150 rtl8192_SetBWModeWorkItem(priv);
2151
2152}
2153
2154
2155void InitialGain819xPci(struct ieee80211_device *ieee, u8 Operation)
2156{
2157#define SCAN_RX_INITIAL_GAIN 0x17
2158#define POWER_DETECTION_TH 0x08
2159 struct r8192_priv *priv = ieee80211_priv(ieee->dev);
2160 u32 BitMask;
2161 u8 initial_gain;
2162
2163 if(priv->up)
2164 {
2165 switch(Operation)
2166 {
2167 case IG_Backup:
2168 RT_TRACE(COMP_SCAN, "IG_Backup, backup the initial gain.\n");
2169 initial_gain = SCAN_RX_INITIAL_GAIN;//pHalData->DefaultInitialGain[0];//
2170 BitMask = bMaskByte0;
2171 if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
2172 rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x8); // FW DIG OFF
2173 priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(priv, rOFDM0_XAAGCCore1, BitMask);
2174 priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(priv, rOFDM0_XBAGCCore1, BitMask);
2175 priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(priv, rOFDM0_XCAGCCore1, BitMask);
2176 priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(priv, rOFDM0_XDAGCCore1, BitMask);
2177 BitMask = bMaskByte2;
2178 priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(priv, rCCK0_CCA, BitMask);
2179
2180 RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc50 is %x\n",priv->initgain_backup.xaagccore1);
2181 RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc58 is %x\n",priv->initgain_backup.xbagccore1);
2182 RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc60 is %x\n",priv->initgain_backup.xcagccore1);
2183 RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc68 is %x\n",priv->initgain_backup.xdagccore1);
2184 RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xa0a is %x\n",priv->initgain_backup.cca);
2185
2186 RT_TRACE(COMP_SCAN, "Write scan initial gain = 0x%x \n", initial_gain);
2187 write_nic_byte(priv, rOFDM0_XAAGCCore1, initial_gain);
2188 write_nic_byte(priv, rOFDM0_XBAGCCore1, initial_gain);
2189 write_nic_byte(priv, rOFDM0_XCAGCCore1, initial_gain);
2190 write_nic_byte(priv, rOFDM0_XDAGCCore1, initial_gain);
2191 RT_TRACE(COMP_SCAN, "Write scan 0xa0a = 0x%x \n", POWER_DETECTION_TH);
2192 write_nic_byte(priv, 0xa0a, POWER_DETECTION_TH);
2193 break;
2194 case IG_Restore:
2195 RT_TRACE(COMP_SCAN, "IG_Restore, restore the initial gain.\n");
2196 BitMask = 0x7f; //Bit0~ Bit6
2197 if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
2198 rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x8); // FW DIG OFF
2199
2200 rtl8192_setBBreg(priv, rOFDM0_XAAGCCore1, BitMask, (u32)priv->initgain_backup.xaagccore1);
2201 rtl8192_setBBreg(priv, rOFDM0_XBAGCCore1, BitMask, (u32)priv->initgain_backup.xbagccore1);
2202 rtl8192_setBBreg(priv, rOFDM0_XCAGCCore1, BitMask, (u32)priv->initgain_backup.xcagccore1);
2203 rtl8192_setBBreg(priv, rOFDM0_XDAGCCore1, BitMask, (u32)priv->initgain_backup.xdagccore1);
2204 BitMask = bMaskByte2;
2205 rtl8192_setBBreg(priv, rCCK0_CCA, BitMask, (u32)priv->initgain_backup.cca);
2206
2207 RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc50 is %x\n",priv->initgain_backup.xaagccore1);
2208 RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc58 is %x\n",priv->initgain_backup.xbagccore1);
2209 RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc60 is %x\n",priv->initgain_backup.xcagccore1);
2210 RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc68 is %x\n",priv->initgain_backup.xdagccore1);
2211 RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xa0a is %x\n",priv->initgain_backup.cca);
2212
2213 rtl8192_phy_setTxPower(priv, priv->ieee80211->current_network.channel);
2214
2215
2216 if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
2217 rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x1); // FW DIG ON
2218 break;
2219 default:
2220 RT_TRACE(COMP_SCAN, "Unknown IG Operation.\n");
2221 break;
2222 }
2223 }
2224}
2225
diff --git a/drivers/staging/rtl8192e/r819xE_phy.h b/drivers/staging/rtl8192e/r819xE_phy.h
new file mode 100644
index 00000000000..496e76fbadb
--- /dev/null
+++ b/drivers/staging/rtl8192e/r819xE_phy.h
@@ -0,0 +1,131 @@
1#ifndef _R819XU_PHY_H
2#define _R819XU_PHY_H
3
4/* Channel switch: the size of command tables for switch channel */
5#define MAX_PRECMD_CNT 16
6#define MAX_RFDEPENDCMD_CNT 16
7#define MAX_POSTCMD_CNT 16
8
9#define MACPHY_Array_PGLength 30
10#define Rtl819XMACPHY_Array_PG Rtl8192PciEMACPHY_Array_PG
11#define Rtl819XMACPHY_Array Rtl8192PciEMACPHY_Array
12#define RadioC_ArrayLength 1
13#define RadioD_ArrayLength 1
14#define Rtl819XRadioA_Array Rtl8192PciERadioA_Array
15#define Rtl819XRadioB_Array Rtl8192PciERadioB_Array
16#define Rtl819XRadioC_Array Rtl8192PciERadioC_Array
17#define Rtl819XRadioD_Array Rtl8192PciERadioD_Array
18#define Rtl819XAGCTAB_Array Rtl8192PciEAGCTAB_Array
19#define PHY_REGArrayLength 1
20#define Rtl819XPHY_REGArray Rtl8192PciEPHY_REGArray
21#define PHY_REG_1T2RArrayLength 296
22#define Rtl819XPHY_REG_1T2RArray Rtl8192PciEPHY_REG_1T2RArray
23
24#define AGCTAB_ArrayLength 384
25#define MACPHY_ArrayLength 18
26
27#define RadioA_ArrayLength 246
28#define RadioB_ArrayLength 78
29
30
31typedef enum _SwChnlCmdID {
32 CmdID_End,
33 CmdID_SetTxPowerLevel,
34 CmdID_BBRegWrite10,
35 CmdID_WritePortUlong,
36 CmdID_WritePortUshort,
37 CmdID_WritePortUchar,
38 CmdID_RF_WriteReg,
39} SwChnlCmdID;
40
41/* switch channel data structure */
42typedef struct _SwChnlCmd {
43 SwChnlCmdID CmdID;
44 u32 Para1;
45 u32 Para2;
46 u32 msDelay;
47} __attribute__ ((packed)) SwChnlCmd;
48
49extern u32 rtl819XMACPHY_Array_PG[];
50extern u32 rtl819XPHY_REG_1T2RArray[];
51extern u32 rtl819XAGCTAB_Array[];
52extern u32 rtl819XRadioA_Array[];
53extern u32 rtl819XRadioB_Array[];
54extern u32 rtl819XRadioC_Array[];
55extern u32 rtl819XRadioD_Array[];
56
57typedef enum _HW90_BLOCK {
58 HW90_BLOCK_MAC = 0,
59 HW90_BLOCK_PHY0 = 1,
60 HW90_BLOCK_PHY1 = 2,
61 HW90_BLOCK_RF = 3,
62 /* Don't ever use this. */
63 HW90_BLOCK_MAXIMUM = 4,
64} HW90_BLOCK_E, *PHW90_BLOCK_E;
65
66typedef enum _RF90_RADIO_PATH {
67 /* Radio paths */
68 RF90_PATH_A = 0,
69 RF90_PATH_B = 1,
70 RF90_PATH_C = 2,
71 RF90_PATH_D = 3,
72
73 /* Max RF number 92 support */
74 RF90_PATH_MAX
75} RF90_RADIO_PATH_E, *PRF90_RADIO_PATH_E;
76
77#define bMaskByte0 0xff
78#define bMaskByte1 0xff00
79#define bMaskByte2 0xff0000
80#define bMaskByte3 0xff000000
81#define bMaskHWord 0xffff0000
82#define bMaskLWord 0x0000ffff
83#define bMaskDWord 0xffffffff
84
85u8 rtl8192_phy_CheckIsLegalRFPath(struct r8192_priv *priv, u32 eRFPath);
86
87void rtl8192_setBBreg(struct r8192_priv *priv, u32 dwRegAddr,
88 u32 dwBitMask, u32 dwData);
89
90u32 rtl8192_QueryBBReg(struct r8192_priv *priv, u32 dwRegAddr,
91 u32 dwBitMask);
92
93void rtl8192_phy_SetRFReg(struct r8192_priv *priv,
94 RF90_RADIO_PATH_E eRFPath, u32 RegAddr,
95 u32 BitMask, u32 Data);
96
97u32 rtl8192_phy_QueryRFReg(struct r8192_priv *priv,
98 RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask);
99
100void rtl8192_phy_configmac(struct r8192_priv *priv);
101
102void rtl8192_phyConfigBB(struct r8192_priv *priv, u8 ConfigType);
103
104RT_STATUS rtl8192_phy_checkBBAndRF(struct r8192_priv *priv,
105 HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
106
107RT_STATUS rtl8192_BBConfig(struct r8192_priv *priv);
108
109void rtl8192_phy_getTxPower(struct r8192_priv *priv);
110
111void rtl8192_phy_setTxPower(struct r8192_priv *priv, u8 channel);
112
113RT_STATUS rtl8192_phy_RFConfig(struct r8192_priv *priv);
114
115void rtl8192_phy_updateInitGain(struct r8192_priv *priv);
116
117u8 rtl8192_phy_ConfigRFWithHeaderFile(struct r8192_priv *priv,
118 RF90_RADIO_PATH_E eRFPath);
119
120u8 rtl8192_phy_SwChnl(struct ieee80211_device *ieee80211, u8 channel);
121
122void rtl8192_SetBWMode(struct ieee80211_device *ieee80211,
123 HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
124
125void rtl8192_SwChnl_WorkItem(struct r8192_priv *priv);
126
127void rtl8192_SetBWModeWorkItem(struct r8192_priv *priv);
128
129void InitialGain819xPci(struct ieee80211_device *ieee, u8 Operation);
130
131#endif /* _R819XU_PHY_H */
diff --git a/drivers/staging/rtl8192e/r819xE_phyreg.h b/drivers/staging/rtl8192e/r819xE_phyreg.h
new file mode 100644
index 00000000000..d5de279f664
--- /dev/null
+++ b/drivers/staging/rtl8192e/r819xE_phyreg.h
@@ -0,0 +1,915 @@
1#ifndef _R819XU_PHYREG_H
2#define _R819XU_PHYREG_H
3
4
5#define RF_DATA 0x1d4 // FW will write RF data in the register.
6
7//Register //duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF
8//page 1
9#define rPMAC_Reset 0x100
10#define rPMAC_TxStart 0x104
11#define rPMAC_TxLegacySIG 0x108
12#define rPMAC_TxHTSIG1 0x10c
13#define rPMAC_TxHTSIG2 0x110
14#define rPMAC_PHYDebug 0x114
15#define rPMAC_TxPacketNum 0x118
16#define rPMAC_TxIdle 0x11c
17#define rPMAC_TxMACHeader0 0x120
18#define rPMAC_TxMACHeader1 0x124
19#define rPMAC_TxMACHeader2 0x128
20#define rPMAC_TxMACHeader3 0x12c
21#define rPMAC_TxMACHeader4 0x130
22#define rPMAC_TxMACHeader5 0x134
23#define rPMAC_TxDataType 0x138
24#define rPMAC_TxRandomSeed 0x13c
25#define rPMAC_CCKPLCPPreamble 0x140
26#define rPMAC_CCKPLCPHeader 0x144
27#define rPMAC_CCKCRC16 0x148
28#define rPMAC_OFDMRxCRC32OK 0x170
29#define rPMAC_OFDMRxCRC32Er 0x174
30#define rPMAC_OFDMRxParityEr 0x178
31#define rPMAC_OFDMRxCRC8Er 0x17c
32#define rPMAC_CCKCRxRC16Er 0x180
33#define rPMAC_CCKCRxRC32Er 0x184
34#define rPMAC_CCKCRxRC32OK 0x188
35#define rPMAC_TxStatus 0x18c
36
37//90P
38#define MCS_TXAGC 0x340 // MCS AGC
39#define CCK_TXAGC 0x348 // CCK AGC
40
41#define MacBlkCtrl 0x403 // Mac block on/off control register
42
43//page8
44#define rFPGA0_RFMOD 0x800 //RF mode & CCK TxSC
45#define rFPGA0_TxInfo 0x804
46#define rFPGA0_PSDFunction 0x808
47#define rFPGA0_TxGainStage 0x80c
48#define rFPGA0_RFTiming1 0x810
49#define rFPGA0_RFTiming2 0x814
50//#define rFPGA0_XC_RFTiming 0x818
51//#define rFPGA0_XD_RFTiming 0x81c
52#define rFPGA0_XA_HSSIParameter1 0x820
53#define rFPGA0_XA_HSSIParameter2 0x824
54#define rFPGA0_XB_HSSIParameter1 0x828
55#define rFPGA0_XB_HSSIParameter2 0x82c
56#define rFPGA0_XC_HSSIParameter1 0x830
57#define rFPGA0_XC_HSSIParameter2 0x834
58#define rFPGA0_XD_HSSIParameter1 0x838
59#define rFPGA0_XD_HSSIParameter2 0x83c
60#define rFPGA0_XA_LSSIParameter 0x840
61#define rFPGA0_XB_LSSIParameter 0x844
62#define rFPGA0_XC_LSSIParameter 0x848
63#define rFPGA0_XD_LSSIParameter 0x84c
64#define rFPGA0_RFWakeUpParameter 0x850
65#define rFPGA0_RFSleepUpParameter 0x854
66#define rFPGA0_XAB_SwitchControl 0x858
67#define rFPGA0_XCD_SwitchControl 0x85c
68#define rFPGA0_XA_RFInterfaceOE 0x860
69#define rFPGA0_XB_RFInterfaceOE 0x864
70#define rFPGA0_XC_RFInterfaceOE 0x868
71#define rFPGA0_XD_RFInterfaceOE 0x86c
72#define rFPGA0_XAB_RFInterfaceSW 0x870
73#define rFPGA0_XCD_RFInterfaceSW 0x874
74#define rFPGA0_XAB_RFParameter 0x878
75#define rFPGA0_XCD_RFParameter 0x87c
76#define rFPGA0_AnalogParameter1 0x880
77#define rFPGA0_AnalogParameter2 0x884
78#define rFPGA0_AnalogParameter3 0x888
79#define rFPGA0_AnalogParameter4 0x88c
80#define rFPGA0_XA_LSSIReadBack 0x8a0
81#define rFPGA0_XB_LSSIReadBack 0x8a4
82#define rFPGA0_XC_LSSIReadBack 0x8a8
83#define rFPGA0_XD_LSSIReadBack 0x8ac
84#define rFPGA0_PSDReport 0x8b4
85#define rFPGA0_XAB_RFInterfaceRB 0x8e0
86#define rFPGA0_XCD_RFInterfaceRB 0x8e4
87
88/* Page 9 - RF mode & OFDM TxSC */
89#define rFPGA1_RFMOD 0x900
90#define rFPGA1_TxBlock 0x904
91#define rFPGA1_DebugSelect 0x908
92#define rFPGA1_TxInfo 0x90c
93
94/* Page a */
95#define rCCK0_System 0xa00
96#define rCCK0_AFESetting 0xa04
97#define rCCK0_CCA 0xa08
98/* AGC default value, saturation level */
99#define rCCK0_RxAGC1 0xa0c
100/* AGC & DAGC */
101#define rCCK0_RxAGC2 0xa10
102#define rCCK0_RxHP 0xa14
103/* Timing recovery & channel estimation threshold */
104#define rCCK0_DSPParameter1 0xa18
105/* SQ threshold */
106#define rCCK0_DSPParameter2 0xa1c
107#define rCCK0_TxFilter1 0xa20
108#define rCCK0_TxFilter2 0xa24
109/* Debug port and TX filter 3 */
110#define rCCK0_DebugPort 0xa28
111#define rCCK0_FalseAlarmReport 0xa2c
112#define rCCK0_TRSSIReport 0xa50
113#define rCCK0_RxReport 0xa54
114#define rCCK0_FACounterLower 0xa5c
115#define rCCK0_FACounterUpper 0xa58
116
117/* Page c */
118#define rOFDM0_LSTF 0xc00
119#define rOFDM0_TRxPathEnable 0xc04
120#define rOFDM0_TRMuxPar 0xc08
121#define rOFDM0_TRSWIsolation 0xc0c
122/* RxIQ DC offset, Rx digital filter, DC notch filter */
123#define rOFDM0_XARxAFE 0xc10
124/* RxIQ imblance matrix */
125#define rOFDM0_XARxIQImbalance 0xc14
126#define rOFDM0_XBRxAFE 0xc18
127#define rOFDM0_XBRxIQImbalance 0xc1c
128#define rOFDM0_XCRxAFE 0xc20
129#define rOFDM0_XCRxIQImbalance 0xc24
130#define rOFDM0_XDRxAFE 0xc28
131#define rOFDM0_XDRxIQImbalance 0xc2c
132/* PD, BW & SBD */
133#define rOFDM0_RxDetector1 0xc30
134/* SBD */
135#define rOFDM0_RxDetector2 0xc34
136/* Frame Sync */
137#define rOFDM0_RxDetector3 0xc38
138/* PD, SBD, Frame Sync & Short-GI */
139#define rOFDM0_RxDetector4 0xc3c
140/* Rx Sync Path */
141#define rOFDM0_RxDSP 0xc40
142/* CFO & DAGC */
143#define rOFDM0_CFOandDAGC 0xc44
144/* CCA Drop threshold */
145#define rOFDM0_CCADropThreshold 0xc48
146/* Energy CCA */
147#define rOFDM0_ECCAThreshold 0xc4c
148#define rOFDM0_XAAGCCore1 0xc50
149#define rOFDM0_XAAGCCore2 0xc54
150#define rOFDM0_XBAGCCore1 0xc58
151#define rOFDM0_XBAGCCore2 0xc5c
152#define rOFDM0_XCAGCCore1 0xc60
153#define rOFDM0_XCAGCCore2 0xc64
154#define rOFDM0_XDAGCCore1 0xc68
155#define rOFDM0_XDAGCCore2 0xc6c
156#define rOFDM0_AGCParameter1 0xc70
157#define rOFDM0_AGCParameter2 0xc74
158#define rOFDM0_AGCRSSITable 0xc78
159#define rOFDM0_HTSTFAGC 0xc7c
160#define rOFDM0_XATxIQImbalance 0xc80
161#define rOFDM0_XATxAFE 0xc84
162#define rOFDM0_XBTxIQImbalance 0xc88
163#define rOFDM0_XBTxAFE 0xc8c
164#define rOFDM0_XCTxIQImbalance 0xc90
165#define rOFDM0_XCTxAFE 0xc94
166#define rOFDM0_XDTxIQImbalance 0xc98
167#define rOFDM0_XDTxAFE 0xc9c
168#define rOFDM0_RxHPParameter 0xce0
169#define rOFDM0_TxPseudoNoiseWgt 0xce4
170#define rOFDM0_FrameSync 0xcf0
171#define rOFDM0_DFSReport 0xcf4
172#define rOFDM0_TxCoeff1 0xca4
173#define rOFDM0_TxCoeff2 0xca8
174#define rOFDM0_TxCoeff3 0xcac
175#define rOFDM0_TxCoeff4 0xcb0
176#define rOFDM0_TxCoeff5 0xcb4
177#define rOFDM0_TxCoeff6 0xcb8
178
179
180/* Page d */
181#define rOFDM1_LSTF 0xd00
182#define rOFDM1_TRxPathEnable 0xd04
183#define rOFDM1_CFO 0xd08
184#define rOFDM1_CSI1 0xd10
185#define rOFDM1_SBD 0xd14
186#define rOFDM1_CSI2 0xd18
187#define rOFDM1_CFOTracking 0xd2c
188#define rOFDM1_TRxMesaure1 0xd34
189#define rOFDM1_IntfDet 0xd3c
190#define rOFDM1_PseudoNoiseStateAB 0xd50
191#define rOFDM1_PseudoNoiseStateCD 0xd54
192#define rOFDM1_RxPseudoNoiseWgt 0xd58
193/* cca, parity fail */
194#define rOFDM_PHYCounter1 0xda0
195/* rate illegal, crc8 fail */
196#define rOFDM_PHYCounter2 0xda4
197/* MCS not supported */
198#define rOFDM_PHYCounter3 0xda8
199#define rOFDM_ShortCFOAB 0xdac
200#define rOFDM_ShortCFOCD 0xdb0
201#define rOFDM_LongCFOAB 0xdb4
202#define rOFDM_LongCFOCD 0xdb8
203#define rOFDM_TailCFOAB 0xdbc
204#define rOFDM_TailCFOCD 0xdc0
205#define rOFDM_PWMeasure1 0xdc4
206#define rOFDM_PWMeasure2 0xdc8
207#define rOFDM_BWReport 0xdcc
208#define rOFDM_AGCReport 0xdd0
209#define rOFDM_RxSNR 0xdd4
210#define rOFDM_RxEVMCSI 0xdd8
211#define rOFDM_SIGReport 0xddc
212
213/* Page e */
214#define rTxAGC_Rate18_06 0xe00
215#define rTxAGC_Rate54_24 0xe04
216#define rTxAGC_CCK_Mcs32 0xe08
217#define rTxAGC_Mcs03_Mcs00 0xe10
218#define rTxAGC_Mcs07_Mcs04 0xe14
219#define rTxAGC_Mcs11_Mcs08 0xe18
220#define rTxAGC_Mcs15_Mcs12 0xe1c
221
222
223/* RF Zebra 1 */
224#define rZebra1_HSSIEnable 0x0
225#define rZebra1_TRxEnable1 0x1
226#define rZebra1_TRxEnable2 0x2
227#define rZebra1_AGC 0x4
228#define rZebra1_ChargePump 0x5
229#define rZebra1_Channel 0x7
230#define rZebra1_TxGain 0x8
231#define rZebra1_TxLPF 0x9
232#define rZebra1_RxLPF 0xb
233#define rZebra1_RxHPFCorner 0xc
234
235/* Zebra 4 */
236#define rGlobalCtrl 0
237#define rRTL8256_TxLPF 19
238#define rRTL8256_RxLPF 11
239
240/* RTL8258 */
241#define rRTL8258_TxLPF 0x11
242#define rRTL8258_RxLPF 0x13
243#define rRTL8258_RSSILPF 0xa
244
245/* Bit Mask */
246/* Page 1 */
247#define bBBResetB 0x100
248#define bGlobalResetB 0x200
249#define bOFDMTxStart 0x4
250#define bCCKTxStart 0x8
251#define bCRC32Debug 0x100
252#define bPMACLoopback 0x10
253#define bTxLSIG 0xffffff
254#define bOFDMTxRate 0xf
255#define bOFDMTxReserved 0x10
256#define bOFDMTxLength 0x1ffe0
257#define bOFDMTxParity 0x20000
258#define bTxHTSIG1 0xffffff
259#define bTxHTMCSRate 0x7f
260#define bTxHTBW 0x80
261#define bTxHTLength 0xffff00
262#define bTxHTSIG2 0xffffff
263#define bTxHTSmoothing 0x1
264#define bTxHTSounding 0x2
265#define bTxHTReserved 0x4
266#define bTxHTAggreation 0x8
267#define bTxHTSTBC 0x30
268#define bTxHTAdvanceCoding 0x40
269#define bTxHTShortGI 0x80
270#define bTxHTNumberHT_LTF 0x300
271#define bTxHTCRC8 0x3fc00
272#define bCounterReset 0x10000
273#define bNumOfOFDMTx 0xffff
274#define bNumOfCCKTx 0xffff0000
275#define bTxIdleInterval 0xffff
276#define bOFDMService 0xffff0000
277#define bTxMACHeader 0xffffffff
278#define bTxDataInit 0xff
279#define bTxHTMode 0x100
280#define bTxDataType 0x30000
281#define bTxRandomSeed 0xffffffff
282#define bCCKTxPreamble 0x1
283#define bCCKTxSFD 0xffff0000
284#define bCCKTxSIG 0xff
285#define bCCKTxService 0xff00
286#define bCCKLengthExt 0x8000
287#define bCCKTxLength 0xffff0000
288#define bCCKTxCRC16 0xffff
289#define bCCKTxStatus 0x1
290#define bOFDMTxStatus 0x2
291
292/* Page 8 */
293#define bRFMOD 0x1
294#define bJapanMode 0x2
295#define bCCKTxSC 0x30
296#define bCCKEn 0x1000000
297#define bOFDMEn 0x2000000
298#define bOFDMRxADCPhase 0x10000
299#define bOFDMTxDACPhase 0x40000
300#define bXATxAGC 0x3f
301#define bXBTxAGC 0xf00
302#define bXCTxAGC 0xf000
303#define bXDTxAGC 0xf0000
304#define bPAStart 0xf0000000
305#define bTRStart 0x00f00000
306#define bRFStart 0x0000f000
307#define bBBStart 0x000000f0
308#define bBBCCKStart 0x0000000f
309/* Reg)x814 */
310#define bPAEnd 0xf
311#define bTREnd 0x0f000000
312#define bRFEnd 0x000f0000
313/* T2R */
314#define bCCAMask 0x000000f0
315#define bR2RCCAMask 0x00000f00
316#define bHSSI_R2TDelay 0xf8000000
317#define bHSSI_T2RDelay 0xf80000
318/* Channel gain at continue TX. */
319#define bContTxHSSI 0x400
320#define bIGFromCCK 0x200
321#define bAGCAddress 0x3f
322#define bRxHPTx 0x7000
323#define bRxHPT2R 0x38000
324#define bRxHPCCKIni 0xc0000
325#define bAGCTxCode 0xc00000
326#define bAGCRxCode 0x300000
327#define b3WireDataLength 0x800
328#define b3WireAddressLength 0x400
329#define b3WireRFPowerDown 0x1
330/*#define bHWSISelect 0x8 */
331#define b5GPAPEPolarity 0x40000000
332#define b2GPAPEPolarity 0x80000000
333#define bRFSW_TxDefaultAnt 0x3
334#define bRFSW_TxOptionAnt 0x30
335#define bRFSW_RxDefaultAnt 0x300
336#define bRFSW_RxOptionAnt 0x3000
337#define bRFSI_3WireData 0x1
338#define bRFSI_3WireClock 0x2
339#define bRFSI_3WireLoad 0x4
340#define bRFSI_3WireRW 0x8
341/* 3-wire total control */
342#define bRFSI_3Wire 0xf
343#define bRFSI_RFENV 0x10
344#define bRFSI_TRSW 0x20
345#define bRFSI_TRSWB 0x40
346#define bRFSI_ANTSW 0x100
347#define bRFSI_ANTSWB 0x200
348#define bRFSI_PAPE 0x400
349#define bRFSI_PAPE5G 0x800
350#define bBandSelect 0x1
351#define bHTSIG2_GI 0x80
352#define bHTSIG2_Smoothing 0x01
353#define bHTSIG2_Sounding 0x02
354#define bHTSIG2_Aggreaton 0x08
355#define bHTSIG2_STBC 0x30
356#define bHTSIG2_AdvCoding 0x40
357#define bHTSIG2_NumOfHTLTF 0x300
358#define bHTSIG2_CRC8 0x3fc
359#define bHTSIG1_MCS 0x7f
360#define bHTSIG1_BandWidth 0x80
361#define bHTSIG1_HTLength 0xffff
362#define bLSIG_Rate 0xf
363#define bLSIG_Reserved 0x10
364#define bLSIG_Length 0x1fffe
365#define bLSIG_Parity 0x20
366#define bCCKRxPhase 0x4
367/* LSSI "read" address */
368#define bLSSIReadAddress 0x3f000000
369/* LSSI "read" edge signal */
370#define bLSSIReadEdge 0x80000000
371#define bLSSIReadBackData 0xfff
372#define bLSSIReadOKFlag 0x1000
373/* 0: 44 MHz, 1: 88MHz */
374#define bCCKSampleRate 0x8
375
376#define bRegulator0Standby 0x1
377#define bRegulatorPLLStandby 0x2
378#define bRegulator1Standby 0x4
379#define bPLLPowerUp 0x8
380#define bDPLLPowerUp 0x10
381#define bDA10PowerUp 0x20
382#define bAD7PowerUp 0x200
383#define bDA6PowerUp 0x2000
384#define bXtalPowerUp 0x4000
385#define b40MDClkPowerUP 0x8000
386#define bDA6DebugMode 0x20000
387#define bDA6Swing 0x380000
388#define bADClkPhase 0x4000000
389#define b80MClkDelay 0x18000000
390#define bAFEWatchDogEnable 0x20000000
391#define bXtalCap 0x0f000000
392#define bXtalCap01 0xc0000000
393#define bXtalCap23 0x3
394#define bXtalCap92x 0x0f000000
395#define bIntDifClkEnable 0x400
396#define bExtSigClkEnable 0x800
397#define bBandgapMbiasPowerUp 0x10000
398#define bAD11SHGain 0xc0000
399#define bAD11InputRange 0x700000
400#define bAD11OPCurrent 0x3800000
401#define bIPathLoopback 0x4000000
402#define bQPathLoopback 0x8000000
403#define bAFELoopback 0x10000000
404#define bDA10Swing 0x7e0
405#define bDA10Reverse 0x800
406#define bDAClkSource 0x1000
407#define bAD7InputRange 0x6000
408#define bAD7Gain 0x38000
409#define bAD7OutputCMMode 0x40000
410#define bAD7InputCMMode 0x380000
411#define bAD7Current 0xc00000
412#define bRegulatorAdjust 0x7000000
413#define bAD11PowerUpAtTx 0x1
414#define bDA10PSAtTx 0x10
415#define bAD11PowerUpAtRx 0x100
416#define bDA10PSAtRx 0x1000
417
418#define bCCKRxAGCFormat 0x200
419
420#define bPSDFFTSamplepPoint 0xc000
421#define bPSDAverageNum 0x3000
422#define bIQPathControl 0xc00
423#define bPSDFreq 0x3ff
424#define bPSDAntennaPath 0x30
425#define bPSDIQSwitch 0x40
426#define bPSDRxTrigger 0x400000
427#define bPSDTxTrigger 0x80000000
428#define bPSDSineToneScale 0x7f000000
429#define bPSDReport 0xffff
430
431/* Page 8 */
432#define bOFDMTxSC 0x30000000
433#define bCCKTxOn 0x1
434#define bOFDMTxOn 0x2
435/* Reset debug page and also HWord, LWord */
436#define bDebugPage 0xfff
437/* Reset debug page and LWord */
438#define bDebugItem 0xff
439#define bAntL 0x10
440#define bAntNonHT 0x100
441#define bAntHT1 0x1000
442#define bAntHT2 0x10000
443#define bAntHT1S1 0x100000
444#define bAntNonHTS1 0x1000000
445
446/* Page a */
447#define bCCKBBMode 0x3
448#define bCCKTxPowerSaving 0x80
449#define bCCKRxPowerSaving 0x40
450#define bCCKSideBand 0x10
451#define bCCKScramble 0x8
452#define bCCKAntDiversity 0x8000
453#define bCCKCarrierRecovery 0x4000
454#define bCCKTxRate 0x3000
455#define bCCKDCCancel 0x0800
456#define bCCKISICancel 0x0400
457#define bCCKMatchFilter 0x0200
458#define bCCKEqualizer 0x0100
459#define bCCKPreambleDetect 0x800000
460#define bCCKFastFalseCCA 0x400000
461#define bCCKChEstStart 0x300000
462#define bCCKCCACount 0x080000
463#define bCCKcs_lim 0x070000
464#define bCCKBistMode 0x80000000
465#define bCCKCCAMask 0x40000000
466#define bCCKTxDACPhase 0x4
467/* r_rx_clk */
468#define bCCKRxADCPhase 0x20000000
469#define bCCKr_cp_mode0 0x0100
470#define bCCKTxDCOffset 0xf0
471#define bCCKRxDCOffset 0xf
472#define bCCKCCAMode 0xc000
473#define bCCKFalseCS_lim 0x3f00
474#define bCCKCS_ratio 0xc00000
475#define bCCKCorgBit_sel 0x300000
476#define bCCKPD_lim 0x0f0000
477#define bCCKNewCCA 0x80000000
478#define bCCKRxHPofIG 0x8000
479#define bCCKRxIG 0x7f00
480#define bCCKLNAPolarity 0x800000
481#define bCCKRx1stGain 0x7f0000
482/* CCK Rx Initial gain polarity */
483#define bCCKRFExtend 0x20000000
484#define bCCKRxAGCSatLevel 0x1f000000
485#define bCCKRxAGCSatCount 0xe0
486/* AGCSAmp_dly */
487#define bCCKRxRFSettle 0x1f
488#define bCCKFixedRxAGC 0x8000
489/*#define bCCKRxAGCFormat 0x4000 remove to HSSI register 0x824 */
490#define bCCKAntennaPolarity 0x2000
491#define bCCKTxFilterType 0x0c00
492#define bCCKRxAGCReportType 0x0300
493#define bCCKRxDAGCEn 0x80000000
494#define bCCKRxDAGCPeriod 0x20000000
495#define bCCKRxDAGCSatLevel 0x1f000000
496#define bCCKTimingRecovery 0x800000
497#define bCCKTxC0 0x3f0000
498#define bCCKTxC1 0x3f000000
499#define bCCKTxC2 0x3f
500#define bCCKTxC3 0x3f00
501#define bCCKTxC4 0x3f0000
502#define bCCKTxC5 0x3f000000
503#define bCCKTxC6 0x3f
504#define bCCKTxC7 0x3f00
505#define bCCKDebugPort 0xff0000
506#define bCCKDACDebug 0x0f000000
507#define bCCKFalseAlarmEnable 0x8000
508#define bCCKFalseAlarmRead 0x4000
509#define bCCKTRSSI 0x7f
510#define bCCKRxAGCReport 0xfe
511#define bCCKRxReport_AntSel 0x80000000
512#define bCCKRxReport_MFOff 0x40000000
513#define bCCKRxRxReport_SQLoss 0x20000000
514#define bCCKRxReport_Pktloss 0x10000000
515#define bCCKRxReport_Lockedbit 0x08000000
516#define bCCKRxReport_RateError 0x04000000
517#define bCCKRxReport_RxRate 0x03000000
518#define bCCKRxFACounterLower 0xff
519#define bCCKRxFACounterUpper 0xff000000
520#define bCCKRxHPAGCStart 0xe000
521#define bCCKRxHPAGCFinal 0x1c00
522
523#define bCCKRxFalseAlarmEnable 0x8000
524#define bCCKFACounterFreeze 0x4000
525
526#define bCCKTxPathSel 0x10000000
527#define bCCKDefaultRxPath 0xc000000
528#define bCCKOptionRxPath 0x3000000
529
530/* Page c */
531#define bNumOfSTF 0x3
532#define bShift_L 0xc0
533#define bGI_TH 0xc
534#define bRxPathA 0x1
535#define bRxPathB 0x2
536#define bRxPathC 0x4
537#define bRxPathD 0x8
538#define bTxPathA 0x1
539#define bTxPathB 0x2
540#define bTxPathC 0x4
541#define bTxPathD 0x8
542#define bTRSSIFreq 0x200
543#define bADCBackoff 0x3000
544#define bDFIRBackoff 0xc000
545#define bTRSSILatchPhase 0x10000
546#define bRxIDCOffset 0xff
547#define bRxQDCOffset 0xff00
548#define bRxDFIRMode 0x1800000
549#define bRxDCNFType 0xe000000
550#define bRXIQImb_A 0x3ff
551#define bRXIQImb_B 0xfc00
552#define bRXIQImb_C 0x3f0000
553#define bRXIQImb_D 0xffc00000
554#define bDC_dc_Notch 0x60000
555#define bRxNBINotch 0x1f000000
556#define bPD_TH 0xf
557#define bPD_TH_Opt2 0xc000
558#define bPWED_TH 0x700
559#define bIfMF_Win_L 0x800
560#define bPD_Option 0x1000
561#define bMF_Win_L 0xe000
562#define bBW_Search_L 0x30000
563#define bwin_enh_L 0xc0000
564#define bBW_TH 0x700000
565#define bED_TH2 0x3800000
566#define bBW_option 0x4000000
567#define bRatio_TH 0x18000000
568#define bWindow_L 0xe0000000
569#define bSBD_Option 0x1
570#define bFrame_TH 0x1c
571#define bFS_Option 0x60
572#define bDC_Slope_check 0x80
573#define bFGuard_Counter_DC_L 0xe00
574#define bFrame_Weight_Short 0x7000
575#define bSub_Tune 0xe00000
576#define bFrame_DC_Length 0xe000000
577#define bSBD_start_offset 0x30000000
578#define bFrame_TH_2 0x7
579#define bFrame_GI2_TH 0x38
580#define bGI2_Sync_en 0x40
581#define bSarch_Short_Early 0x300
582#define bSarch_Short_Late 0xc00
583#define bSarch_GI2_Late 0x70000
584#define bCFOAntSum 0x1
585#define bCFOAcc 0x2
586#define bCFOStartOffset 0xc
587#define bCFOLookBack 0x70
588#define bCFOSumWeight 0x80
589#define bDAGCEnable 0x10000
590#define bTXIQImb_A 0x3ff
591#define bTXIQImb_B 0xfc00
592#define bTXIQImb_C 0x3f0000
593#define bTXIQImb_D 0xffc00000
594#define bTxIDCOffset 0xff
595#define bTxQDCOffset 0xff00
596#define bTxDFIRMode 0x10000
597#define bTxPesudoNoiseOn 0x4000000
598#define bTxPesudoNoise_A 0xff
599#define bTxPesudoNoise_B 0xff00
600#define bTxPesudoNoise_C 0xff0000
601#define bTxPesudoNoise_D 0xff000000
602#define bCCADropOption 0x20000
603#define bCCADropThres 0xfff00000
604#define bEDCCA_H 0xf
605#define bEDCCA_L 0xf0
606#define bLambda_ED 0x300
607#define bRxInitialGain 0x7f
608#define bRxAntDivEn 0x80
609#define bRxAGCAddressForLNA 0x7f00
610#define bRxHighPowerFlow 0x8000
611#define bRxAGCFreezeThres 0xc0000
612#define bRxFreezeStep_AGC1 0x300000
613#define bRxFreezeStep_AGC2 0xc00000
614#define bRxFreezeStep_AGC3 0x3000000
615#define bRxFreezeStep_AGC0 0xc000000
616#define bRxRssi_Cmp_En 0x10000000
617#define bRxQuickAGCEn 0x20000000
618#define bRxAGCFreezeThresMode 0x40000000
619#define bRxOverFlowCheckType 0x80000000
620#define bRxAGCShift 0x7f
621#define bTRSW_Tri_Only 0x80
622#define bPowerThres 0x300
623#define bRxAGCEn 0x1
624#define bRxAGCTogetherEn 0x2
625#define bRxAGCMin 0x4
626#define bRxHP_Ini 0x7
627#define bRxHP_TRLNA 0x70
628#define bRxHP_RSSI 0x700
629#define bRxHP_BBP1 0x7000
630#define bRxHP_BBP2 0x70000
631#define bRxHP_BBP3 0x700000
632/* The threshold for high power */
633#define bRSSI_H 0x7f0000
634/* The threshold for ant diversity */
635#define bRSSI_Gen 0x7f000000
636#define bRxSettle_TRSW 0x7
637#define bRxSettle_LNA 0x38
638#define bRxSettle_RSSI 0x1c0
639#define bRxSettle_BBP 0xe00
640#define bRxSettle_RxHP 0x7000
641#define bRxSettle_AntSW_RSSI 0x38000
642#define bRxSettle_AntSW 0xc0000
643#define bRxProcessTime_DAGC 0x300000
644#define bRxSettle_HSSI 0x400000
645#define bRxProcessTime_BBPPW 0x800000
646#define bRxAntennaPowerShift 0x3000000
647#define bRSSITableSelect 0xc000000
648#define bRxHP_Final 0x7000000
649#define bRxHTSettle_BBP 0x7
650#define bRxHTSettle_HSSI 0x8
651#define bRxHTSettle_RxHP 0x70
652#define bRxHTSettle_BBPPW 0x80
653#define bRxHTSettle_Idle 0x300
654#define bRxHTSettle_Reserved 0x1c00
655#define bRxHTRxHPEn 0x8000
656#define bRxHTAGCFreezeThres 0x30000
657#define bRxHTAGCTogetherEn 0x40000
658#define bRxHTAGCMin 0x80000
659#define bRxHTAGCEn 0x100000
660#define bRxHTDAGCEn 0x200000
661#define bRxHTRxHP_BBP 0x1c00000
662#define bRxHTRxHP_Final 0xe0000000
663#define bRxPWRatioTH 0x3
664#define bRxPWRatioEn 0x4
665#define bRxMFHold 0x3800
666#define bRxPD_Delay_TH1 0x38
667#define bRxPD_Delay_TH2 0x1c0
668#define bRxPD_DC_COUNT_MAX 0x600
669/*#define bRxMF_Hold 0x3800*/
670#define bRxPD_Delay_TH 0x8000
671#define bRxProcess_Delay 0xf0000
672#define bRxSearchrange_GI2_Early 0x700000
673#define bRxFrame_Guard_Counter_L 0x3800000
674#define bRxSGI_Guard_L 0xc000000
675#define bRxSGI_Search_L 0x30000000
676#define bRxSGI_TH 0xc0000000
677#define bDFSCnt0 0xff
678#define bDFSCnt1 0xff00
679#define bDFSFlag 0xf0000
680
681#define bMFWeightSum 0x300000
682#define bMinIdxTH 0x7f000000
683
684#define bDAFormat 0x40000
685
686#define bTxChEmuEnable 0x01000000
687
688#define bTRSWIsolation_A 0x7f
689#define bTRSWIsolation_B 0x7f00
690#define bTRSWIsolation_C 0x7f0000
691#define bTRSWIsolation_D 0x7f000000
692
693#define bExtLNAGain 0x7c00
694
695/* Page d */
696#define bSTBCEn 0x4
697#define bAntennaMapping 0x10
698#define bNss 0x20
699#define bCFOAntSumD 0x200
700#define bPHYCounterReset 0x8000000
701#define bCFOReportGet 0x4000000
702#define bOFDMContinueTx 0x10000000
703#define bOFDMSingleCarrier 0x20000000
704#define bOFDMSingleTone 0x40000000
705/*#define bRxPath1 0x01
706#define bRxPath2 0x02
707#define bRxPath3 0x04
708#define bRxPath4 0x08
709#define bTxPath1 0x10
710#define bTxPath2 0x20*/
711#define bHTDetect 0x100
712#define bCFOEn 0x10000
713#define bCFOValue 0xfff00000
714#define bSigTone_Re 0x3f
715#define bSigTone_Im 0x7f00
716#define bCounter_CCA 0xffff
717#define bCounter_ParityFail 0xffff0000
718#define bCounter_RateIllegal 0xffff
719#define bCounter_CRC8Fail 0xffff0000
720#define bCounter_MCSNoSupport 0xffff
721#define bCounter_FastSync 0xffff
722#define bShortCFO 0xfff
723/* total */
724#define bShortCFOTLength 12
725/* fraction */
726#define bShortCFOFLength 11
727#define bLongCFO 0x7ff
728#define bLongCFOTLength 11
729#define bLongCFOFLength 11
730#define bTailCFO 0x1fff
731#define bTailCFOTLength 13
732#define bTailCFOFLength 12
733
734#define bmax_en_pwdB 0xffff
735#define bCC_power_dB 0xffff0000
736#define bnoise_pwdB 0xffff
737#define bPowerMeasTLength 10
738#define bPowerMeasFLength 3
739#define bRx_HT_BW 0x1
740#define bRxSC 0x6
741#define bRx_HT 0x8
742
743#define bNB_intf_det_on 0x1
744#define bIntf_win_len_cfg 0x30
745#define bNB_Intf_TH_cfg 0x1c0
746
747#define bRFGain 0x3f
748#define bTableSel 0x40
749#define bTRSW 0x80
750
751#define bRxSNR_A 0xff
752#define bRxSNR_B 0xff00
753#define bRxSNR_C 0xff0000
754#define bRxSNR_D 0xff000000
755#define bSNREVMTLength 8
756#define bSNREVMFLength 1
757
758#define bCSI1st 0xff
759#define bCSI2nd 0xff00
760#define bRxEVM1st 0xff0000
761#define bRxEVM2nd 0xff000000
762
763#define bSIGEVM 0xff
764#define bPWDB 0xff00
765#define bSGIEN 0x10000
766
767#define bSFactorQAM1 0xf
768#define bSFactorQAM2 0xf0
769#define bSFactorQAM3 0xf00
770#define bSFactorQAM4 0xf000
771#define bSFactorQAM5 0xf0000
772#define bSFactorQAM6 0xf0000
773#define bSFactorQAM7 0xf00000
774#define bSFactorQAM8 0xf000000
775#define bSFactorQAM9 0xf0000000
776#define bCSIScheme 0x100000
777
778#define bNoiseLvlTopSet 0x3
779#define bChSmooth 0x4
780#define bChSmoothCfg1 0x38
781#define bChSmoothCfg2 0x1c0
782#define bChSmoothCfg3 0xe00
783#define bChSmoothCfg4 0x7000
784#define bMRCMode 0x800000
785#define bTHEVMCfg 0x7000000
786
787#define bLoopFitType 0x1
788#define bUpdCFO 0x40
789#define bUpdCFOOffData 0x80
790#define bAdvUpdCFO 0x100
791#define bAdvTimeCtrl 0x800
792#define bUpdClko 0x1000
793#define bFC 0x6000
794#define bTrackingMode 0x8000
795#define bPhCmpEnable 0x10000
796#define bUpdClkoLTF 0x20000
797#define bComChCFO 0x40000
798#define bCSIEstiMode 0x80000
799#define bAdvUpdEqz 0x100000
800#define bUChCfg 0x7000000
801#define bUpdEqz 0x8000000
802
803/* Page e */
804#define bTxAGCRate18_06 0x7f7f7f7f
805#define bTxAGCRate54_24 0x7f7f7f7f
806#define bTxAGCRateMCS32 0x7f
807#define bTxAGCRateCCK 0x7f00
808#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f
809#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f
810#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f
811#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f
812
813
814/* Rx Pseduo noise */
815#define bRxPesudoNoiseOn 0x20000000
816#define bRxPesudoNoise_A 0xff
817#define bRxPesudoNoise_B 0xff00
818#define bRxPesudoNoise_C 0xff0000
819#define bRxPesudoNoise_D 0xff000000
820#define bPesudoNoiseState_A 0xffff
821#define bPesudoNoiseState_B 0xffff0000
822#define bPesudoNoiseState_C 0xffff
823#define bPesudoNoiseState_D 0xffff0000
824
825/* RF Zebra 1 */
826#define bZebra1_HSSIEnable 0x8
827#define bZebra1_TRxControl 0xc00
828#define bZebra1_TRxGainSetting 0x07f
829#define bZebra1_RxCorner 0xc00
830#define bZebra1_TxChargePump 0x38
831#define bZebra1_RxChargePump 0x7
832#define bZebra1_ChannelNum 0xf80
833#define bZebra1_TxLPFBW 0x400
834#define bZebra1_RxLPFBW 0x600
835
836/* Zebra4 */
837#define bRTL8256RegModeCtrl1 0x100
838#define bRTL8256RegModeCtrl0 0x40
839#define bRTL8256_TxLPFBW 0x18
840#define bRTL8256_RxLPFBW 0x600
841
842//RTL8258
843#define bRTL8258_TxLPFBW 0xc
844#define bRTL8258_RxLPFBW 0xc00
845#define bRTL8258_RSSILPFBW 0xc0
846
847/* byte endable for sb_write */
848#define bByte0 0x1
849#define bByte1 0x2
850#define bByte2 0x4
851#define bByte3 0x8
852#define bWord0 0x3
853#define bWord1 0xc
854#define bDWord 0xf
855
856/* for PutRegsetting & GetRegSetting BitMask */
857#define bMaskByte0 0xff
858#define bMaskByte1 0xff00
859#define bMaskByte2 0xff0000
860#define bMaskByte3 0xff000000
861#define bMaskHWord 0xffff0000
862#define bMaskLWord 0x0000ffff
863#define bMaskDWord 0xffffffff
864
865/* for PutRFRegsetting & GetRFRegSetting BitMask */
866#define bMask12Bits 0xfff
867
868#define bEnable 0x1
869#define bDisable 0x0
870
871#define LeftAntenna 0x0
872#define RightAntenna 0x1
873
874/* 500 ms */
875#define tCheckTxStatus 500
876/* 100 ms */
877#define tUpdateRxCounter 100
878
879#define rateCCK 0
880#define rateOFDM 1
881#define rateHT 2
882
883/* define Register-End */
884#define bPMAC_End 0x1ff
885#define bFPGAPHY0_End 0x8ff
886#define bFPGAPHY1_End 0x9ff
887#define bCCKPHY0_End 0xaff
888#define bOFDMPHY0_End 0xcff
889#define bOFDMPHY1_End 0xdff
890
891/*#define max debug item in each debug page
892#define bMaxItem_FPGA_PHY0 0x9
893#define bMaxItem_FPGA_PHY1 0x3
894#define bMaxItem_PHY_11B 0x16
895#define bMaxItem_OFDM_PHY0 0x29
896#define bMaxItem_OFDM_PHY1 0x0 */
897
898#define bPMACControl 0x0
899#define bWMACControl 0x1
900#define bWNICControl 0x2
901
902#define PathA 0x0
903#define PathB 0x1
904#define PathC 0x2
905#define PathD 0x3
906
907#define rRTL8256RxMixerPole 0xb
908#define bZebraRxMixerPole 0x6
909#define rRTL8256TxBBOPBias 0x9
910#define bRTL8256TxBBOPBias 0x400
911#define rRTL8256TxBBBW 19
912#define bRTL8256TxBBBW 0x18
913
914
915#endif /* __INC_HAL8190PCIPHYREG_H */