]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/rt2860/common/mlme.c
Staging: rt28x0: remove typedefs (part three)
[net-next-2.6.git] / drivers / staging / rt2860 / common / mlme.c
CommitLineData
91980990
GKH
1/*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
7 *
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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 as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 * *
25 *************************************************************************
26
27 Module Name:
28 mlme.c
29
30 Abstract:
31
32 Revision History:
33 Who When What
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-08-25 Modify from RT2500 code base
36 John Chang 2004-09-06 modified for RT2600
37*/
38
39#include "../rt_config.h"
40#include <stdarg.h>
41
51126deb
BZ
42u8 CISCO_OUI[] = { 0x00, 0x40, 0x96 };
43
44u8 WPA_OUI[] = { 0x00, 0x50, 0xf2, 0x01 };
45u8 RSN_OUI[] = { 0x00, 0x0f, 0xac };
46u8 WME_INFO_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01 };
47u8 WME_PARM_ELEM[] = { 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01 };
48u8 Ccx2QosInfo[] = { 0x00, 0x40, 0x96, 0x04 };
49u8 RALINK_OUI[] = { 0x00, 0x0c, 0x43 };
50u8 BROADCOM_OUI[] = { 0x00, 0x90, 0x4c };
51u8 WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 };
52u8 PRE_N_HT_OUI[] = { 0x00, 0x90, 0x4c };
53
54u8 RateSwitchTable[] = {
ec278fa2
BZ
55/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
56 0x11, 0x00, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
57 0x00, 0x00, 0, 40, 101,
58 0x01, 0x00, 1, 40, 50,
59 0x02, 0x00, 2, 35, 45,
60 0x03, 0x00, 3, 20, 45,
61 0x04, 0x21, 0, 30, 50,
62 0x05, 0x21, 1, 20, 50,
63 0x06, 0x21, 2, 20, 50,
64 0x07, 0x21, 3, 15, 50,
65 0x08, 0x21, 4, 15, 30,
66 0x09, 0x21, 5, 10, 25,
67 0x0a, 0x21, 6, 8, 25,
68 0x0b, 0x21, 7, 8, 25,
69 0x0c, 0x20, 12, 15, 30,
70 0x0d, 0x20, 13, 8, 20,
71 0x0e, 0x20, 14, 8, 20,
72 0x0f, 0x20, 15, 8, 25,
73 0x10, 0x22, 15, 8, 25,
74 0x11, 0x00, 0, 0, 0,
75 0x12, 0x00, 0, 0, 0,
76 0x13, 0x00, 0, 0, 0,
77 0x14, 0x00, 0, 0, 0,
78 0x15, 0x00, 0, 0, 0,
79 0x16, 0x00, 0, 0, 0,
80 0x17, 0x00, 0, 0, 0,
81 0x18, 0x00, 0, 0, 0,
82 0x19, 0x00, 0, 0, 0,
83 0x1a, 0x00, 0, 0, 0,
84 0x1b, 0x00, 0, 0, 0,
85 0x1c, 0x00, 0, 0, 0,
86 0x1d, 0x00, 0, 0, 0,
87 0x1e, 0x00, 0, 0, 0,
88 0x1f, 0x00, 0, 0, 0,
91980990
GKH
89};
90
51126deb 91u8 RateSwitchTable11B[] = {
ec278fa2
BZ
92/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
93 0x04, 0x03, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
94 0x00, 0x00, 0, 40, 101,
95 0x01, 0x00, 1, 40, 50,
96 0x02, 0x00, 2, 35, 45,
97 0x03, 0x00, 3, 20, 45,
91980990
GKH
98};
99
51126deb 100u8 RateSwitchTable11BG[] = {
ec278fa2
BZ
101/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
102 0x0a, 0x00, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
103 0x00, 0x00, 0, 40, 101,
104 0x01, 0x00, 1, 40, 50,
105 0x02, 0x00, 2, 35, 45,
106 0x03, 0x00, 3, 20, 45,
107 0x04, 0x10, 2, 20, 35,
108 0x05, 0x10, 3, 16, 35,
109 0x06, 0x10, 4, 10, 25,
110 0x07, 0x10, 5, 16, 25,
111 0x08, 0x10, 6, 10, 25,
112 0x09, 0x10, 7, 10, 13,
91980990
GKH
113};
114
51126deb 115u8 RateSwitchTable11G[] = {
ec278fa2
BZ
116/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
117 0x08, 0x00, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
118 0x00, 0x10, 0, 20, 101,
119 0x01, 0x10, 1, 20, 35,
120 0x02, 0x10, 2, 20, 35,
121 0x03, 0x10, 3, 16, 35,
122 0x04, 0x10, 4, 10, 25,
123 0x05, 0x10, 5, 16, 25,
124 0x06, 0x10, 6, 10, 25,
125 0x07, 0x10, 7, 10, 13,
91980990
GKH
126};
127
51126deb 128u8 RateSwitchTable11N1S[] = {
ec278fa2
BZ
129/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
130 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
131 0x00, 0x00, 0, 40, 101,
132 0x01, 0x00, 1, 40, 50,
133 0x02, 0x00, 2, 25, 45,
134 0x03, 0x21, 0, 20, 35,
135 0x04, 0x21, 1, 20, 35,
136 0x05, 0x21, 2, 20, 35,
137 0x06, 0x21, 3, 15, 35,
138 0x07, 0x21, 4, 15, 30,
139 0x08, 0x21, 5, 10, 25,
140 0x09, 0x21, 6, 8, 14,
141 0x0a, 0x21, 7, 8, 14,
142 0x0b, 0x23, 7, 8, 14,
91980990
GKH
143};
144
51126deb 145u8 RateSwitchTable11N2S[] = {
ec278fa2
BZ
146/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
147 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
148 0x00, 0x00, 0, 40, 101,
149 0x01, 0x00, 1, 40, 50,
150 0x02, 0x00, 2, 25, 45,
151 0x03, 0x21, 0, 20, 35,
152 0x04, 0x21, 1, 20, 35,
153 0x05, 0x21, 2, 20, 35,
154 0x06, 0x21, 3, 15, 35,
155 0x07, 0x21, 4, 15, 30,
156 0x08, 0x20, 11, 15, 30,
157 0x09, 0x20, 12, 15, 30,
158 0x0a, 0x20, 13, 8, 20,
159 0x0b, 0x20, 14, 8, 20,
160 0x0c, 0x20, 15, 8, 25,
161 0x0d, 0x22, 15, 8, 15,
91980990
GKH
162};
163
51126deb 164u8 RateSwitchTable11N3S[] = {
ec278fa2
BZ
165/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
166 0x0b, 0x00, 0, 0, 0, /* 0x0a, 0x00, 0, 0, 0, // Initial used item after association */
96b3c83d
BZ
167 0x00, 0x21, 0, 30, 101,
168 0x01, 0x21, 1, 20, 50,
169 0x02, 0x21, 2, 20, 50,
170 0x03, 0x21, 3, 15, 50,
171 0x04, 0x21, 4, 15, 30,
ec278fa2
BZ
172 0x05, 0x20, 11, 15, 30, /* Required by System-Alan @ 20080812 */
173 0x06, 0x20, 12, 15, 30, /* 0x05, 0x20, 12, 15, 30, */
174 0x07, 0x20, 13, 8, 20, /* 0x06, 0x20, 13, 8, 20, */
175 0x08, 0x20, 14, 8, 20, /* 0x07, 0x20, 14, 8, 20, */
176 0x09, 0x20, 15, 8, 25, /* 0x08, 0x20, 15, 8, 25, */
177 0x0a, 0x22, 15, 8, 25, /* 0x09, 0x22, 15, 8, 25, */
91980990
GKH
178};
179
51126deb 180u8 RateSwitchTable11N2SForABand[] = {
ec278fa2
BZ
181/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
182 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
183 0x00, 0x21, 0, 30, 101,
184 0x01, 0x21, 1, 20, 50,
185 0x02, 0x21, 2, 20, 50,
186 0x03, 0x21, 3, 15, 50,
187 0x04, 0x21, 4, 15, 30,
188 0x05, 0x21, 5, 15, 30,
189 0x06, 0x20, 12, 15, 30,
190 0x07, 0x20, 13, 8, 20,
191 0x08, 0x20, 14, 8, 20,
192 0x09, 0x20, 15, 8, 25,
193 0x0a, 0x22, 15, 8, 25,
91980990
GKH
194};
195
51126deb 196u8 RateSwitchTable11N3SForABand[] = { /* 3*3 */
ec278fa2
BZ
197/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
198 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
199 0x00, 0x21, 0, 30, 101,
200 0x01, 0x21, 1, 20, 50,
201 0x02, 0x21, 2, 20, 50,
202 0x03, 0x21, 3, 15, 50,
203 0x04, 0x21, 4, 15, 30,
204 0x05, 0x21, 5, 15, 30,
205 0x06, 0x20, 12, 15, 30,
206 0x07, 0x20, 13, 8, 20,
207 0x08, 0x20, 14, 8, 20,
208 0x09, 0x20, 15, 8, 25,
209 0x0a, 0x22, 15, 8, 25,
91980990
GKH
210};
211
51126deb 212u8 RateSwitchTable11BGN1S[] = {
ec278fa2
BZ
213/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
214 0x0c, 0x0a, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
215 0x00, 0x00, 0, 40, 101,
216 0x01, 0x00, 1, 40, 50,
217 0x02, 0x00, 2, 25, 45,
218 0x03, 0x21, 0, 20, 35,
219 0x04, 0x21, 1, 20, 35,
220 0x05, 0x21, 2, 20, 35,
221 0x06, 0x21, 3, 15, 35,
222 0x07, 0x21, 4, 15, 30,
223 0x08, 0x21, 5, 10, 25,
224 0x09, 0x21, 6, 8, 14,
225 0x0a, 0x21, 7, 8, 14,
226 0x0b, 0x23, 7, 8, 14,
91980990
GKH
227};
228
51126deb 229u8 RateSwitchTable11BGN2S[] = {
ec278fa2
BZ
230/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
231 0x0e, 0x0c, 0, 0, 0, /* Initial used item after association */
96b3c83d
BZ
232 0x00, 0x00, 0, 40, 101,
233 0x01, 0x00, 1, 40, 50,
234 0x02, 0x00, 2, 25, 45,
235 0x03, 0x21, 0, 20, 35,
236 0x04, 0x21, 1, 20, 35,
237 0x05, 0x21, 2, 20, 35,
238 0x06, 0x21, 3, 15, 35,
239 0x07, 0x21, 4, 15, 30,
240 0x08, 0x20, 11, 15, 30,
241 0x09, 0x20, 12, 15, 30,
242 0x0a, 0x20, 13, 8, 20,
243 0x0b, 0x20, 14, 8, 20,
244 0x0c, 0x20, 15, 8, 25,
245 0x0d, 0x22, 15, 8, 15,
91980990
GKH
246};
247
51126deb 248u8 RateSwitchTable11BGN3S[] = { /* 3*3 */
ec278fa2
BZ
249/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
250 0x0a, 0x00, 0, 0, 0, /* Initial used item after association */
251 0x00, 0x21, 0, 30, 101, /*50 */
96b3c83d
BZ
252 0x01, 0x21, 1, 20, 50,
253 0x02, 0x21, 2, 20, 50,
254 0x03, 0x21, 3, 20, 50,
255 0x04, 0x21, 4, 15, 50,
256 0x05, 0x20, 20, 15, 30,
257 0x06, 0x20, 21, 8, 20,
258 0x07, 0x20, 22, 8, 20,
259 0x08, 0x20, 23, 8, 25,
260 0x09, 0x22, 23, 8, 25,
91980990
GKH
261};
262
51126deb 263u8 RateSwitchTable11BGN2SForABand[] = {
ec278fa2
BZ
264/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
265 0x0b, 0x09, 0, 0, 0, /* Initial used item after association */
266 0x00, 0x21, 0, 30, 101, /*50 */
96b3c83d
BZ
267 0x01, 0x21, 1, 20, 50,
268 0x02, 0x21, 2, 20, 50,
269 0x03, 0x21, 3, 15, 50,
270 0x04, 0x21, 4, 15, 30,
271 0x05, 0x21, 5, 15, 30,
272 0x06, 0x20, 12, 15, 30,
273 0x07, 0x20, 13, 8, 20,
274 0x08, 0x20, 14, 8, 20,
275 0x09, 0x20, 15, 8, 25,
276 0x0a, 0x22, 15, 8, 25,
91980990
GKH
277};
278
51126deb 279u8 RateSwitchTable11BGN3SForABand[] = { /* 3*3 */
ec278fa2
BZ
280/* Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF) */
281 0x0c, 0x09, 0, 0, 0, /* Initial used item after association */
282 0x00, 0x21, 0, 30, 101, /*50 */
96b3c83d
BZ
283 0x01, 0x21, 1, 20, 50,
284 0x02, 0x21, 2, 20, 50,
285 0x03, 0x21, 3, 15, 50,
286 0x04, 0x21, 4, 15, 30,
287 0x05, 0x21, 5, 15, 30,
288 0x06, 0x21, 12, 15, 30,
289 0x07, 0x20, 20, 15, 30,
290 0x08, 0x20, 21, 8, 20,
291 0x09, 0x20, 22, 8, 20,
292 0x0a, 0x20, 23, 8, 25,
293 0x0b, 0x22, 23, 8, 25,
91980990 294};
91980990 295
51126deb 296extern u8 OfdmRateToRxwiMCS[];
ec278fa2
BZ
297/* since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate. */
298/* otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate */
51126deb 299unsigned long BasicRateMask[12] =
96b3c83d
BZ
300 { 0xfffff001 /* 1-Mbps */ , 0xfffff003 /* 2 Mbps */ , 0xfffff007 /* 5.5 */ ,
3010xfffff00f /* 11 */ ,
302 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ ,
303 0xfffff0ff /* 18 */ ,
304 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ ,
305 0xffffffff /* 54 */
306};
91980990 307
51126deb
BZ
308u8 BROADCAST_ADDR[MAC_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
309u8 ZERO_MAC_ADDR[MAC_ADDR_LEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
91980990 310
ec278fa2
BZ
311/* e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than */
312/* this value, then it's quaranteed capable of operating in 36 mbps TX rate in */
313/* clean environment. */
314/* TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100 */
51126deb 315char RssiSafeLevelForTxRate[] =
96b3c83d
BZ
316 { -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
317
51126deb
BZ
318u8 RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100 };
319u16 RateIdTo500Kbps[] =
96b3c83d
BZ
320 { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200 };
321
51126deb
BZ
322u8 SsidIe = IE_SSID;
323u8 SupRateIe = IE_SUPP_RATES;
324u8 ExtRateIe = IE_EXT_SUPP_RATES;
325u8 HtCapIe = IE_HT_CAP;
326u8 AddHtInfoIe = IE_ADD_HT;
327u8 NewExtChanIe = IE_SECONDARY_CH_OFFSET;
328u8 ErpIe = IE_ERP;
329u8 DsIe = IE_DS_PARM;
330u8 TimIe = IE_TIM;
331u8 WpaIe = IE_WPA;
332u8 Wpa2Ie = IE_WPA2;
333u8 IbssIe = IE_IBSS_PARM;
96b3c83d 334
51126deb 335extern u8 WPA_OUI[];
96b3c83d 336
51126deb 337u8 SES_OUI[] = { 0x00, 0x90, 0x4c };
96b3c83d 338
51126deb 339u8 ZeroSsid[32] =
96b3c83d
BZ
340 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3410x00, 0x00, 0x00, 0x00,
342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343 0x00, 0x00, 0x00, 0x00
344};
91980990
GKH
345
346/*
347 ==========================================================================
348 Description:
349 initialize the MLME task and its data structure (queue, spinlock,
350 timer, state machines).
351
352 IRQL = PASSIVE_LEVEL
353
354 Return:
355 always return NDIS_STATUS_SUCCESS
356
357 ==========================================================================
358*/
62eb734b 359int MlmeInit(struct rt_rtmp_adapter *pAd)
91980990 360{
51126deb 361 int Status = NDIS_STATUS_SUCCESS;
91980990
GKH
362
363 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
364
96b3c83d 365 do {
91980990 366 Status = MlmeQueueInit(&pAd->Mlme.Queue);
96b3c83d 367 if (Status != NDIS_STATUS_SUCCESS)
91980990
GKH
368 break;
369
370 pAd->Mlme.bRunning = FALSE;
371 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
372
91980990
GKH
373 {
374 BssTableInit(&pAd->ScanTab);
375
ec278fa2 376 /* init STA state machines */
96b3c83d
BZ
377 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine,
378 pAd->Mlme.AssocFunc);
379 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine,
380 pAd->Mlme.AuthFunc);
381 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine,
382 pAd->Mlme.AuthRspFunc);
383 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine,
384 pAd->Mlme.SyncFunc);
91980990 385
ec278fa2
BZ
386 /* Since we are using switch/case to implement it, the init is different from the above */
387 /* state machine init */
91980990
GKH
388 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
389 }
91980990 390
96b3c83d
BZ
391 WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine,
392 pAd->Mlme.WpaFunc);
ca97b838 393
96b3c83d
BZ
394 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine,
395 pAd->Mlme.ActFunc);
91980990 396
ec278fa2 397 /* Init mlme periodic timer */
96b3c83d
BZ
398 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer,
399 GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
91980990 400
ec278fa2 401 /* Set mlme periodic timer */
91980990
GKH
402 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
403
ec278fa2 404 /* software-based RX Antenna diversity */
96b3c83d
BZ
405 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer,
406 GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd,
407 FALSE);
91980990 408
91980990 409 {
ca97b838 410#ifdef RTMP_PCI_SUPPORT
96b3c83d 411 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
ec278fa2 412 /* only PCIe cards need these two timers */
96b3c83d
BZ
413 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer,
414 GET_TIMER_FUNCTION
415 (PsPollWakeExec), pAd, FALSE);
416 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer,
417 GET_TIMER_FUNCTION(RadioOnExec),
418 pAd, FALSE);
419 }
ec278fa2 420#endif /* RTMP_PCI_SUPPORT // */
ca97b838 421
96b3c83d
BZ
422 RTMPInitTimer(pAd, &pAd->Mlme.LinkDownTimer,
423 GET_TIMER_FUNCTION(LinkDownExec), pAd,
424 FALSE);
ca97b838
BZ
425
426#ifdef RTMP_MAC_USB
96b3c83d
BZ
427 RTMPInitTimer(pAd, &pAd->Mlme.AutoWakeupTimer,
428 GET_TIMER_FUNCTION
429 (RtmpUsbStaAsicForceWakeupTimeout), pAd,
430 FALSE);
ca97b838 431 pAd->Mlme.AutoWakeupTimerRunning = FALSE;
ec278fa2 432#endif /* RTMP_MAC_USB // */
91980990 433 }
ca97b838 434
91980990
GKH
435 } while (FALSE);
436
437 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
438
439 return Status;
440}
441
442/*
443 ==========================================================================
444 Description:
445 main loop of the MLME
446 Pre:
447 Mlme has to be initialized, and there are something inside the queue
448 Note:
449 This function is invoked from MPSetInformation and MPReceive;
450 This task guarantee only one MlmeHandler will run.
451
452 IRQL = DISPATCH_LEVEL
453
454 ==========================================================================
455 */
62eb734b 456void MlmeHandler(struct rt_rtmp_adapter *pAd)
91980990 457{
62eb734b 458 struct rt_mlme_queue_elem *Elem = NULL;
91980990 459
ec278fa2
BZ
460 /* Only accept MLME and Frame from peer side, no other (control/data) frame should */
461 /* get into this state machine */
91980990
GKH
462
463 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
96b3c83d 464 if (pAd->Mlme.bRunning) {
91980990
GKH
465 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
466 return;
96b3c83d 467 } else {
91980990
GKH
468 pAd->Mlme.bRunning = TRUE;
469 }
470 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
471
96b3c83d 472 while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
91980990 473 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
96b3c83d
BZ
474 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
475 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
476 DBGPRINT(RT_DEBUG_TRACE,
477 ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n",
478 pAd->Mlme.Queue.Num));
91980990
GKH
479 break;
480 }
ec278fa2 481 /*From message type, determine which state machine I should drive */
96b3c83d 482 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
ca97b838 483#ifdef RTMP_MAC_USB
96b3c83d
BZ
484 if (Elem->MsgType == MT2_RESET_CONF) {
485 DBGPRINT_RAW(RT_DEBUG_TRACE,
486 ("!!! reset MLME state machine !!!\n"));
59fe2d89
BZ
487 MlmeRestartStateMachine(pAd);
488 Elem->Occupied = FALSE;
489 Elem->MsgLen = 0;
490 continue;
491 }
ec278fa2 492#endif /* RTMP_MAC_USB // */
91980990 493
ec278fa2 494 /* if dequeue success */
96b3c83d 495 switch (Elem->Machine) {
ec278fa2 496 /* STA state machines */
96b3c83d
BZ
497 case ASSOC_STATE_MACHINE:
498 StateMachinePerformAction(pAd,
499 &pAd->Mlme.
500 AssocMachine, Elem);
501 break;
502 case AUTH_STATE_MACHINE:
503 StateMachinePerformAction(pAd,
504 &pAd->Mlme.
505 AuthMachine, Elem);
506 break;
507 case AUTH_RSP_STATE_MACHINE:
508 StateMachinePerformAction(pAd,
509 &pAd->Mlme.
510 AuthRspMachine, Elem);
511 break;
512 case SYNC_STATE_MACHINE:
513 StateMachinePerformAction(pAd,
514 &pAd->Mlme.
515 SyncMachine, Elem);
516 break;
517 case MLME_CNTL_STATE_MACHINE:
518 MlmeCntlMachinePerformAction(pAd,
519 &pAd->Mlme.
520 CntlMachine, Elem);
521 break;
522 case WPA_PSK_STATE_MACHINE:
523 StateMachinePerformAction(pAd,
524 &pAd->Mlme.
525 WpaPskMachine, Elem);
526 break;
91980990 527
96b3c83d
BZ
528 case ACTION_STATE_MACHINE:
529 StateMachinePerformAction(pAd,
530 &pAd->Mlme.ActMachine,
531 Elem);
532 break;
91980990 533
96b3c83d
BZ
534 case WPA_STATE_MACHINE:
535 StateMachinePerformAction(pAd,
536 &pAd->Mlme.WpaMachine,
537 Elem);
538 break;
91980990 539
96b3c83d
BZ
540 default:
541 DBGPRINT(RT_DEBUG_TRACE,
542 ("ERROR: Illegal machine %ld in MlmeHandler()\n",
543 Elem->Machine));
544 break;
ec278fa2 545 } /* end of switch */
91980990 546
ec278fa2 547 /* free MLME element */
91980990
GKH
548 Elem->Occupied = FALSE;
549 Elem->MsgLen = 0;
550
96b3c83d 551 } else {
91980990
GKH
552 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
553 }
554 }
555
556 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
557 pAd->Mlme.bRunning = FALSE;
558 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
559}
560
561/*
562 ==========================================================================
563 Description:
564 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
565 Parameters:
566 Adapter - NIC Adapter pointer
567 Post:
568 The MLME task will no longer work properly
569
570 IRQL = PASSIVE_LEVEL
571
572 ==========================================================================
573 */
62eb734b 574void MlmeHalt(struct rt_rtmp_adapter *pAd)
91980990 575{
96b3c83d 576 BOOLEAN Cancelled;
91980990
GKH
577
578 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
579
96b3c83d 580 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
ec278fa2 581 /* disable BEACON generation and other BEACON related hardware timers */
91980990
GKH
582 AsicDisableSync(pAd);
583 }
584
91980990 585 {
ec278fa2 586 /* Cancel pending timers */
96b3c83d
BZ
587 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
588 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
589 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
590 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
591 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
592 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
ca97b838
BZ
593
594#ifdef RTMP_MAC_PCI
96b3c83d
BZ
595 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)
596 && (pAd->StaCfg.PSControl.field.EnableNewPS == TRUE)) {
597 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
598 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
91980990 599 }
ec278fa2 600#endif /* RTMP_MAC_PCI // */
ca97b838 601
96b3c83d 602 RTMPCancelTimer(&pAd->Mlme.LinkDownTimer, &Cancelled);
ca97b838
BZ
603
604#ifdef RTMP_MAC_USB
605 RTMPCancelTimer(&pAd->Mlme.AutoWakeupTimer, &Cancelled);
ec278fa2 606#endif /* RTMP_MAC_USB // */
91980990 607 }
91980990 608
96b3c83d
BZ
609 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
610 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
91980990 611
96b3c83d 612 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) {
62eb734b 613 struct rt_rtmp_chip_op *pChipOps = &pAd->chipOps;
ca97b838 614
ec278fa2 615 /* Set LED */
91980990 616 RTMPSetLED(pAd, LED_HALT);
ec278fa2 617 RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it. */
ca97b838 618#ifdef RTMP_MAC_USB
96b3c83d
BZ
619 {
620 LED_CFG_STRUC LedCfg;
621 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
622 LedCfg.field.LedPolar = 0;
623 LedCfg.field.RLedMode = 0;
624 LedCfg.field.GLedMode = 0;
625 LedCfg.field.YLedMode = 0;
626 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
627 }
ec278fa2 628#endif /* RTMP_MAC_USB // */
ca97b838
BZ
629
630 if (pChipOps->AsicHaltAction)
631 pChipOps->AsicHaltAction(pAd);
91980990
GKH
632 }
633
ec278fa2 634 RTMPusecDelay(5000); /* 5 msec to gurantee Ant Diversity timer canceled */
91980990
GKH
635
636 MlmeQueueDestroy(&pAd->Mlme.Queue);
637 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
638
639 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
640}
641
62eb734b 642void MlmeResetRalinkCounters(struct rt_rtmp_adapter *pAd)
91980990 643{
96b3c83d
BZ
644 pAd->RalinkCounters.LastOneSecRxOkDataCnt =
645 pAd->RalinkCounters.OneSecRxOkDataCnt;
ec278fa2 646 /* clear all OneSecxxx counters. */
91980990
GKH
647 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
648 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
649 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
650 pAd->RalinkCounters.OneSecRxOkCnt = 0;
651 pAd->RalinkCounters.OneSecTxFailCount = 0;
652 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
653 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
654 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
ca97b838
BZ
655 pAd->RalinkCounters.OneSecReceivedByteCount = 0;
656 pAd->RalinkCounters.OneSecTransmittedByteCount = 0;
91980990 657
ec278fa2 658 /* TODO: for debug only. to be removed */
91980990
GKH
659 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
660 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
661 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
662 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
663 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
664 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
665 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
666 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
667 pAd->RalinkCounters.OneSecTxDoneCount = 0;
668 pAd->RalinkCounters.OneSecRxCount = 0;
669 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
670 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
671
672 return;
673}
674
91980990
GKH
675/*
676 ==========================================================================
677 Description:
678 This routine is executed periodically to -
679 1. Decide if it's a right time to turn on PwrMgmt bit of all
680 outgoiing frames
681 2. Calculate ChannelQuality based on statistics of the last
682 period, so that TX rate won't toggling very frequently between a
683 successful TX and a failed TX.
684 3. If the calculated ChannelQuality indicated current connection not
685 healthy, then a ROAMing attempt is tried here.
686
687 IRQL = DISPATCH_LEVEL
688
689 ==========================================================================
690 */
ec278fa2 691#define ADHOC_BEACON_LOST_TIME (8*OS_HZ) /* 8 sec */
51126deb
BZ
692void MlmePeriodicExec(void *SystemSpecific1,
693 void *FunctionContext,
694 void *SystemSpecific2, void *SystemSpecific3)
91980990 695{
51126deb 696 unsigned long TxTotalCnt;
62eb734b 697 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
91980990 698
ca97b838 699#ifdef RTMP_MAC_PCI
91980990 700 {
ec278fa2
BZ
701 /* If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second. */
702 /* Move code to here, because following code will return when radio is off */
96b3c83d
BZ
703 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) ==
704 0) && (pAd->StaCfg.bHardwareRadio == TRUE)
705 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
706 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))
707 /*&&(pAd->bPCIclkOff == FALSE) */
708 ) {
51126deb 709 u32 data = 0;
91980990 710
ec278fa2 711 /* Read GPIO pin2 as Hardware controlled radio state */
e44fd1cf 712#ifndef RT3090
ca97b838 713 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
ec278fa2
BZ
714#endif /* RT3090 // */
715/*KH(PCIE PS):Added based on Jane<-- */
e44fd1cf 716#ifdef RT3090
ec278fa2
BZ
717/* Read GPIO pin2 as Hardware controlled radio state */
718/* We need to Read GPIO if HW said so no mater what advance power saving */
96b3c83d
BZ
719 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
720 &&
721 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))
722 && (pAd->StaCfg.PSControl.field.EnablePSinIdle ==
723 TRUE)) {
ec278fa2 724 /* Want to make sure device goes to L0 state before reading register. */
96b3c83d
BZ
725 RTMPPCIeLinkCtrlValueRestore(pAd, 0);
726 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
727 RTMPPCIeLinkCtrlSetting(pAd, 3);
728 } else
729 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
ec278fa2
BZ
730#endif /* RT3090 // */
731/*KH(PCIE PS):Added based on Jane--> */
e44fd1cf 732
96b3c83d 733 if (data & 0x04) {
91980990 734 pAd->StaCfg.bHwRadio = TRUE;
96b3c83d 735 } else {
91980990
GKH
736 pAd->StaCfg.bHwRadio = FALSE;
737 }
96b3c83d
BZ
738 if (pAd->StaCfg.bRadio !=
739 (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio)) {
740 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio
741 && pAd->StaCfg.bSwRadio);
742 if (pAd->StaCfg.bRadio == TRUE) {
91980990 743 MlmeRadioOn(pAd);
ec278fa2 744 /* Update extra information */
91980990 745 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
96b3c83d 746 } else {
91980990 747 MlmeRadioOff(pAd);
ec278fa2 748 /* Update extra information */
91980990
GKH
749 pAd->ExtraInfo = HW_RADIO_OFF;
750 }
751 }
752 }
753 }
ec278fa2 754#endif /* RTMP_MAC_PCI // */
91980990 755
ec278fa2
BZ
756 /* Do nothing if the driver is starting halt state. */
757 /* This might happen when timer already been fired before cancel timer with mlmehalt */
91980990 758 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
96b3c83d
BZ
759 fRTMP_ADAPTER_RADIO_OFF |
760 fRTMP_ADAPTER_RADIO_MEASUREMENT |
761 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
91980990
GKH
762 return;
763
ca97b838 764 RTMP_MLME_PRE_SANITY_CHECK(pAd);
91980990 765
91980990 766 {
ec278fa2 767 /* Do nothing if monitor mode is on */
91980990
GKH
768 if (MONITOR_ON(pAd))
769 return;
770
96b3c83d 771 if (pAd->Mlme.PeriodicRound & 0x1) {
ec278fa2 772 /* This is the fix for wifi 11n extension channel overlapping test case. for 2860D */
91980990 773 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
96b3c83d
BZ
774 (STA_TGN_WIFI_ON(pAd)) &&
775 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
776 {
777 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
778 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
779 } else if ((STA_TGN_WIFI_ON(pAd)) &&
780 ((pAd->MACVersion & 0xffff) == 0x0101)) {
781 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
782 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
783 }
91980990
GKH
784 }
785 }
91980990
GKH
786
787 pAd->bUpdateBcnCntDone = FALSE;
788
ec278fa2 789/* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3); */
96b3c83d 790 pAd->Mlme.PeriodicRound++;
91980990 791
ca97b838 792#ifdef RTMP_MAC_USB
ec278fa2 793 /* execute every 100ms, update the Tx FIFO Cnt for update Tx Rate. */
59fe2d89 794 NICUpdateFifoStaCounters(pAd);
ec278fa2 795#endif /* RTMP_MAC_USB // */
ca97b838 796
ec278fa2 797 /* execute every 500ms */
96b3c83d
BZ
798 if ((pAd->Mlme.PeriodicRound % 5 == 0)
799 && RTMPAutoRateSwitchCheck(pAd)
800 /*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)) */ )
91980990 801 {
ec278fa2 802 /* perform dynamic tx rate switching based on past TX history */
91980990 803 {
96b3c83d
BZ
804 if ((OPSTATUS_TEST_FLAG
805 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
806 )
807 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
91980990
GKH
808 MlmeDynamicTxRateSwitching(pAd);
809 }
91980990 810 }
ec278fa2 811 /* Normal 1 second Mlme PeriodicExec. */
96b3c83d
BZ
812 if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) {
813 pAd->Mlme.OneSecPeriodicRound++;
ca97b838 814
ec278fa2 815 /*ORIBATimerTimeout(pAd); */
91980990 816
ec278fa2 817 /* Media status changed, report to NDIS */
96b3c83d 818 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE)) {
91980990 819 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
96b3c83d
BZ
820 if (OPSTATUS_TEST_FLAG
821 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
822 pAd->IndicateMediaState =
823 NdisMediaStateConnected;
91980990
GKH
824 RTMP_IndicateMediaState(pAd);
825
96b3c83d
BZ
826 } else {
827 pAd->IndicateMediaState =
828 NdisMediaStateDisconnected;
91980990
GKH
829 RTMP_IndicateMediaState(pAd);
830 }
831 }
832
833 NdisGetSystemUpTime(&pAd->Mlme.Now32);
834
ec278fa2
BZ
835 /* add the most up-to-date h/w raw counters into software variable, so that */
836 /* the dynamic tuning mechanism below are based on most up-to-date information */
91980990
GKH
837 NICUpdateRawCounters(pAd);
838
ca97b838
BZ
839#ifdef RTMP_MAC_USB
840 RTUSBWatchDog(pAd);
ec278fa2 841#endif /* RTMP_MAC_USB // */
59fe2d89 842
ec278fa2 843 /* Need statistics after read counter. So put after NICUpdateRawCounters */
91980990 844 ORIBATimerTimeout(pAd);
91980990 845
ec278fa2
BZ
846 /* if MGMT RING is full more than twice within 1 second, we consider there's */
847 /* a hardware problem stucking the TX path. In this case, try a hardware reset */
848 /* to recover the system */
849 /* if (pAd->RalinkCounters.MgmtRingFullCount >= 2) */
850 /* RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR); */
851 /* else */
852 /* pAd->RalinkCounters.MgmtRingFullCount = 0; */
ca97b838 853
ec278fa2 854 /* The time period for checking antenna is according to traffic */
ca97b838 855 {
96b3c83d
BZ
856 if (pAd->Mlme.bEnableAutoAntennaCheck) {
857 TxTotalCnt =
858 pAd->RalinkCounters.OneSecTxNoRetryOkCount +
859 pAd->RalinkCounters.OneSecTxRetryOkCount +
860 pAd->RalinkCounters.OneSecTxFailCount;
861
ec278fa2 862 /* dynamic adjust antenna evaluation period according to the traffic */
96b3c83d
BZ
863 if (TxTotalCnt > 50) {
864 if (pAd->Mlme.OneSecPeriodicRound %
865 10 == 0) {
866 AsicEvaluateRxAnt(pAd);
867 }
868 } else {
869 if (pAd->Mlme.OneSecPeriodicRound % 3 ==
870 0) {
871 AsicEvaluateRxAnt(pAd);
872 }
91980990
GKH
873 }
874 }
875 }
876
5a911fd6 877 STAMlmePeriodicExec(pAd);
91980990
GKH
878
879 MlmeResetRalinkCounters(pAd);
880
91980990 881 {
ca97b838 882#ifdef RTMP_MAC_PCI
96b3c83d
BZ
883 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)
884 && (pAd->bPCIclkOff == FALSE))
ec278fa2 885#endif /* RTMP_MAC_PCI // */
91980990 886 {
ec278fa2
BZ
887 /* When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock */
888 /* and sending CTS-to-self over and over. */
889 /* Software Patch Solution: */
890 /* 1. Polling debug state register 0x10F4 every one second. */
891 /* 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred. */
892 /* 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again. */
91980990 893
51126deb 894 u32 MacReg = 0;
91980990
GKH
895
896 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
96b3c83d
BZ
897 if (((MacReg & 0x20000000) && (MacReg & 0x80))
898 || ((MacReg & 0x20000000)
899 && (MacReg & 0x20))) {
91980990
GKH
900 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
901 RTMPusecDelay(1);
902 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
903
96b3c83d
BZ
904 DBGPRINT(RT_DEBUG_WARN,
905 ("Warning, MAC specific condition occurs \n"));
91980990
GKH
906 }
907 }
908 }
91980990 909
ca97b838 910 RTMP_MLME_HANDLER(pAd);
91980990
GKH
911 }
912
91980990
GKH
913 pAd->bUpdateBcnCntDone = FALSE;
914}
915
ca97b838
BZ
916/*
917 ==========================================================================
918 Validate SSID for connection try and rescan purpose
919 Valid SSID will have visible chars only.
920 The valid length is from 0 to 32.
921 IRQL = DISPATCH_LEVEL
922 ==========================================================================
923 */
51126deb 924BOOLEAN MlmeValidateSSID(u8 *pSsid, u8 SsidLen)
91980990 925{
96b3c83d 926 int index;
91980990 927
ca97b838
BZ
928 if (SsidLen > MAX_LEN_OF_SSID)
929 return (FALSE);
930
ec278fa2 931 /* Check each character value */
96b3c83d 932 for (index = 0; index < SsidLen; index++) {
ca97b838
BZ
933 if (pSsid[index] < 0x20)
934 return (FALSE);
96b3c83d 935 }
91980990 936
ec278fa2 937 /* All checked */
ca97b838
BZ
938 return (TRUE);
939}
940
62eb734b
BZ
941void MlmeSelectTxRateTable(struct rt_rtmp_adapter *pAd,
942 struct rt_mac_table_entry *pEntry,
51126deb
BZ
943 u8 ** ppTable,
944 u8 *pTableSize, u8 *pInitTxRateIdx)
ca97b838 945{
96b3c83d 946 do {
ec278fa2 947 /* decide the rate table for tuning */
96b3c83d 948 if (pAd->CommonCfg.TxRateTableSize > 0) {
ca97b838
BZ
949 *ppTable = RateSwitchTable;
950 *pTableSize = RateSwitchTable[0];
951 *pInitTxRateIdx = RateSwitchTable[1];
952
953 break;
96b3c83d 954 }
ed291e80 955
96b3c83d 956 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd)) {
ec278fa2 957 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) { /* 11N 1S Adhoc */
ca97b838
BZ
958 *ppTable = RateSwitchTable11N1S;
959 *pTableSize = RateSwitchTable11N1S[0];
960 *pInitTxRateIdx = RateSwitchTable11N1S[1];
961
ec278fa2 962 } else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) { /* 11N 2S Adhoc */
96b3c83d 963 if (pAd->LatchRfRegs.Channel <= 14) {
ca97b838
BZ
964 *ppTable = RateSwitchTable11N2S;
965 *pTableSize = RateSwitchTable11N2S[0];
96b3c83d
BZ
966 *pInitTxRateIdx =
967 RateSwitchTable11N2S[1];
968 } else {
ca97b838 969 *ppTable = RateSwitchTable11N2SForABand;
96b3c83d
BZ
970 *pTableSize =
971 RateSwitchTable11N2SForABand[0];
972 *pInitTxRateIdx =
973 RateSwitchTable11N2SForABand[1];
974 }
91980990 975
96b3c83d
BZ
976 } else if ((pEntry->RateLen == 4)
977 && (pEntry->HTCapability.MCSSet[0] == 0)
978 && (pEntry->HTCapability.MCSSet[1] == 0)
979 ) {
ca97b838
BZ
980 *ppTable = RateSwitchTable11B;
981 *pTableSize = RateSwitchTable11B[0];
982 *pInitTxRateIdx = RateSwitchTable11B[1];
91980990 983
96b3c83d 984 } else if (pAd->LatchRfRegs.Channel <= 14) {
ca97b838
BZ
985 *ppTable = RateSwitchTable11BG;
986 *pTableSize = RateSwitchTable11BG[0];
987 *pInitTxRateIdx = RateSwitchTable11BG[1];
91980990 988
96b3c83d 989 } else {
ca97b838
BZ
990 *ppTable = RateSwitchTable11G;
991 *pTableSize = RateSwitchTable11G[0];
992 *pInitTxRateIdx = RateSwitchTable11G[1];
91980990 993
ca97b838
BZ
994 }
995 break;
996 }
ec278fa2
BZ
997 /*if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
998 /* ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
999 if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) { /* 11BGN 1S AP */
ca97b838
BZ
1000 *ppTable = RateSwitchTable11BGN1S;
1001 *pTableSize = RateSwitchTable11BGN1S[0];
1002 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
91980990 1003
ca97b838 1004 break;
96b3c83d 1005 }
ec278fa2
BZ
1006 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && */
1007 /* (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1008 if (((pEntry->RateLen == 12) || (pAd->OpMode == OPMODE_STA)) && (pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) { /* 11BGN 2S AP */
96b3c83d 1009 if (pAd->LatchRfRegs.Channel <= 14) {
ca97b838
BZ
1010 *ppTable = RateSwitchTable11BGN2S;
1011 *pTableSize = RateSwitchTable11BGN2S[0];
1012 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
91980990 1013
96b3c83d 1014 } else {
ca97b838
BZ
1015 *ppTable = RateSwitchTable11BGN2SForABand;
1016 *pTableSize = RateSwitchTable11BGN2SForABand[0];
96b3c83d
BZ
1017 *pInitTxRateIdx =
1018 RateSwitchTable11BGN2SForABand[1];
91980990 1019
ca97b838
BZ
1020 }
1021 break;
91980990 1022 }
ec278fa2
BZ
1023 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) */
1024 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1))) { /* 11N 1S AP */
ca97b838
BZ
1025 *ppTable = RateSwitchTable11N1S;
1026 *pTableSize = RateSwitchTable11N1S[0];
1027 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1028
1029 break;
1030 }
ec278fa2
BZ
1031 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) */
1032 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2)) { /* 11N 2S AP */
96b3c83d
BZ
1033 if (pAd->LatchRfRegs.Channel <= 14) {
1034 *ppTable = RateSwitchTable11N2S;
1035 *pTableSize = RateSwitchTable11N2S[0];
1036 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1037 } else {
ca97b838
BZ
1038 *ppTable = RateSwitchTable11N2SForABand;
1039 *pTableSize = RateSwitchTable11N2SForABand[0];
96b3c83d
BZ
1040 *pInitTxRateIdx =
1041 RateSwitchTable11N2SForABand[1];
ca97b838
BZ
1042 }
1043
1044 break;
1045 }
ec278fa2 1046 /*else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
96b3c83d 1047 if ((pEntry->RateLen == 4 || pAd->CommonCfg.PhyMode == PHY_11B)
ec278fa2 1048 /*Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode */
96b3c83d 1049 /* && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0) */
ec278fa2 1050 ) { /* B only AP */
ca97b838
BZ
1051 *ppTable = RateSwitchTable11B;
1052 *pTableSize = RateSwitchTable11B[0];
1053 *pInitTxRateIdx = RateSwitchTable11B[1];
1054
1055 break;
1056 }
ec278fa2 1057 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
ca97b838 1058 if ((pEntry->RateLen > 8)
96b3c83d
BZ
1059 && (pEntry->HTCapability.MCSSet[0] == 0)
1060 && (pEntry->HTCapability.MCSSet[1] == 0)
ec278fa2 1061 ) { /* B/G mixed AP */
ca97b838
BZ
1062 *ppTable = RateSwitchTable11BG;
1063 *pTableSize = RateSwitchTable11BG[0];
1064 *pInitTxRateIdx = RateSwitchTable11BG[1];
1065
1066 break;
1067 }
ec278fa2 1068 /*else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
ca97b838 1069 if ((pEntry->RateLen == 8)
96b3c83d
BZ
1070 && (pEntry->HTCapability.MCSSet[0] == 0)
1071 && (pEntry->HTCapability.MCSSet[1] == 0)
ec278fa2 1072 ) { /* G only AP */
ca97b838
BZ
1073 *ppTable = RateSwitchTable11G;
1074 *pTableSize = RateSwitchTable11G[0];
1075 *pInitTxRateIdx = RateSwitchTable11G[1];
1076
1077 break;
1078 }
1079
1080 {
ec278fa2
BZ
1081 /*else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0)) */
1082 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)) { /* Legacy mode */
96b3c83d 1083 if (pAd->CommonCfg.MaxTxRate <= RATE_11) {
ca97b838
BZ
1084 *ppTable = RateSwitchTable11B;
1085 *pTableSize = RateSwitchTable11B[0];
1086 *pInitTxRateIdx = RateSwitchTable11B[1];
96b3c83d
BZ
1087 } else if ((pAd->CommonCfg.MaxTxRate > RATE_11)
1088 && (pAd->CommonCfg.MinTxRate >
1089 RATE_11)) {
ca97b838
BZ
1090 *ppTable = RateSwitchTable11G;
1091 *pTableSize = RateSwitchTable11G[0];
1092 *pInitTxRateIdx = RateSwitchTable11G[1];
1093
96b3c83d 1094 } else {
ca97b838
BZ
1095 *ppTable = RateSwitchTable11BG;
1096 *pTableSize = RateSwitchTable11BG[0];
96b3c83d
BZ
1097 *pInitTxRateIdx =
1098 RateSwitchTable11BG[1];
ca97b838
BZ
1099 }
1100 break;
1101 }
96b3c83d
BZ
1102 if (pAd->LatchRfRegs.Channel <= 14) {
1103 if (pAd->CommonCfg.TxStream == 1) {
ca97b838
BZ
1104 *ppTable = RateSwitchTable11N1S;
1105 *pTableSize = RateSwitchTable11N1S[0];
96b3c83d
BZ
1106 *pInitTxRateIdx =
1107 RateSwitchTable11N1S[1];
1108 DBGPRINT_RAW(RT_DEBUG_ERROR,
1109 ("DRS: unkown mode,default use 11N 1S AP \n"));
1110 } else {
ca97b838
BZ
1111 *ppTable = RateSwitchTable11N2S;
1112 *pTableSize = RateSwitchTable11N2S[0];
96b3c83d
BZ
1113 *pInitTxRateIdx =
1114 RateSwitchTable11N2S[1];
1115 DBGPRINT_RAW(RT_DEBUG_ERROR,
1116 ("DRS: unkown mode,default use 11N 2S AP \n"));
ca97b838 1117 }
96b3c83d
BZ
1118 } else {
1119 if (pAd->CommonCfg.TxStream == 1) {
ca97b838
BZ
1120 *ppTable = RateSwitchTable11N1S;
1121 *pTableSize = RateSwitchTable11N1S[0];
96b3c83d
BZ
1122 *pInitTxRateIdx =
1123 RateSwitchTable11N1S[1];
1124 DBGPRINT_RAW(RT_DEBUG_ERROR,
1125 ("DRS: unkown mode,default use 11N 1S AP \n"));
1126 } else {
ca97b838 1127 *ppTable = RateSwitchTable11N2SForABand;
96b3c83d
BZ
1128 *pTableSize =
1129 RateSwitchTable11N2SForABand[0];
1130 *pInitTxRateIdx =
1131 RateSwitchTable11N2SForABand[1];
1132 DBGPRINT_RAW(RT_DEBUG_ERROR,
1133 ("DRS: unkown mode,default use 11N 2S AP \n"));
ca97b838
BZ
1134 }
1135 }
96b3c83d
BZ
1136 DBGPRINT_RAW(RT_DEBUG_ERROR,
1137 ("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1138 pAd->StaActive.SupRateLen,
1139 pAd->StaActive.ExtRateLen,
1140 pAd->StaActive.SupportedPhyInfo.MCSSet[0],
1141 pAd->StaActive.SupportedPhyInfo.
1142 MCSSet[1]));
ca97b838 1143 }
96b3c83d 1144 } while (FALSE);
ca97b838
BZ
1145}
1146
62eb734b 1147void STAMlmePeriodicExec(struct rt_rtmp_adapter *pAd)
ca97b838 1148{
51126deb 1149 unsigned long TxTotalCnt;
96b3c83d 1150 int i;
ca97b838
BZ
1151
1152 /*
96b3c83d
BZ
1153 We return here in ATE mode, because the statistics
1154 that ATE need are not collected via this routine.
1155 */
ca97b838 1156#if defined(RT305x)||defined(RT3070)
ec278fa2 1157 /* request by Gary, if Rssi0 > -42, BBP 82 need to be changed from 0x62 to 0x42, , bbp 67 need to be changed from 0x20 to 0x18 */
96b3c83d 1158 if (!pAd->CommonCfg.HighPowerPatchDisabled) {
ca97b838 1159#ifdef RT3070
96b3c83d 1160 if ((IS_RT3070(pAd) && ((pAd->MACVersion & 0xffff) < 0x0201)))
ec278fa2 1161#endif /* RT3070 // */
96b3c83d
BZ
1162 {
1163 if ((pAd->StaCfg.RssiSample.AvgRssi0 != 0)
1164 && (pAd->StaCfg.RssiSample.AvgRssi0 >
1165 (pAd->BbpRssiToDbmDelta - 35))) {
1166 RT30xxWriteRFRegister(pAd, RF_R27, 0x20);
1167 } else {
1168 RT30xxWriteRFRegister(pAd, RF_R27, 0x23);
1169 }
1170 }
ca97b838
BZ
1171 }
1172#endif
e44fd1cf 1173#ifdef PCIE_PS_SUPPORT
ec278fa2
BZ
1174/* don't perform idle-power-save mechanism within 3 min after driver initialization. */
1175/* This can make rebooter test more robust */
96b3c83d
BZ
1176 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_PCIE_DEVICE)) {
1177 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd))
1178 && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1179 && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1180 && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF))) {
1181 if (IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)) {
1182 if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1183 TRUE) {
1184 DBGPRINT(RT_DEBUG_TRACE,
1185 ("%s\n", __func__));
1186 RT28xxPciAsicRadioOff(pAd,
1187 GUI_IDLE_POWER_SAVE,
1188 0);
1189 } else {
1190 AsicSendCommandToMcu(pAd, 0x30,
1191 PowerSafeCID, 0xff,
1192 0x2);
ec278fa2 1193 /* Wait command success */
96b3c83d
BZ
1194 AsicCheckCommanOk(pAd, PowerSafeCID);
1195 RTMP_SET_FLAG(pAd,
1196 fRTMP_ADAPTER_IDLE_RADIO_OFF);
1197 DBGPRINT(RT_DEBUG_TRACE,
1198 ("PSM - rt30xx Issue Sleep command)\n"));
e44fd1cf 1199 }
96b3c83d
BZ
1200 } else if (pAd->Mlme.OneSecPeriodicRound > 180) {
1201 if (pAd->StaCfg.PSControl.field.EnableNewPS ==
1202 TRUE) {
1203 DBGPRINT(RT_DEBUG_TRACE,
1204 ("%s\n", __func__));
1205 RT28xxPciAsicRadioOff(pAd,
1206 GUI_IDLE_POWER_SAVE,
1207 0);
1208 } else {
1209 AsicSendCommandToMcu(pAd, 0x30,
1210 PowerSafeCID, 0xff,
1211 0x02);
ec278fa2 1212 /* Wait command success */
96b3c83d
BZ
1213 AsicCheckCommanOk(pAd, PowerSafeCID);
1214 RTMP_SET_FLAG(pAd,
1215 fRTMP_ADAPTER_IDLE_RADIO_OFF);
1216 DBGPRINT(RT_DEBUG_TRACE,
1217 ("PSM - rt28xx Issue Sleep command)\n"));
e44fd1cf
BZ
1218 }
1219 }
96b3c83d
BZ
1220 } else {
1221 DBGPRINT(RT_DEBUG_TRACE,
1222 ("STAMlmePeriodicExec MMCHK - CommonCfg.Ssid[%d]=%c%c%c%c... MlmeAux.Ssid[%d]=%c%c%c%c...\n",
1223 pAd->CommonCfg.SsidLen,
1224 pAd->CommonCfg.Ssid[0],
1225 pAd->CommonCfg.Ssid[1],
1226 pAd->CommonCfg.Ssid[2],
1227 pAd->CommonCfg.Ssid[3], pAd->MlmeAux.SsidLen,
1228 pAd->MlmeAux.Ssid[0], pAd->MlmeAux.Ssid[1],
1229 pAd->MlmeAux.Ssid[2], pAd->MlmeAux.Ssid[3]));
e44fd1cf
BZ
1230 }
1231 }
ec278fa2 1232#endif /* PCIE_PS_SUPPORT // */
ca97b838 1233
96b3c83d 1234 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE) {
ec278fa2 1235 /* WPA MIC error should block association attempt for 60 seconds */
ca97b838 1236 if (pAd->StaCfg.bBlockAssoc &&
96b3c83d
BZ
1237 RTMP_TIME_AFTER(pAd->Mlme.Now32,
1238 pAd->StaCfg.LastMicErrorTime +
1239 (60 * OS_HZ)))
1240 pAd->StaCfg.bBlockAssoc = FALSE;
1241 }
1242
1243 if ((pAd->PreMediaState != pAd->IndicateMediaState)
1244 && (pAd->CommonCfg.bWirelessEvent)) {
1245 if (pAd->IndicateMediaState == NdisMediaStateConnected) {
1246 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG,
1247 pAd->MacTab.Content[BSSID_WCID].
1248 Addr, BSS0, 0);
ca97b838
BZ
1249 }
1250 pAd->PreMediaState = pAd->IndicateMediaState;
1251 }
1252
96b3c83d
BZ
1253 if (pAd->CommonCfg.PSPXlink && ADHOC_ON(pAd)) {
1254 } else {
1255 AsicStaBbpTuning(pAd);
ca97b838
BZ
1256 }
1257
1258 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
96b3c83d
BZ
1259 pAd->RalinkCounters.OneSecTxRetryOkCount +
1260 pAd->RalinkCounters.OneSecTxFailCount;
ca97b838 1261
96b3c83d 1262 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
ec278fa2 1263 /* update channel quality for Roaming and UI LinkQuality display */
ca97b838
BZ
1264 MlmeCalculateChannelQuality(pAd, NULL, pAd->Mlme.Now32);
1265 }
ec278fa2
BZ
1266 /* must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if */
1267 /* Radio is currently in noisy environment */
ca97b838 1268 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
96b3c83d 1269 AsicAdjustTxPower(pAd);
ca97b838 1270
96b3c83d 1271 if (INFRA_ON(pAd)) {
ca97b838 1272
ec278fa2
BZ
1273 /* Is PSM bit consistent with user power management policy? */
1274 /* This is the only place that will set PSM bit ON. */
ca97b838 1275 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
96b3c83d 1276 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
ca97b838
BZ
1277
1278 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1279
96b3c83d
BZ
1280 if ((RTMP_TIME_AFTER
1281 (pAd->Mlme.Now32,
1282 pAd->StaCfg.LastBeaconRxTime + (1 * OS_HZ)))
1283 &&
1284 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1285 &&
1286 (((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt) <
1287 600))) {
ca97b838 1288 RTMPSetAGCInitValue(pAd, BW_20);
96b3c83d
BZ
1289 DBGPRINT(RT_DEBUG_TRACE,
1290 ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n",
1291 (0x2E + GET_LNA_GAIN(pAd))));
1292 }
ec278fa2
BZ
1293 /*if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) && */
1294 /* (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)) */
96b3c83d
BZ
1295 {
1296 if (pAd->CommonCfg.bAPSDCapable
1297 && pAd->CommonCfg.APEdcaParm.bAPSDCapable) {
ec278fa2 1298 /* When APSD is enabled, the period changes as 20 sec */
96b3c83d
BZ
1299 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1300 RTMPSendNullFrame(pAd,
1301 pAd->CommonCfg.TxRate,
1302 TRUE);
1303 } else {
ec278fa2 1304 /* Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out) */
96b3c83d
BZ
1305 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) {
1306 if (pAd->CommonCfg.bWmmCapable)
1307 RTMPSendNullFrame(pAd,
1308 pAd->
1309 CommonCfg.
1310 TxRate, TRUE);
1311 else
1312 RTMPSendNullFrame(pAd,
1313 pAd->
1314 CommonCfg.
1315 TxRate,
1316 FALSE);
1317 }
1318 }
ca97b838
BZ
1319 }
1320
96b3c83d
BZ
1321 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality)) {
1322 DBGPRINT(RT_DEBUG_TRACE,
1323 ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n",
1324 pAd->RalinkCounters.BadCQIAutoRecoveryCount));
ca97b838 1325
ec278fa2 1326 /* Lost AP, send disconnect & link down event */
91980990
GKH
1327 LinkDown(pAd, FALSE);
1328
96b3c83d
BZ
1329 RtmpOSWrielessEventSend(pAd, SIOCGIWAP, -1, NULL, NULL,
1330 0);
ca97b838 1331
ec278fa2 1332 /* RTMPPatchMacBbpBug(pAd); */
91980990 1333 MlmeAutoReconnectLastSSID(pAd);
96b3c83d
BZ
1334 } else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality)) {
1335 pAd->RalinkCounters.BadCQIAutoRecoveryCount++;
1336 DBGPRINT(RT_DEBUG_TRACE,
1337 ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n",
1338 pAd->RalinkCounters.BadCQIAutoRecoveryCount));
91980990
GKH
1339 MlmeAutoReconnectLastSSID(pAd);
1340 }
1341
96b3c83d
BZ
1342 if (pAd->StaCfg.bAutoRoaming) {
1343 BOOLEAN rv = FALSE;
51126deb
BZ
1344 char dBmToRoam = pAd->StaCfg.dBmToRoam;
1345 char MaxRssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
1346 pAd->StaCfg.RssiSample.
1347 LastRssi0,
1348 pAd->StaCfg.RssiSample.
1349 LastRssi1,
1350 pAd->StaCfg.RssiSample.
1351 LastRssi2);
91980990 1352
ec278fa2 1353 /* Scanning, ignore Roaming */
96b3c83d
BZ
1354 if (!RTMP_TEST_FLAG
1355 (pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)
1356 && (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE)
1357 && (MaxRssi <= dBmToRoam)) {
1358 DBGPRINT(RT_DEBUG_TRACE,
1359 ("Rssi=%d, dBmToRoam=%d\n", MaxRssi,
51126deb 1360 (char)dBmToRoam));
ca97b838 1361
ec278fa2 1362 /* Add auto seamless roaming */
ca97b838
BZ
1363 if (rv == FALSE)
1364 rv = MlmeCheckForFastRoaming(pAd);
91980990 1365
96b3c83d
BZ
1366 if (rv == FALSE) {
1367 if ((pAd->StaCfg.LastScanTime +
1368 10 * OS_HZ) < pAd->Mlme.Now32) {
1369 DBGPRINT(RT_DEBUG_TRACE,
1370 ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
ca97b838 1371 pAd->StaCfg.ScanCnt = 2;
96b3c83d
BZ
1372 pAd->StaCfg.LastScanTime =
1373 pAd->Mlme.Now32;
ca97b838 1374 MlmeAutoScan(pAd);
96b3c83d
BZ
1375 }
1376 }
91980990
GKH
1377 }
1378 }
96b3c83d 1379 } else if (ADHOC_ON(pAd)) {
ec278fa2
BZ
1380 /* If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState */
1381 /* to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can */
1382 /* join later. */
96b3c83d
BZ
1383 if (RTMP_TIME_AFTER
1384 (pAd->Mlme.Now32,
1385 pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME)
1386 && OPSTATUS_TEST_FLAG(pAd,
1387 fOP_STATUS_MEDIA_STATE_CONNECTED)) {
62eb734b 1388 struct rt_mlme_start_req StartReq;
96b3c83d
BZ
1389
1390 DBGPRINT(RT_DEBUG_TRACE,
1391 ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
91980990
GKH
1392 LinkDown(pAd, FALSE);
1393
96b3c83d 1394 StartParmFill(pAd, &StartReq,
51126deb 1395 (char *) pAd->MlmeAux.Ssid,
96b3c83d
BZ
1396 pAd->MlmeAux.SsidLen);
1397 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ,
62eb734b 1398 sizeof(struct rt_mlme_start_req), &StartReq);
91980990
GKH
1399 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1400 }
59fe2d89 1401
96b3c83d 1402 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
62eb734b 1403 struct rt_mac_table_entry *pEntry = &pAd->MacTab.Content[i];
59fe2d89
BZ
1404
1405 if (pEntry->ValidAsCLI == FALSE)
1406 continue;
1407
96b3c83d
BZ
1408 if (RTMP_TIME_AFTER
1409 (pAd->Mlme.Now32,
1410 pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME))
1411 MacTableDeleteEntry(pAd, pEntry->Aid,
1412 pEntry->Addr);
59fe2d89 1413 }
ec278fa2 1414 } else /* no INFRA nor ADHOC connection */
91980990
GKH
1415 {
1416
1417 if (pAd->StaCfg.bScanReqIsFromWebUI &&
96b3c83d
BZ
1418 RTMP_TIME_BEFORE(pAd->Mlme.Now32,
1419 pAd->StaCfg.LastScanTime + (30 * OS_HZ)))
91980990 1420 goto SKIP_AUTO_SCAN_CONN;
96b3c83d
BZ
1421 else
1422 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
91980990
GKH
1423
1424 if ((pAd->StaCfg.bAutoReconnect == TRUE)
96b3c83d
BZ
1425 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1426 &&
1427 (MlmeValidateSSID
1428 (pAd->MlmeAux.AutoReconnectSsid,
1429 pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
1430 if ((pAd->ScanTab.BssNr == 0)
1431 && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)) {
62eb734b 1432 struct rt_mlme_scan_req ScanReq;
96b3c83d
BZ
1433
1434 if (RTMP_TIME_AFTER
1435 (pAd->Mlme.Now32,
1436 pAd->StaCfg.LastScanTime + (10 * OS_HZ))) {
1437 DBGPRINT(RT_DEBUG_TRACE,
1438 ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n",
1439 pAd->MlmeAux.
1440 AutoReconnectSsid));
1441 ScanParmFill(pAd, &ScanReq,
51126deb 1442 (char *)pAd->MlmeAux.
96b3c83d
BZ
1443 AutoReconnectSsid,
1444 pAd->MlmeAux.
1445 AutoReconnectSsidLen,
1446 BSS_ANY, SCAN_ACTIVE);
1447 MlmeEnqueue(pAd, SYNC_STATE_MACHINE,
1448 MT2_MLME_SCAN_REQ,
1449 sizeof
62eb734b 1450 (struct rt_mlme_scan_req),
96b3c83d
BZ
1451 &ScanReq);
1452 pAd->Mlme.CntlMachine.CurrState =
1453 CNTL_WAIT_OID_LIST_SCAN;
ec278fa2 1454 /* Reset Missed scan number */
96b3c83d
BZ
1455 pAd->StaCfg.LastScanTime =
1456 pAd->Mlme.Now32;
ec278fa2 1457 } else if (pAd->StaCfg.BssType == BSS_ADHOC) /* Quit the forever scan when in a very clean room */
91980990 1458 MlmeAutoReconnectLastSSID(pAd);
96b3c83d
BZ
1459 } else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1460 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0) {
91980990 1461 MlmeAutoScan(pAd);
96b3c83d
BZ
1462 pAd->StaCfg.LastScanTime =
1463 pAd->Mlme.Now32;
1464 } else {
1465 MlmeAutoReconnectLastSSID(pAd);
91980990
GKH
1466 }
1467 }
1468 }
1469 }
1470
1471SKIP_AUTO_SCAN_CONN:
1472
96b3c83d
BZ
1473 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap != 0)
1474 && (pAd->MacTab.fAnyBASession == FALSE)) {
91980990 1475 pAd->MacTab.fAnyBASession = TRUE;
96b3c83d
BZ
1476 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE,
1477 FALSE);
1478 } else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap == 0)
1479 && (pAd->MacTab.fAnyBASession == TRUE)) {
91980990 1480 pAd->MacTab.fAnyBASession = FALSE;
96b3c83d
BZ
1481 AsicUpdateProtect(pAd,
1482 pAd->MlmeAux.AddHtInfo.AddHtInfo2.
1483 OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
91980990 1484 }
91980990 1485
91980990
GKH
1486 return;
1487}
1488
ec278fa2 1489/* Link down report */
51126deb
BZ
1490void LinkDownExec(void *SystemSpecific1,
1491 void *FunctionContext,
1492 void *SystemSpecific2, void *SystemSpecific3)
91980990 1493{
62eb734b 1494 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
91980990 1495
96b3c83d 1496 if (pAd != NULL) {
62eb734b 1497 struct rt_mlme_disassoc_req DisassocReq;
ca97b838
BZ
1498
1499 if ((pAd->StaCfg.PortSecured == WPA_802_1X_PORT_NOT_SECURED) &&
96b3c83d
BZ
1500 (INFRA_ON(pAd))) {
1501 DBGPRINT(RT_DEBUG_TRACE,
1502 ("LinkDownExec(): disassociate with current AP...\n"));
1503 DisassocParmFill(pAd, &DisassocReq,
1504 pAd->CommonCfg.Bssid,
1505 REASON_DISASSOC_STA_LEAVING);
1506 MlmeEnqueue(pAd, ASSOC_STATE_MACHINE,
1507 MT2_MLME_DISASSOC_REQ,
62eb734b 1508 sizeof(struct rt_mlme_disassoc_req),
96b3c83d 1509 &DisassocReq);
ca97b838
BZ
1510 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_DISASSOC;
1511
96b3c83d
BZ
1512 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1513 RTMP_IndicateMediaState(pAd);
1514 pAd->ExtraInfo = GENERAL_LINK_DOWN;
ca97b838
BZ
1515 }
1516 }
91980990
GKH
1517}
1518
ec278fa2 1519/* IRQL = DISPATCH_LEVEL */
62eb734b 1520void MlmeAutoScan(struct rt_rtmp_adapter *pAd)
91980990 1521{
ec278fa2 1522 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
96b3c83d 1523 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
91980990
GKH
1524 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1525 MlmeEnqueue(pAd,
96b3c83d
BZ
1526 MLME_CNTL_STATE_MACHINE,
1527 OID_802_11_BSSID_LIST_SCAN,
1528 pAd->MlmeAux.AutoReconnectSsidLen,
1529 pAd->MlmeAux.AutoReconnectSsid);
ca97b838 1530 RTMP_MLME_HANDLER(pAd);
91980990
GKH
1531 }
1532}
1533
ec278fa2 1534/* IRQL = DISPATCH_LEVEL */
62eb734b 1535void MlmeAutoReconnectLastSSID(struct rt_rtmp_adapter *pAd)
91980990 1536{
96b3c83d
BZ
1537 if (pAd->StaCfg.bAutoConnectByBssid) {
1538 DBGPRINT(RT_DEBUG_TRACE,
1539 ("Driver auto reconnect to last OID_802_11_BSSID setting - %02X:%02X:%02X:%02X:%02X:%02X\n",
1540 pAd->MlmeAux.Bssid[0], pAd->MlmeAux.Bssid[1],
1541 pAd->MlmeAux.Bssid[2], pAd->MlmeAux.Bssid[3],
1542 pAd->MlmeAux.Bssid[4], pAd->MlmeAux.Bssid[5]));
ca97b838
BZ
1543
1544 pAd->MlmeAux.Channel = pAd->CommonCfg.Channel;
1545 MlmeEnqueue(pAd,
96b3c83d
BZ
1546 MLME_CNTL_STATE_MACHINE,
1547 OID_802_11_BSSID, MAC_ADDR_LEN, pAd->MlmeAux.Bssid);
91980990 1548
ca97b838 1549 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
91980990 1550
ca97b838
BZ
1551 RTMP_MLME_HANDLER(pAd);
1552 }
ec278fa2 1553 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
ca97b838 1554 else if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
96b3c83d
BZ
1555 (MlmeValidateSSID
1556 (pAd->MlmeAux.AutoReconnectSsid,
1557 pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) {
62eb734b 1558 struct rt_ndis_802_11_ssid OidSsid;
91980990 1559 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
96b3c83d
BZ
1560 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid,
1561 pAd->MlmeAux.AutoReconnectSsidLen);
1562
1563 DBGPRINT(RT_DEBUG_TRACE,
1564 ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n",
1565 pAd->MlmeAux.AutoReconnectSsid,
1566 pAd->MlmeAux.AutoReconnectSsidLen));
1567 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID,
62eb734b 1568 sizeof(struct rt_ndis_802_11_ssid), &OidSsid);
ca97b838 1569 RTMP_MLME_HANDLER(pAd);
91980990
GKH
1570 }
1571}
91980990
GKH
1572
1573/*
1574 ==========================================================================
ca97b838
BZ
1575 Description:
1576 This routine checks if there're other APs out there capable for
1577 roaming. Caller should call this routine only when Link up in INFRA mode
1578 and channel quality is below CQI_GOOD_THRESHOLD.
1579
91980990 1580 IRQL = DISPATCH_LEVEL
ca97b838
BZ
1581
1582 Output:
91980990
GKH
1583 ==========================================================================
1584 */
62eb734b 1585void MlmeCheckForRoaming(struct rt_rtmp_adapter *pAd, unsigned long Now32)
91980990 1586{
51126deb 1587 u16 i;
62eb734b
BZ
1588 struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1589 struct rt_bss_entry *pBss;
91980990 1590
ca97b838 1591 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
ec278fa2 1592 /* put all roaming candidates into RoamTab, and sort in RSSI order */
ca97b838 1593 BssTableInit(pRoamTab);
96b3c83d 1594 for (i = 0; i < pAd->ScanTab.BssNr; i++) {
ca97b838
BZ
1595 pBss = &pAd->ScanTab.BssEntry[i];
1596
96b3c83d
BZ
1597 if ((pBss->LastBeaconRxTime + pAd->StaCfg.BeaconLostTime) <
1598 Now32)
ec278fa2 1599 continue; /* AP disappear */
ca97b838 1600 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
ec278fa2 1601 continue; /* RSSI too weak. forget it. */
ca97b838 1602 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
ec278fa2 1603 continue; /* skip current AP */
96b3c83d
BZ
1604 if (pBss->Rssi <
1605 (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
ec278fa2 1606 continue; /* only AP with stronger RSSI is eligible for roaming */
ca97b838 1607
ec278fa2 1608 /* AP passing all above rules is put into roaming candidate table */
96b3c83d 1609 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
62eb734b 1610 sizeof(struct rt_bss_entry));
ca97b838 1611 pRoamTab->BssNr += 1;
91980990
GKH
1612 }
1613
96b3c83d 1614 if (pRoamTab->BssNr > 0) {
ec278fa2 1615 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
96b3c83d
BZ
1616 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1617 pAd->RalinkCounters.PoorCQIRoamingCount++;
1618 DBGPRINT(RT_DEBUG_TRACE,
1619 ("MMCHK - Roaming attempt #%ld\n",
1620 pAd->RalinkCounters.PoorCQIRoamingCount));
1621 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1622 MT2_MLME_ROAMING_REQ, 0, NULL);
ca97b838
BZ
1623 RTMP_MLME_HANDLER(pAd);
1624 }
1625 }
96b3c83d
BZ
1626 DBGPRINT(RT_DEBUG_TRACE,
1627 ("<== MlmeCheckForRoaming(# of candidate= %d)\n",
1628 pRoamTab->BssNr));
91980990
GKH
1629}
1630
ca97b838
BZ
1631/*
1632 ==========================================================================
1633 Description:
1634 This routine checks if there're other APs out there capable for
1635 roaming. Caller should call this routine only when link up in INFRA mode
1636 and channel quality is below CQI_GOOD_THRESHOLD.
1637
1638 IRQL = DISPATCH_LEVEL
1639
1640 Output:
1641 ==========================================================================
1642 */
62eb734b 1643BOOLEAN MlmeCheckForFastRoaming(struct rt_rtmp_adapter *pAd)
91980990 1644{
51126deb 1645 u16 i;
62eb734b
BZ
1646 struct rt_bss_table *pRoamTab = &pAd->MlmeAux.RoamTab;
1647 struct rt_bss_entry *pBss;
ca97b838
BZ
1648
1649 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
ec278fa2 1650 /* put all roaming candidates into RoamTab, and sort in RSSI order */
ca97b838 1651 BssTableInit(pRoamTab);
96b3c83d 1652 for (i = 0; i < pAd->ScanTab.BssNr; i++) {
ca97b838 1653 pBss = &pAd->ScanTab.BssEntry[i];
91980990 1654
96b3c83d
BZ
1655 if ((pBss->Rssi <= -50)
1656 && (pBss->Channel == pAd->CommonCfg.Channel))
ec278fa2 1657 continue; /* RSSI too weak. forget it. */
ca97b838 1658 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
ec278fa2 1659 continue; /* skip current AP */
96b3c83d
BZ
1660 if (!SSID_EQUAL
1661 (pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid,
1662 pAd->CommonCfg.SsidLen))
ec278fa2 1663 continue; /* skip different SSID */
96b3c83d
BZ
1664 if (pBss->Rssi <
1665 (RTMPMaxRssi
1666 (pAd, pAd->StaCfg.RssiSample.LastRssi0,
1667 pAd->StaCfg.RssiSample.LastRssi1,
1668 pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
ec278fa2 1669 continue; /* skip AP without better RSSI */
96b3c83d
BZ
1670
1671 DBGPRINT(RT_DEBUG_TRACE,
1672 ("LastRssi0 = %d, pBss->Rssi = %d\n",
1673 RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0,
1674 pAd->StaCfg.RssiSample.LastRssi1,
1675 pAd->StaCfg.RssiSample.LastRssi2),
1676 pBss->Rssi));
ec278fa2 1677 /* AP passing all above rules is put into roaming candidate table */
96b3c83d 1678 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss,
62eb734b 1679 sizeof(struct rt_bss_entry));
ca97b838 1680 pRoamTab->BssNr += 1;
96b3c83d 1681 }
91980990 1682
96b3c83d
BZ
1683 DBGPRINT(RT_DEBUG_TRACE,
1684 ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1685 if (pRoamTab->BssNr > 0) {
ec278fa2 1686 /* check CntlMachine.CurrState to avoid collision with NDIS SetOID request */
96b3c83d
BZ
1687 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) {
1688 pAd->RalinkCounters.PoorCQIRoamingCount++;
1689 DBGPRINT(RT_DEBUG_TRACE,
1690 ("MMCHK - Roaming attempt #%ld\n",
1691 pAd->RalinkCounters.PoorCQIRoamingCount));
1692 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE,
1693 MT2_MLME_ROAMING_REQ, 0, NULL);
ca97b838
BZ
1694 RTMP_MLME_HANDLER(pAd);
1695 return TRUE;
96b3c83d
BZ
1696 }
1697 }
91980990 1698
ca97b838
BZ
1699 return FALSE;
1700}
91980990 1701
62eb734b
BZ
1702void MlmeSetTxRate(struct rt_rtmp_adapter *pAd,
1703 struct rt_mac_table_entry *pEntry, struct rt_rtmp_tx_rate_switch * pTxRate)
ca97b838 1704{
51126deb 1705 u8 MaxMode = MODE_OFDM;
91980990 1706
ca97b838 1707 MaxMode = MODE_HTGREENFIELD;
91980990 1708
96b3c83d
BZ
1709 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC)
1710 && (pAd->Antenna.field.TxPath == 2))
ca97b838 1711 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
96b3c83d 1712 else
ca97b838 1713 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
91980990 1714
ca97b838
BZ
1715 if (pTxRate->CurrMCS < MCS_AUTO)
1716 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
91980990 1717
ca97b838
BZ
1718 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1719 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
91980990 1720
96b3c83d 1721 if (ADHOC_ON(pAd)) {
ec278fa2 1722 /* If peer adhoc is b-only mode, we can't send 11g rate. */
ca97b838 1723 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
96b3c83d 1724 pEntry->HTPhyMode.field.STBC = STBC_NONE;
91980990 1725
ec278fa2
BZ
1726 /* */
1727 /* For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary */
1728 /* */
96b3c83d
BZ
1729 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1730 pEntry->HTPhyMode.field.ShortGI =
1731 pAd->StaCfg.HTPhyMode.field.ShortGI;
1732 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
ca97b838 1733
ec278fa2 1734 /* Patch speed error in status page */
ca97b838 1735 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
96b3c83d 1736 } else {
ca97b838 1737 if (pTxRate->Mode <= MaxMode)
96b3c83d 1738 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
91980990 1739
96b3c83d
BZ
1740 if (pTxRate->ShortGI
1741 && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
ca97b838
BZ
1742 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1743 else
1744 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
91980990 1745
ec278fa2 1746 /* Reexam each bandwidth's SGI support. */
96b3c83d
BZ
1747 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400) {
1748 if ((pEntry->HTPhyMode.field.BW == BW_20)
1749 &&
1750 (!CLIENT_STATUS_TEST_FLAG
1751 (pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
ca97b838 1752 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
96b3c83d
BZ
1753 if ((pEntry->HTPhyMode.field.BW == BW_40)
1754 &&
1755 (!CLIENT_STATUS_TEST_FLAG
1756 (pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
ca97b838 1757 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
91980990 1758 }
ec278fa2 1759 /* Turn RTS/CTS rate to 6Mbps. */
96b3c83d
BZ
1760 if ((pEntry->HTPhyMode.field.MCS == 0)
1761 && (pAd->StaCfg.HTPhyMode.field.MCS != 0)) {
1762 pEntry->HTPhyMode.field.MCS =
1763 pAd->StaCfg.HTPhyMode.field.MCS;
1764 if (pAd->MacTab.fAnyBASession) {
1765 AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1766 ALLN_SETPROTECT, TRUE,
1767 (BOOLEAN) pAd->MlmeAux.
1768 AddHtInfo.AddHtInfo2.
1769 NonGfPresent);
1770 } else {
1771 AsicUpdateProtect(pAd,
1772 pAd->MlmeAux.AddHtInfo.
1773 AddHtInfo2.OperaionMode,
1774 ALLN_SETPROTECT, TRUE,
1775 (BOOLEAN) pAd->MlmeAux.
1776 AddHtInfo.AddHtInfo2.
1777 NonGfPresent);
91980990 1778 }
96b3c83d
BZ
1779 } else if ((pEntry->HTPhyMode.field.MCS == 8)
1780 && (pAd->StaCfg.HTPhyMode.field.MCS != 8)) {
1781 pEntry->HTPhyMode.field.MCS =
1782 pAd->StaCfg.HTPhyMode.field.MCS;
1783 if (pAd->MacTab.fAnyBASession) {
1784 AsicUpdateProtect(pAd, HT_FORCERTSCTS,
1785 ALLN_SETPROTECT, TRUE,
1786 (BOOLEAN) pAd->MlmeAux.
1787 AddHtInfo.AddHtInfo2.
1788 NonGfPresent);
1789 } else {
1790 AsicUpdateProtect(pAd,
1791 pAd->MlmeAux.AddHtInfo.
1792 AddHtInfo2.OperaionMode,
1793 ALLN_SETPROTECT, TRUE,
1794 (BOOLEAN) pAd->MlmeAux.
1795 AddHtInfo.AddHtInfo2.
1796 NonGfPresent);
ca97b838 1797 }
96b3c83d
BZ
1798 } else if ((pEntry->HTPhyMode.field.MCS != 0)
1799 && (pAd->StaCfg.HTPhyMode.field.MCS == 0)) {
1800 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1801 TRUE,
1802 (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1803 AddHtInfo2.NonGfPresent);
1804
1805 } else if ((pEntry->HTPhyMode.field.MCS != 8)
1806 && (pAd->StaCfg.HTPhyMode.field.MCS == 8)) {
1807 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT,
1808 TRUE,
1809 (BOOLEAN) pAd->MlmeAux.AddHtInfo.
1810 AddHtInfo2.NonGfPresent);
91980990 1811 }
91980990 1812
96b3c83d
BZ
1813 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1814 pEntry->HTPhyMode.field.ShortGI =
1815 pAd->StaCfg.HTPhyMode.field.ShortGI;
1816 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1817 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1818 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD)
1819 && pAd->WIFItestbed.bGreenField)
1820 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1821 }
1822
51126deb 1823 pAd->LastTxRate = (u16)(pEntry->HTPhyMode.word);
91980990
GKH
1824}
1825
91980990
GKH
1826/*
1827 ==========================================================================
1828 Description:
ca97b838
BZ
1829 This routine calculates the acumulated TxPER of eaxh TxRate. And
1830 according to the calculation result, change CommonCfg.TxRate which
1831 is the stable TX Rate we expect the Radio situation could sustained.
1832
1833 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1834 Output:
1835 CommonCfg.TxRate -
91980990
GKH
1836
1837 IRQL = DISPATCH_LEVEL
1838
ca97b838
BZ
1839 NOTE:
1840 call this routine every second
91980990
GKH
1841 ==========================================================================
1842 */
62eb734b 1843void MlmeDynamicTxRateSwitching(struct rt_rtmp_adapter *pAd)
91980990 1844{
51126deb
BZ
1845 u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1846 unsigned long i, AccuTxTotalCnt = 0, TxTotalCnt;
1847 unsigned long TxErrorRatio = 0;
96b3c83d 1848 BOOLEAN bTxRateChanged = FALSE, bUpgradeQuality = FALSE;
62eb734b 1849 struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
51126deb
BZ
1850 u8 *pTable;
1851 u8 TableSize = 0;
1852 u8 InitTxRateIdx = 0, TrainUp, TrainDown;
1853 char Rssi, RssiOffset = 0;
96b3c83d
BZ
1854 TX_STA_CNT1_STRUC StaTx1;
1855 TX_STA_CNT0_STRUC TxStaCnt0;
51126deb 1856 unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
62eb734b
BZ
1857 struct rt_mac_table_entry *pEntry;
1858 struct rt_rssi_sample *pRssi = &pAd->StaCfg.RssiSample;
91980990 1859
ec278fa2
BZ
1860 /* */
1861 /* walk through MAC table, see if need to change AP's TX rate toward each entry */
1862 /* */
96b3c83d 1863 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
ca97b838 1864 pEntry = &pAd->MacTab.Content[i];
91980990 1865
ec278fa2 1866 /* check if this entry need to switch rate automatically */
ca97b838
BZ
1867 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1868 continue;
91980990 1869
96b3c83d 1870 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls)) {
ca97b838 1871 Rssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
1872 pRssi->AvgRssi0,
1873 pRssi->AvgRssi1, pRssi->AvgRssi2);
91980990 1874
ec278fa2 1875 /* Update statistic counter */
ca97b838
BZ
1876 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1877 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1878 pAd->bUpdateBcnCntDone = TRUE;
1879 TxRetransmit = StaTx1.field.TxRetransmit;
1880 TxSuccess = StaTx1.field.TxSuccess;
1881 TxFailCount = TxStaCnt0.field.TxFailCount;
1882 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
91980990 1883
96b3c83d
BZ
1884 pAd->RalinkCounters.OneSecTxRetryOkCount +=
1885 StaTx1.field.TxRetransmit;
1886 pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
1887 StaTx1.field.TxSuccess;
1888 pAd->RalinkCounters.OneSecTxFailCount +=
1889 TxStaCnt0.field.TxFailCount;
1890 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
1891 StaTx1.field.TxSuccess;
1892 pAd->WlanCounters.RetryCount.u.LowPart +=
1893 StaTx1.field.TxRetransmit;
1894 pAd->WlanCounters.FailedCount.u.LowPart +=
1895 TxStaCnt0.field.TxFailCount;
91980990 1896
ec278fa2
BZ
1897 /* if no traffic in the past 1-sec period, don't change TX rate, */
1898 /* but clear all bad history. because the bad history may affect the next */
1899 /* Chariot throughput test */
96b3c83d
BZ
1900 AccuTxTotalCnt =
1901 pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1902 pAd->RalinkCounters.OneSecTxRetryOkCount +
1903 pAd->RalinkCounters.OneSecTxFailCount;
91980990 1904
ca97b838 1905 if (TxTotalCnt)
96b3c83d
BZ
1906 TxErrorRatio =
1907 ((TxRetransmit +
1908 TxFailCount) * 100) / TxTotalCnt;
1909 } else {
ca97b838
BZ
1910 if (INFRA_ON(pAd) && (i == 1))
1911 Rssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
1912 pRssi->AvgRssi0,
1913 pRssi->AvgRssi1,
1914 pRssi->AvgRssi2);
ca97b838
BZ
1915 else
1916 Rssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
1917 pEntry->RssiSample.AvgRssi0,
1918 pEntry->RssiSample.AvgRssi1,
1919 pEntry->RssiSample.AvgRssi2);
91980990 1920
ca97b838 1921 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
96b3c83d
BZ
1922 pEntry->OneSecTxRetryOkCount +
1923 pEntry->OneSecTxFailCount;
91980990 1924
ca97b838 1925 if (TxTotalCnt)
96b3c83d
BZ
1926 TxErrorRatio =
1927 ((pEntry->OneSecTxRetryOkCount +
1928 pEntry->OneSecTxFailCount) * 100) /
1929 TxTotalCnt;
1930 }
91980990 1931
96b3c83d 1932 if (TxTotalCnt) {
ca97b838 1933 /*
96b3c83d
BZ
1934 Three AdHoc connections can not work normally if one AdHoc connection is disappeared from a heavy traffic environment generated by ping tool
1935 We force to set LongRtyLimit and ShortRtyLimit to 0 to stop retransmitting packet, after a while, resoring original settings
1936 */
1937 if (TxErrorRatio == 100) {
1938 TX_RTY_CFG_STRUC TxRtyCfg, TxRtyCfgtmp;
51126deb
BZ
1939 unsigned long Index;
1940 unsigned long MACValue;
ca97b838
BZ
1941
1942 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
1943 TxRtyCfgtmp.word = TxRtyCfg.word;
1944 TxRtyCfg.field.LongRtyLimit = 0x0;
1945 TxRtyCfg.field.ShortRtyLimit = 0x0;
1946 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
1947
1948 RTMPusecDelay(1);
1949
1950 Index = 0;
1951 MACValue = 0;
96b3c83d
BZ
1952 do {
1953 RTMP_IO_READ32(pAd, TXRXQ_PCNT,
1954 &MACValue);
ca97b838
BZ
1955 if ((MACValue & 0xffffff) == 0)
1956 break;
1957 Index++;
1958 RTMPusecDelay(1000);
96b3c83d
BZ
1959 } while ((Index < 330)
1960 &&
1961 (!RTMP_TEST_FLAG
1962 (pAd,
1963 fRTMP_ADAPTER_HALT_IN_PROGRESS)));
ca97b838
BZ
1964
1965 RTMP_IO_READ32(pAd, TX_RTY_CFG, &TxRtyCfg.word);
96b3c83d
BZ
1966 TxRtyCfg.field.LongRtyLimit =
1967 TxRtyCfgtmp.field.LongRtyLimit;
1968 TxRtyCfg.field.ShortRtyLimit =
1969 TxRtyCfgtmp.field.ShortRtyLimit;
ca97b838 1970 RTMP_IO_WRITE32(pAd, TX_RTY_CFG, TxRtyCfg.word);
96b3c83d 1971 }
91980990 1972 }
91980990 1973
ca97b838 1974 CurrRateIdx = pEntry->CurrTxRateIndex;
91980990 1975
96b3c83d
BZ
1976 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
1977 &InitTxRateIdx);
91980990 1978
96b3c83d 1979 if (CurrRateIdx >= TableSize) {
ca97b838
BZ
1980 CurrRateIdx = TableSize - 1;
1981 }
ec278fa2
BZ
1982 /* When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex. */
1983 /* So need to sync here. */
96b3c83d 1984 pCurrTxRate =
62eb734b 1985 (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
ca97b838 1986 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
ec278fa2 1987 /*&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE) */
96b3c83d 1988 ) {
91980990 1989
ec278fa2
BZ
1990 /* Need to sync Real Tx rate and our record. */
1991 /* Then return for next DRS. */
96b3c83d 1992 pCurrTxRate =
62eb734b 1993 (struct rt_rtmp_tx_rate_switch *) & pTable[(InitTxRateIdx + 1)
96b3c83d 1994 * 5];
ca97b838
BZ
1995 pEntry->CurrTxRateIndex = InitTxRateIdx;
1996 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
91980990 1997
ec278fa2 1998 /* reset all OneSecTx counters */
ca97b838
BZ
1999 RESET_ONE_SEC_TX_CNT(pEntry);
2000 continue;
2001 }
ec278fa2 2002 /* decide the next upgrade rate and downgrade rate, if any */
96b3c83d 2003 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
ca97b838 2004 UpRateIdx = CurrRateIdx + 1;
96b3c83d
BZ
2005 DownRateIdx = CurrRateIdx - 1;
2006 } else if (CurrRateIdx == 0) {
ca97b838
BZ
2007 UpRateIdx = CurrRateIdx + 1;
2008 DownRateIdx = CurrRateIdx;
96b3c83d 2009 } else if (CurrRateIdx == (TableSize - 1)) {
ca97b838
BZ
2010 UpRateIdx = CurrRateIdx;
2011 DownRateIdx = CurrRateIdx - 1;
96b3c83d 2012 }
91980990 2013
96b3c83d 2014 pCurrTxRate =
62eb734b 2015 (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
96b3c83d
BZ
2016
2017 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2018 TrainUp =
2019 (pCurrTxRate->TrainUp +
2020 (pCurrTxRate->TrainUp >> 1));
2021 TrainDown =
2022 (pCurrTxRate->TrainDown +
2023 (pCurrTxRate->TrainDown >> 1));
2024 } else {
2025 TrainUp = pCurrTxRate->TrainUp;
2026 TrainDown = pCurrTxRate->TrainDown;
2027 }
91980990 2028
ec278fa2 2029 /*pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction; */
91980990 2030
ec278fa2
BZ
2031 /* */
2032 /* Keep the last time TxRateChangeAction status. */
2033 /* */
96b3c83d
BZ
2034 pEntry->LastTimeTxRateChangeAction =
2035 pEntry->LastSecTxRateChangeAction;
91980990 2036
ec278fa2
BZ
2037 /* */
2038 /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2039 /* (criteria copied from RT2500 for Netopia case) */
2040 /* */
96b3c83d 2041 if (TxTotalCnt <= 15) {
51126deb
BZ
2042 char idx = 0;
2043 u8 TxRateIdx;
2044 u8 MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 =
96b3c83d 2045 0, MCS5 = 0, MCS6 = 0, MCS7 = 0;
51126deb
BZ
2046 u8 MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2047 u8 MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; /* 3*3 */
91980990 2048
ec278fa2 2049 /* check the existence and index of each needed MCS */
96b3c83d
BZ
2050 while (idx < pTable[0]) {
2051 pCurrTxRate =
62eb734b 2052 (struct rt_rtmp_tx_rate_switch *) & pTable[(idx + 1) *
96b3c83d 2053 5];
91980990 2054
96b3c83d 2055 if (pCurrTxRate->CurrMCS == MCS_0) {
ca97b838 2056 MCS0 = idx;
96b3c83d 2057 } else if (pCurrTxRate->CurrMCS == MCS_1) {
ca97b838 2058 MCS1 = idx;
96b3c83d 2059 } else if (pCurrTxRate->CurrMCS == MCS_2) {
ca97b838 2060 MCS2 = idx;
96b3c83d 2061 } else if (pCurrTxRate->CurrMCS == MCS_3) {
ca97b838 2062 MCS3 = idx;
96b3c83d 2063 } else if (pCurrTxRate->CurrMCS == MCS_4) {
ca97b838 2064 MCS4 = idx;
96b3c83d
BZ
2065 } else if (pCurrTxRate->CurrMCS == MCS_5) {
2066 MCS5 = idx;
2067 } else if (pCurrTxRate->CurrMCS == MCS_6) {
2068 MCS6 = idx;
2069 }
ec278fa2
BZ
2070 /*else if (pCurrTxRate->CurrMCS == MCS_7) */
2071 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) /* prevent the highest MCS using short GI when 1T and low throughput */
96b3c83d 2072 {
ca97b838 2073 MCS7 = idx;
96b3c83d 2074 } else if (pCurrTxRate->CurrMCS == MCS_12) {
ca97b838 2075 MCS12 = idx;
96b3c83d 2076 } else if (pCurrTxRate->CurrMCS == MCS_13) {
ca97b838 2077 MCS13 = idx;
96b3c83d 2078 } else if (pCurrTxRate->CurrMCS == MCS_14) {
ca97b838 2079 MCS14 = idx;
96b3c83d 2080 }
ec278fa2 2081 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) /*we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI */
96b3c83d 2082 {
ca97b838 2083 MCS15 = idx;
ec278fa2 2084 } else if (pCurrTxRate->CurrMCS == MCS_20) /* 3*3 */
ca97b838
BZ
2085 {
2086 MCS20 = idx;
96b3c83d 2087 } else if (pCurrTxRate->CurrMCS == MCS_21) {
ca97b838 2088 MCS21 = idx;
96b3c83d 2089 } else if (pCurrTxRate->CurrMCS == MCS_22) {
ca97b838 2090 MCS22 = idx;
96b3c83d 2091 } else if (pCurrTxRate->CurrMCS == MCS_23) {
ca97b838
BZ
2092 MCS23 = idx;
2093 }
96b3c83d 2094 idx++;
ca97b838 2095 }
91980990 2096
96b3c83d
BZ
2097 if (pAd->LatchRfRegs.Channel <= 14) {
2098 if (pAd->NicConfig2.field.ExternalLNAForG) {
ca97b838 2099 RssiOffset = 2;
96b3c83d 2100 } else {
ca97b838
BZ
2101 RssiOffset = 5;
2102 }
96b3c83d
BZ
2103 } else {
2104 if (pAd->NicConfig2.field.ExternalLNAForA) {
ca97b838 2105 RssiOffset = 5;
96b3c83d 2106 } else {
ca97b838
BZ
2107 RssiOffset = 8;
2108 }
2109 }
91980990 2110
96b3c83d 2111 /*if (MCS15) */
ec278fa2 2112 if ((pTable == RateSwitchTable11BGN3S) || (pTable == RateSwitchTable11N3S) || (pTable == RateSwitchTable)) { /* N mode with 3 stream // 3*3 */
ca97b838
BZ
2113 if (MCS23 && (Rssi >= -70))
2114 TxRateIdx = MCS23;
2115 else if (MCS22 && (Rssi >= -72))
2116 TxRateIdx = MCS22;
96b3c83d 2117 else if (MCS21 && (Rssi >= -76))
ca97b838
BZ
2118 TxRateIdx = MCS21;
2119 else if (MCS20 && (Rssi >= -78))
2120 TxRateIdx = MCS20;
96b3c83d
BZ
2121 else if (MCS4 && (Rssi >= -82))
2122 TxRateIdx = MCS4;
2123 else if (MCS3 && (Rssi >= -84))
2124 TxRateIdx = MCS3;
2125 else if (MCS2 && (Rssi >= -86))
2126 TxRateIdx = MCS2;
2127 else if (MCS1 && (Rssi >= -88))
2128 TxRateIdx = MCS1;
2129 else
2130 TxRateIdx = MCS0;
2131 }
ec278fa2
BZ
2132/* else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable)) */
2133 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) || (pTable == RateSwitchTable11N2S) || (pTable == RateSwitchTable11N2SForABand)) /* 3*3 */
2134 { /* N mode with 2 stream */
96b3c83d 2135 if (MCS15 && (Rssi >= (-70 + RssiOffset)))
ca97b838 2136 TxRateIdx = MCS15;
96b3c83d 2137 else if (MCS14 && (Rssi >= (-72 + RssiOffset)))
ca97b838 2138 TxRateIdx = MCS14;
96b3c83d 2139 else if (MCS13 && (Rssi >= (-76 + RssiOffset)))
ca97b838 2140 TxRateIdx = MCS13;
96b3c83d 2141 else if (MCS12 && (Rssi >= (-78 + RssiOffset)))
ca97b838 2142 TxRateIdx = MCS12;
96b3c83d 2143 else if (MCS4 && (Rssi >= (-82 + RssiOffset)))
ca97b838 2144 TxRateIdx = MCS4;
96b3c83d 2145 else if (MCS3 && (Rssi >= (-84 + RssiOffset)))
ca97b838 2146 TxRateIdx = MCS3;
96b3c83d 2147 else if (MCS2 && (Rssi >= (-86 + RssiOffset)))
ca97b838 2148 TxRateIdx = MCS2;
96b3c83d 2149 else if (MCS1 && (Rssi >= (-88 + RssiOffset)))
ca97b838
BZ
2150 TxRateIdx = MCS1;
2151 else
2152 TxRateIdx = MCS0;
ec278fa2 2153 } else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S)) { /* N mode with 1 stream */
96b3c83d 2154 if (MCS7 && (Rssi > (-72 + RssiOffset)))
ca97b838 2155 TxRateIdx = MCS7;
96b3c83d 2156 else if (MCS6 && (Rssi > (-74 + RssiOffset)))
ca97b838 2157 TxRateIdx = MCS6;
96b3c83d 2158 else if (MCS5 && (Rssi > (-77 + RssiOffset)))
ca97b838 2159 TxRateIdx = MCS5;
96b3c83d 2160 else if (MCS4 && (Rssi > (-79 + RssiOffset)))
ca97b838 2161 TxRateIdx = MCS4;
96b3c83d 2162 else if (MCS3 && (Rssi > (-81 + RssiOffset)))
ca97b838 2163 TxRateIdx = MCS3;
96b3c83d 2164 else if (MCS2 && (Rssi > (-83 + RssiOffset)))
ca97b838 2165 TxRateIdx = MCS2;
96b3c83d 2166 else if (MCS1 && (Rssi > (-86 + RssiOffset)))
ca97b838
BZ
2167 TxRateIdx = MCS1;
2168 else
2169 TxRateIdx = MCS0;
ec278fa2 2170 } else { /* Legacy mode */
ca97b838
BZ
2171 if (MCS7 && (Rssi > -70))
2172 TxRateIdx = MCS7;
2173 else if (MCS6 && (Rssi > -74))
2174 TxRateIdx = MCS6;
2175 else if (MCS5 && (Rssi > -78))
2176 TxRateIdx = MCS5;
2177 else if (MCS4 && (Rssi > -82))
2178 TxRateIdx = MCS4;
ec278fa2 2179 else if (MCS4 == 0) /* for B-only mode */
ca97b838
BZ
2180 TxRateIdx = MCS3;
2181 else if (MCS3 && (Rssi > -85))
2182 TxRateIdx = MCS3;
2183 else if (MCS2 && (Rssi > -87))
2184 TxRateIdx = MCS2;
2185 else if (MCS1 && (Rssi > -90))
2186 TxRateIdx = MCS1;
2187 else
2188 TxRateIdx = MCS0;
2189 }
91980990 2190
ec278fa2 2191 /* if (TxRateIdx != pAd->CommonCfg.TxRateIndex) */
ca97b838
BZ
2192 {
2193 pEntry->CurrTxRateIndex = TxRateIdx;
96b3c83d 2194 pNextTxRate =
62eb734b 2195 (struct rt_rtmp_tx_rate_switch *) &
96b3c83d 2196 pTable[(pEntry->CurrTxRateIndex + 1) * 5];
ca97b838
BZ
2197 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2198 }
91980990 2199
96b3c83d 2200 NdisZeroMemory(pEntry->TxQuality,
51126deb 2201 sizeof(u16)*
96b3c83d
BZ
2202 MAX_STEP_OF_TX_RATE_SWITCH);
2203 NdisZeroMemory(pEntry->PER,
51126deb 2204 sizeof(u8)*
96b3c83d 2205 MAX_STEP_OF_TX_RATE_SWITCH);
ca97b838 2206 pEntry->fLastSecAccordingRSSI = TRUE;
ec278fa2 2207 /* reset all OneSecTx counters */
ca97b838 2208 RESET_ONE_SEC_TX_CNT(pEntry);
91980990 2209
ca97b838
BZ
2210 continue;
2211 }
91980990 2212
96b3c83d 2213 if (pEntry->fLastSecAccordingRSSI == TRUE) {
ca97b838
BZ
2214 pEntry->fLastSecAccordingRSSI = FALSE;
2215 pEntry->LastSecTxRateChangeAction = 0;
ec278fa2 2216 /* reset all OneSecTx counters */
ca97b838
BZ
2217 RESET_ONE_SEC_TX_CNT(pEntry);
2218
2219 continue;
91980990
GKH
2220 }
2221
96b3c83d
BZ
2222 do {
2223 BOOLEAN bTrainUpDown = FALSE;
1623267a 2224
96b3c83d 2225 pEntry->CurrTxRateStableTime++;
91980990 2226
ec278fa2 2227 /* downgrade TX quality if PER >= Rate-Down threshold */
96b3c83d 2228 if (TxErrorRatio >= TrainDown) {
ca97b838 2229 bTrainUpDown = TRUE;
96b3c83d
BZ
2230 pEntry->TxQuality[CurrRateIdx] =
2231 DRS_TX_QUALITY_WORST_BOUND;
91980990 2232 }
ec278fa2 2233 /* upgrade TX quality if PER <= Rate-Up threshold */
96b3c83d 2234 else if (TxErrorRatio <= TrainUp) {
ca97b838
BZ
2235 bTrainUpDown = TRUE;
2236 bUpgradeQuality = TRUE;
2237 if (pEntry->TxQuality[CurrRateIdx])
ec278fa2 2238 pEntry->TxQuality[CurrRateIdx]--; /* quality very good in CurrRate */
ca97b838
BZ
2239
2240 if (pEntry->TxRateUpPenalty)
96b3c83d 2241 pEntry->TxRateUpPenalty--;
ca97b838 2242 else if (pEntry->TxQuality[UpRateIdx])
ec278fa2 2243 pEntry->TxQuality[UpRateIdx]--; /* may improve next UP rate's quality */
91980990
GKH
2244 }
2245
51126deb 2246 pEntry->PER[CurrRateIdx] = (u8)TxErrorRatio;
91980990 2247
96b3c83d 2248 if (bTrainUpDown) {
ec278fa2 2249 /* perform DRS - consider TxRate Down first, then rate up. */
96b3c83d
BZ
2250 if ((CurrRateIdx != DownRateIdx)
2251 && (pEntry->TxQuality[CurrRateIdx] >=
2252 DRS_TX_QUALITY_WORST_BOUND)) {
ca97b838 2253 pEntry->CurrTxRateIndex = DownRateIdx;
96b3c83d
BZ
2254 } else if ((CurrRateIdx != UpRateIdx)
2255 && (pEntry->TxQuality[UpRateIdx] <=
2256 0)) {
ca97b838 2257 pEntry->CurrTxRateIndex = UpRateIdx;
91980990
GKH
2258 }
2259 }
ca97b838 2260 } while (FALSE);
91980990 2261
ec278fa2 2262 /* if rate-up happen, clear all bad history of all TX rates */
96b3c83d 2263 if (pEntry->CurrTxRateIndex > CurrRateIdx) {
ca97b838
BZ
2264 pEntry->CurrTxRateStableTime = 0;
2265 pEntry->TxRateUpPenalty = 0;
ec278fa2 2266 pEntry->LastSecTxRateChangeAction = 1; /* rate UP */
96b3c83d 2267 NdisZeroMemory(pEntry->TxQuality,
51126deb 2268 sizeof(u16)*
96b3c83d
BZ
2269 MAX_STEP_OF_TX_RATE_SWITCH);
2270 NdisZeroMemory(pEntry->PER,
51126deb 2271 sizeof(u8)*
96b3c83d 2272 MAX_STEP_OF_TX_RATE_SWITCH);
91980990 2273
ec278fa2
BZ
2274 /* */
2275 /* For TxRate fast train up */
2276 /* */
96b3c83d
BZ
2277 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2278 RTMPSetTimer(&pAd->StaCfg.
2279 StaQuickResponeForRateUpTimer,
2280 100);
91980990 2281
96b3c83d
BZ
2282 pAd->StaCfg.
2283 StaQuickResponeForRateUpTimerRunning = TRUE;
91980990 2284 }
ca97b838
BZ
2285 bTxRateChanged = TRUE;
2286 }
ec278fa2 2287 /* if rate-down happen, only clear DownRate's bad history */
96b3c83d 2288 else if (pEntry->CurrTxRateIndex < CurrRateIdx) {
ca97b838 2289 pEntry->CurrTxRateStableTime = 0;
ec278fa2
BZ
2290 pEntry->TxRateUpPenalty = 0; /* no penalty */
2291 pEntry->LastSecTxRateChangeAction = 2; /* rate DOWN */
ca97b838
BZ
2292 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2293 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
91980990 2294
ec278fa2
BZ
2295 /* */
2296 /* For TxRate fast train down */
2297 /* */
96b3c83d
BZ
2298 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning) {
2299 RTMPSetTimer(&pAd->StaCfg.
2300 StaQuickResponeForRateUpTimer,
2301 100);
91980990 2302
96b3c83d
BZ
2303 pAd->StaCfg.
2304 StaQuickResponeForRateUpTimerRunning = TRUE;
ca97b838
BZ
2305 }
2306 bTxRateChanged = TRUE;
96b3c83d 2307 } else {
ec278fa2 2308 pEntry->LastSecTxRateChangeAction = 0; /* rate no change */
ca97b838 2309 bTxRateChanged = FALSE;
91980990
GKH
2310 }
2311
ca97b838 2312 pEntry->LastTxOkCount = TxSuccess;
91980990 2313 {
51126deb 2314 u8 tmpTxRate;
ca97b838 2315
ec278fa2 2316 /* to fix tcp ack issue */
96b3c83d
BZ
2317 if (!bTxRateChanged
2318 && (pAd->RalinkCounters.OneSecReceivedByteCount >
2319 (pAd->RalinkCounters.
2320 OneSecTransmittedByteCount * 5))) {
ca97b838 2321 tmpTxRate = DownRateIdx;
96b3c83d
BZ
2322 DBGPRINT_RAW(RT_DEBUG_TRACE,
2323 ("DRS: Rx(%d) is 5 times larger than Tx(%d), use low rate (curr=%d, tmp=%d)\n",
2324 pAd->RalinkCounters.
2325 OneSecReceivedByteCount,
2326 pAd->RalinkCounters.
2327 OneSecTransmittedByteCount,
2328 pEntry->CurrTxRateIndex,
2329 tmpTxRate));
2330 } else {
ca97b838 2331 tmpTxRate = pEntry->CurrTxRateIndex;
91980990 2332 }
ca97b838 2333
96b3c83d 2334 pNextTxRate =
62eb734b 2335 (struct rt_rtmp_tx_rate_switch *) & pTable[(tmpTxRate + 1) *
96b3c83d 2336 5];
ca97b838 2337 }
96b3c83d 2338 if (bTxRateChanged && pNextTxRate) {
ca97b838 2339 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
91980990 2340 }
ec278fa2 2341 /* reset all OneSecTx counters */
ca97b838 2342 RESET_ONE_SEC_TX_CNT(pEntry);
91980990
GKH
2343 }
2344}
91980990 2345
ca97b838
BZ
2346/*
2347 ========================================================================
2348 Routine Description:
2349 Station side, Auto TxRate faster train up timer call back function.
2350
2351 Arguments:
2352 SystemSpecific1 - Not used.
2353 FunctionContext - Pointer to our Adapter context.
2354 SystemSpecific2 - Not used.
2355 SystemSpecific3 - Not used.
2356
2357 Return Value:
2358 None
2359
2360 ========================================================================
2361*/
51126deb
BZ
2362void StaQuickResponeForRateUpExec(void *SystemSpecific1,
2363 void *FunctionContext,
2364 void *SystemSpecific2,
2365 void *SystemSpecific3)
91980990 2366{
62eb734b 2367 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
51126deb
BZ
2368 u8 UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2369 unsigned long TxTotalCnt;
2370 unsigned long TxErrorRatio = 0;
ec278fa2 2371 BOOLEAN bTxRateChanged; /*, bUpgradeQuality = FALSE; */
62eb734b 2372 struct rt_rtmp_tx_rate_switch *pCurrTxRate, *pNextTxRate = NULL;
51126deb
BZ
2373 u8 *pTable;
2374 u8 TableSize = 0;
2375 u8 InitTxRateIdx = 0, TrainUp, TrainDown;
96b3c83d
BZ
2376 TX_STA_CNT1_STRUC StaTx1;
2377 TX_STA_CNT0_STRUC TxStaCnt0;
51126deb
BZ
2378 char Rssi, ratio;
2379 unsigned long TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
62eb734b 2380 struct rt_mac_table_entry *pEntry;
51126deb 2381 unsigned long i;
91980990 2382
ca97b838
BZ
2383 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2384
ec278fa2
BZ
2385 /* */
2386 /* walk through MAC table, see if need to change AP's TX rate toward each entry */
2387 /* */
96b3c83d 2388 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) {
ca97b838 2389 pEntry = &pAd->MacTab.Content[i];
91980990 2390
ec278fa2 2391 /* check if this entry need to switch rate automatically */
ca97b838
BZ
2392 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2393 continue;
91980990 2394
ca97b838
BZ
2395 if (INFRA_ON(pAd) && (i == 1))
2396 Rssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
2397 pAd->StaCfg.RssiSample.AvgRssi0,
2398 pAd->StaCfg.RssiSample.AvgRssi1,
2399 pAd->StaCfg.RssiSample.AvgRssi2);
ca97b838
BZ
2400 else
2401 Rssi = RTMPMaxRssi(pAd,
96b3c83d
BZ
2402 pEntry->RssiSample.AvgRssi0,
2403 pEntry->RssiSample.AvgRssi1,
2404 pEntry->RssiSample.AvgRssi2);
91980990 2405
ca97b838 2406 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
91980990 2407
96b3c83d
BZ
2408 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize,
2409 &InitTxRateIdx);
91980990 2410
ec278fa2 2411 /* decide the next upgrade rate and downgrade rate, if any */
96b3c83d 2412 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) {
ca97b838 2413 UpRateIdx = CurrRateIdx + 1;
96b3c83d
BZ
2414 DownRateIdx = CurrRateIdx - 1;
2415 } else if (CurrRateIdx == 0) {
ca97b838
BZ
2416 UpRateIdx = CurrRateIdx + 1;
2417 DownRateIdx = CurrRateIdx;
96b3c83d 2418 } else if (CurrRateIdx == (TableSize - 1)) {
ca97b838
BZ
2419 UpRateIdx = CurrRateIdx;
2420 DownRateIdx = CurrRateIdx - 1;
2421 }
91980990 2422
96b3c83d 2423 pCurrTxRate =
62eb734b 2424 (struct rt_rtmp_tx_rate_switch *) & pTable[(CurrRateIdx + 1) * 5];
96b3c83d
BZ
2425
2426 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) {
2427 TrainUp =
2428 (pCurrTxRate->TrainUp +
2429 (pCurrTxRate->TrainUp >> 1));
2430 TrainDown =
2431 (pCurrTxRate->TrainDown +
2432 (pCurrTxRate->TrainDown >> 1));
2433 } else {
2434 TrainUp = pCurrTxRate->TrainUp;
2435 TrainDown = pCurrTxRate->TrainDown;
ca97b838
BZ
2436 }
2437
96b3c83d 2438 if (pAd->MacTab.Size == 1) {
ec278fa2 2439 /* Update statistic counter */
ca97b838
BZ
2440 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2441 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2442
2443 TxRetransmit = StaTx1.field.TxRetransmit;
2444 TxSuccess = StaTx1.field.TxSuccess;
2445 TxFailCount = TxStaCnt0.field.TxFailCount;
2446 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2447
96b3c83d
BZ
2448 pAd->RalinkCounters.OneSecTxRetryOkCount +=
2449 StaTx1.field.TxRetransmit;
2450 pAd->RalinkCounters.OneSecTxNoRetryOkCount +=
2451 StaTx1.field.TxSuccess;
2452 pAd->RalinkCounters.OneSecTxFailCount +=
2453 TxStaCnt0.field.TxFailCount;
2454 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart +=
2455 StaTx1.field.TxSuccess;
2456 pAd->WlanCounters.RetryCount.u.LowPart +=
2457 StaTx1.field.TxRetransmit;
2458 pAd->WlanCounters.FailedCount.u.LowPart +=
2459 TxStaCnt0.field.TxFailCount;
ca97b838
BZ
2460
2461 if (TxTotalCnt)
96b3c83d
BZ
2462 TxErrorRatio =
2463 ((TxRetransmit +
2464 TxFailCount) * 100) / TxTotalCnt;
2465 } else {
ca97b838 2466 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
96b3c83d
BZ
2467 pEntry->OneSecTxRetryOkCount +
2468 pEntry->OneSecTxFailCount;
91980990 2469
ca97b838 2470 if (TxTotalCnt)
96b3c83d
BZ
2471 TxErrorRatio =
2472 ((pEntry->OneSecTxRetryOkCount +
2473 pEntry->OneSecTxFailCount) * 100) /
2474 TxTotalCnt;
ca97b838 2475 }
91980990 2476
ec278fa2
BZ
2477 /* */
2478 /* CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI */
2479 /* (criteria copied from RT2500 for Netopia case) */
2480 /* */
96b3c83d
BZ
2481 if (TxTotalCnt <= 12) {
2482 NdisZeroMemory(pAd->DrsCounters.TxQuality,
51126deb 2483 sizeof(u16)*
96b3c83d
BZ
2484 MAX_STEP_OF_TX_RATE_SWITCH);
2485 NdisZeroMemory(pAd->DrsCounters.PER,
51126deb 2486 sizeof(u8)*
96b3c83d
BZ
2487 MAX_STEP_OF_TX_RATE_SWITCH);
2488
2489 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2490 && (CurrRateIdx != DownRateIdx)) {
ca97b838 2491 pAd->CommonCfg.TxRateIndex = DownRateIdx;
96b3c83d
BZ
2492 pAd->DrsCounters.TxQuality[CurrRateIdx] =
2493 DRS_TX_QUALITY_WORST_BOUND;
2494 } else
2495 if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2496 2) && (CurrRateIdx != UpRateIdx)) {
ca97b838
BZ
2497 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2498 }
91980990 2499
96b3c83d
BZ
2500 DBGPRINT_RAW(RT_DEBUG_TRACE,
2501 ("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
ca97b838
BZ
2502 return;
2503 }
91980990 2504
96b3c83d 2505 do {
51126deb 2506 unsigned long OneSecTxNoRetryOKRationCount;
91980990 2507
ca97b838
BZ
2508 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2509 ratio = 5;
2510 else
2511 ratio = 4;
91980990 2512
ec278fa2 2513 /* downgrade TX quality if PER >= Rate-Down threshold */
96b3c83d
BZ
2514 if (TxErrorRatio >= TrainDown) {
2515 pAd->DrsCounters.TxQuality[CurrRateIdx] =
2516 DRS_TX_QUALITY_WORST_BOUND;
ca97b838 2517 }
91980990 2518
96b3c83d 2519 pAd->DrsCounters.PER[CurrRateIdx] =
51126deb 2520 (u8)TxErrorRatio;
91980990 2521
ca97b838 2522 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
91980990 2523
ec278fa2 2524 /* perform DRS - consider TxRate Down first, then rate up. */
96b3c83d
BZ
2525 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1)
2526 && (CurrRateIdx != DownRateIdx)) {
2527 if ((pAd->DrsCounters.LastTxOkCount + 2) >=
2528 OneSecTxNoRetryOKRationCount) {
2529 pAd->CommonCfg.TxRateIndex =
2530 DownRateIdx;
2531 pAd->DrsCounters.
2532 TxQuality[CurrRateIdx] =
2533 DRS_TX_QUALITY_WORST_BOUND;
ca97b838 2534
91980990 2535 }
91980990 2536
96b3c83d
BZ
2537 } else
2538 if ((pAd->DrsCounters.LastSecTxRateChangeAction ==
2539 2) && (CurrRateIdx != UpRateIdx)) {
2540 if ((TxErrorRatio >= 50)
2541 || (TxErrorRatio >= TrainDown)) {
91980990 2542
96b3c83d
BZ
2543 } else if ((pAd->DrsCounters.LastTxOkCount + 2)
2544 >= OneSecTxNoRetryOKRationCount) {
ca97b838 2545 pAd->CommonCfg.TxRateIndex = UpRateIdx;
91980990 2546 }
ca97b838 2547 }
96b3c83d 2548 } while (FALSE);
91980990 2549
ec278fa2 2550 /* if rate-up happen, clear all bad history of all TX rates */
96b3c83d 2551 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx) {
ca97b838 2552 pAd->DrsCounters.TxRateUpPenalty = 0;
96b3c83d 2553 NdisZeroMemory(pAd->DrsCounters.TxQuality,
51126deb 2554 sizeof(u16)*
96b3c83d
BZ
2555 MAX_STEP_OF_TX_RATE_SWITCH);
2556 NdisZeroMemory(pAd->DrsCounters.PER,
51126deb 2557 sizeof(u8)*
96b3c83d 2558 MAX_STEP_OF_TX_RATE_SWITCH);
ca97b838
BZ
2559 bTxRateChanged = TRUE;
2560 }
ec278fa2 2561 /* if rate-down happen, only clear DownRate's bad history */
96b3c83d
BZ
2562 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx) {
2563 DBGPRINT_RAW(RT_DEBUG_TRACE,
2564 ("QuickDRS: --TX rate from %d to %d \n",
2565 CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2566
ec278fa2 2567 pAd->DrsCounters.TxRateUpPenalty = 0; /* no penalty */
96b3c83d
BZ
2568 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] =
2569 0;
ca97b838
BZ
2570 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2571 bTxRateChanged = TRUE;
96b3c83d 2572 } else {
ca97b838
BZ
2573 bTxRateChanged = FALSE;
2574 }
91980990 2575
96b3c83d 2576 pNextTxRate =
62eb734b 2577 (struct rt_rtmp_tx_rate_switch *) &
96b3c83d
BZ
2578 pTable[(pAd->CommonCfg.TxRateIndex + 1) * 5];
2579 if (bTxRateChanged && pNextTxRate) {
ca97b838
BZ
2580 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2581 }
2582 }
2583}
2584
2585/*
2586 ==========================================================================
2587 Description:
2588 This routine is executed periodically inside MlmePeriodicExec() after
2589 association with an AP.
2590 It checks if StaCfg.Psm is consistent with user policy (recorded in
2591 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2592 there're some conditions to consider:
2593 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2594 the time when Mibss==TRUE
2595 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2596 if outgoing traffic available in TxRing or MgmtRing.
2597 Output:
2598 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
91980990 2599
ca97b838 2600 IRQL = DISPATCH_LEVEL
91980990 2601
ca97b838
BZ
2602 ==========================================================================
2603 */
62eb734b 2604void MlmeCheckPsmChange(struct rt_rtmp_adapter *pAd, unsigned long Now32)
ca97b838 2605{
51126deb 2606 unsigned long PowerMode;
91980990 2607
ec278fa2
BZ
2608 /* condition - */
2609 /* 1. Psm maybe ON only happen in INFRASTRUCTURE mode */
2610 /* 2. user wants either MAX_PSP or FAST_PSP */
2611 /* 3. but current psm is not in PWR_SAVE */
2612 /* 4. CNTL state machine is not doing SCANning */
2613 /* 5. no TX SUCCESS event for the past 1-sec period */
96b3c83d 2614 PowerMode = pAd->StaCfg.WindowsPowerMode;
91980990 2615
ca97b838 2616 if (INFRA_ON(pAd) &&
96b3c83d
BZ
2617 (PowerMode != Ndis802_11PowerModeCAM) &&
2618 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
ec278fa2 2619/* (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) */
96b3c83d
BZ
2620 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
2621 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP)
2622 /*&&
2623 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2624 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0) */
2625 ) {
2626 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2627 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
ca97b838 2628 RTMP_SET_PSM_BIT(pAd, PWR_SAVE);
96b3c83d
BZ
2629 if (!
2630 (pAd->CommonCfg.bAPSDCapable
2631 && pAd->CommonCfg.APEdcaParm.bAPSDCapable)) {
2632 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2633 } else {
2634 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
91980990 2635 }
96b3c83d 2636 }
91980990
GKH
2637}
2638
ec278fa2
BZ
2639/* IRQL = PASSIVE_LEVEL */
2640/* IRQL = DISPATCH_LEVEL */
62eb734b 2641void MlmeSetPsmBit(struct rt_rtmp_adapter *pAd, u16 psm)
ca97b838
BZ
2642{
2643 AUTO_RSP_CFG_STRUC csr4;
91980990 2644
ca97b838
BZ
2645 pAd->StaCfg.Psm = psm;
2646 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
96b3c83d 2647 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE) ? 1 : 0;
ca97b838
BZ
2648 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2649
2650 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2651}
2652
2653/*
2654 ==========================================================================
2655 Description:
2656 This routine calculates TxPER, RxPER of the past N-sec period. And
2657 according to the calculation result, ChannelQuality is calculated here
2658 to decide if current AP is still doing the job.
2659
2660 If ChannelQuality is not good, a ROAMing attempt may be tried later.
2661 Output:
2662 StaCfg.ChannelQuality - 0..100
2663
2664 IRQL = DISPATCH_LEVEL
2665
2666 NOTE: This routine decide channle quality based on RX CRC error ratio.
2667 Caller should make sure a function call to NICUpdateRawCounters(pAd)
2668 is performed right before this routine, so that this routine can decide
2669 channel quality based on the most up-to-date information
2670 ==========================================================================
91980990 2671 */
62eb734b
BZ
2672void MlmeCalculateChannelQuality(struct rt_rtmp_adapter *pAd,
2673 struct rt_mac_table_entry *pMacEntry, unsigned long Now32)
91980990 2674{
51126deb
BZ
2675 unsigned long TxOkCnt, TxCnt, TxPER, TxPRR;
2676 unsigned long RxCnt, RxPER;
2677 u8 NorRssi;
2678 char MaxRssi;
62eb734b 2679 struct rt_rssi_sample *pRssiSample = NULL;
51126deb
BZ
2680 u32 OneSecTxNoRetryOkCount = 0;
2681 u32 OneSecTxRetryOkCount = 0;
2682 u32 OneSecTxFailCount = 0;
2683 u32 OneSecRxOkCnt = 0;
2684 u32 OneSecRxFcsErrCnt = 0;
2685 unsigned long ChannelQuality = 0; /* 0..100, Channel Quality Indication for Roaming */
2686 unsigned long BeaconLostTime = pAd->StaCfg.BeaconLostTime;
91980990 2687
96b3c83d 2688 if (pAd->OpMode == OPMODE_STA) {
ca97b838 2689 pRssiSample = &pAd->StaCfg.RssiSample;
96b3c83d
BZ
2690 OneSecTxNoRetryOkCount =
2691 pAd->RalinkCounters.OneSecTxNoRetryOkCount;
ca97b838
BZ
2692 OneSecTxRetryOkCount = pAd->RalinkCounters.OneSecTxRetryOkCount;
2693 OneSecTxFailCount = pAd->RalinkCounters.OneSecTxFailCount;
2694 OneSecRxOkCnt = pAd->RalinkCounters.OneSecRxOkCnt;
2695 OneSecRxFcsErrCnt = pAd->RalinkCounters.OneSecRxFcsErrCnt;
91980990
GKH
2696 }
2697
ca97b838 2698 MaxRssi = RTMPMaxRssi(pAd, pRssiSample->LastRssi0,
96b3c83d 2699 pRssiSample->LastRssi1, pRssiSample->LastRssi2);
91980990 2700
ec278fa2
BZ
2701 /* */
2702 /* calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics */
2703 /* */
ca97b838
BZ
2704 TxOkCnt = OneSecTxNoRetryOkCount + OneSecTxRetryOkCount;
2705 TxCnt = TxOkCnt + OneSecTxFailCount;
96b3c83d 2706 if (TxCnt < 5) {
ca97b838
BZ
2707 TxPER = 0;
2708 TxPRR = 0;
96b3c83d 2709 } else {
ca97b838
BZ
2710 TxPER = (OneSecTxFailCount * 100) / TxCnt;
2711 TxPRR = ((TxCnt - OneSecTxNoRetryOkCount) * 100) / TxCnt;
2712 }
91980990 2713
ec278fa2
BZ
2714 /* */
2715 /* calculate RX PER - don't take RxPER into consideration if too few sample */
2716 /* */
ca97b838
BZ
2717 RxCnt = OneSecRxOkCnt + OneSecRxFcsErrCnt;
2718 if (RxCnt < 5)
2719 RxPER = 0;
2720 else
2721 RxPER = (OneSecRxFcsErrCnt * 100) / RxCnt;
91980990 2722
ec278fa2
BZ
2723 /* */
2724 /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER */
2725 /* */
2726 if ((pAd->OpMode == OPMODE_STA) && INFRA_ON(pAd) && (OneSecTxNoRetryOkCount < 2) && /* no heavy traffic */
96b3c83d
BZ
2727 ((pAd->StaCfg.LastBeaconRxTime + BeaconLostTime) < Now32)) {
2728 DBGPRINT(RT_DEBUG_TRACE,
2729 ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n",
2730 BeaconLostTime, TxOkCnt));
ca97b838 2731 ChannelQuality = 0;
96b3c83d 2732 } else {
ec278fa2 2733 /* Normalize Rssi */
ca97b838
BZ
2734 if (MaxRssi > -40)
2735 NorRssi = 100;
2736 else if (MaxRssi < -90)
2737 NorRssi = 0;
2738 else
2739 NorRssi = (MaxRssi + 90) * 2;
91980990 2740
ec278fa2 2741 /* ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) */
ca97b838 2742 ChannelQuality = (RSSI_WEIGHTING * NorRssi +
96b3c83d
BZ
2743 TX_WEIGHTING * (100 - TxPRR) +
2744 RX_WEIGHTING * (100 - RxPER)) / 100;
ca97b838 2745 }
6a28a69a 2746
ca97b838 2747 if (pAd->OpMode == OPMODE_STA)
96b3c83d
BZ
2748 pAd->Mlme.ChannelQuality =
2749 (ChannelQuality > 100) ? 100 : ChannelQuality;
91980990 2750
ca97b838 2751}
91980990 2752
ec278fa2 2753/* IRQL = DISPATCH_LEVEL */
62eb734b 2754void MlmeSetTxPreamble(struct rt_rtmp_adapter *pAd, u16 TxPreamble)
91980990 2755{
ca97b838 2756 AUTO_RSP_CFG_STRUC csr4;
91980990 2757
ec278fa2
BZ
2758 /* */
2759 /* Always use Long preamble before verifiation short preamble functionality works well. */
2760 /* Todo: remove the following line if short preamble functionality works */
2761 /* */
2762 /*TxPreamble = Rt802_11PreambleLong; */
ca97b838
BZ
2763
2764 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
96b3c83d
BZ
2765 if (TxPreamble == Rt802_11PreambleLong) {
2766 DBGPRINT(RT_DEBUG_TRACE,
51126deb 2767 ("MlmeSetTxPreamble (= long PREAMBLE)\n"));
ca97b838
BZ
2768 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2769 csr4.field.AutoResponderPreamble = 0;
96b3c83d 2770 } else {
ec278fa2 2771 /* NOTE: 1Mbps should always use long preamble */
96b3c83d 2772 DBGPRINT(RT_DEBUG_TRACE,
51126deb 2773 ("MlmeSetTxPreamble (= short PREAMBLE)\n"));
ca97b838
BZ
2774 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2775 csr4.field.AutoResponderPreamble = 1;
2776 }
2777
2778 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2779}
2780
2781/*
2782 ==========================================================================
2783 Description:
2784 Update basic rate bitmap
2785 ==========================================================================
2786 */
2787
62eb734b 2788void UpdateBasicRateBitmap(struct rt_rtmp_adapter *pAdapter)
ca97b838 2789{
51126deb 2790 int i, j;
96b3c83d 2791 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
51126deb
BZ
2792 u8 rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2793 u8 *sup_p = pAdapter->CommonCfg.SupRate;
2794 u8 *ext_p = pAdapter->CommonCfg.ExtRate;
2795 unsigned long bitmap = pAdapter->CommonCfg.BasicRateBitmap;
96b3c83d
BZ
2796
2797 /* if A mode, always use fix BasicRateBitMap */
ec278fa2 2798 /*if (pAdapter->CommonCfg.Channel == PHY_11A) */
ca97b838 2799 if (pAdapter->CommonCfg.Channel > 14)
96b3c83d
BZ
2800 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2801 /* End of if */
2802
2803 if (pAdapter->CommonCfg.BasicRateBitmap > 4095) {
2804 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2805 return;
2806 }
2807 /* End of if */
2808 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2809 sup_p[i] &= 0x7f;
2810 ext_p[i] &= 0x7f;
2811 } /* End of for */
2812
2813 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2814 if (bitmap & (1 << i)) {
2815 for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2816 if (sup_p[j] == rate[i])
2817 sup_p[j] |= 0x80;
2818 /* End of if */
2819 } /* End of for */
2820
2821 for (j = 0; j < MAX_LEN_OF_SUPPORTED_RATES; j++) {
2822 if (ext_p[j] == rate[i])
2823 ext_p[j] |= 0x80;
2824 /* End of if */
2825 } /* End of for */
2826 } /* End of if */
2827 } /* End of for */
2828} /* End of UpdateBasicRateBitmap */
91980990 2829
ec278fa2
BZ
2830/* IRQL = PASSIVE_LEVEL */
2831/* IRQL = DISPATCH_LEVEL */
2832/* bLinkUp is to identify the inital link speed. */
2833/* TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps. */
62eb734b 2834void MlmeUpdateTxRates(struct rt_rtmp_adapter *pAd, IN BOOLEAN bLinkUp, u8 apidx)
91980990 2835{
ca97b838 2836 int i, num;
51126deb
BZ
2837 u8 Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2838 u8 MinSupport = RATE_54;
2839 unsigned long BasicRateBitmap = 0;
2840 u8 CurrBasicRate = RATE_1;
2841 u8 *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
96b3c83d
BZ
2842 PHTTRANSMIT_SETTING pHtPhy = NULL;
2843 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2844 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2845 BOOLEAN *auto_rate_cur_p;
51126deb 2846 u8 HtMcs = MCS_AUTO;
91980990 2847
ec278fa2 2848 /* find max desired rate */
ca97b838 2849 UpdateBasicRateBitmap(pAd);
91980990 2850
ca97b838
BZ
2851 num = 0;
2852 auto_rate_cur_p = NULL;
96b3c83d
BZ
2853 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
2854 switch (pAd->CommonCfg.DesireRate[i] & 0x7f) {
2855 case 2:
2856 Rate = RATE_1;
2857 num++;
2858 break;
2859 case 4:
2860 Rate = RATE_2;
2861 num++;
2862 break;
2863 case 11:
2864 Rate = RATE_5_5;
2865 num++;
2866 break;
2867 case 22:
2868 Rate = RATE_11;
2869 num++;
2870 break;
2871 case 12:
2872 Rate = RATE_6;
2873 num++;
2874 break;
2875 case 18:
2876 Rate = RATE_9;
2877 num++;
2878 break;
2879 case 24:
2880 Rate = RATE_12;
2881 num++;
2882 break;
2883 case 36:
2884 Rate = RATE_18;
2885 num++;
2886 break;
2887 case 48:
2888 Rate = RATE_24;
2889 num++;
2890 break;
2891 case 72:
2892 Rate = RATE_36;
2893 num++;
2894 break;
2895 case 96:
2896 Rate = RATE_48;
2897 num++;
2898 break;
2899 case 108:
2900 Rate = RATE_54;
2901 num++;
2902 break;
ec278fa2 2903 /*default: Rate = RATE_1; break; */
ca97b838 2904 }
96b3c83d
BZ
2905 if (MaxDesire < Rate)
2906 MaxDesire = Rate;
91980990
GKH
2907 }
2908
ec278fa2
BZ
2909/*=========================================================================== */
2910/*=========================================================================== */
ca97b838 2911 {
96b3c83d
BZ
2912 pHtPhy = &pAd->StaCfg.HTPhyMode;
2913 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2914 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
91980990 2915
ca97b838 2916 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
96b3c83d 2917 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
91980990 2918
ca97b838 2919 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
96b3c83d
BZ
2920 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2921 (MaxDesire > RATE_11)) {
ca97b838
BZ
2922 MaxDesire = RATE_11;
2923 }
2924 }
91980990 2925
ca97b838
BZ
2926 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2927 pMinHtPhy->word = 0;
2928 pMaxHtPhy->word = 0;
2929 pHtPhy->word = 0;
91980990 2930
ec278fa2
BZ
2931 /* Auto rate switching is enabled only if more than one DESIRED RATES are */
2932 /* specified; otherwise disabled */
96b3c83d 2933 if (num <= 1) {
ec278fa2
BZ
2934 /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2935 /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */
ca97b838 2936 *auto_rate_cur_p = FALSE;
96b3c83d 2937 } else {
ec278fa2
BZ
2938 /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2939 /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */
ca97b838 2940 *auto_rate_cur_p = TRUE;
91980990
GKH
2941 }
2942
96b3c83d 2943 if (HtMcs != MCS_AUTO) {
ec278fa2
BZ
2944 /*OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2945 /*pAd->CommonCfg.bAutoTxRateSwitch = FALSE; */
ca97b838 2946 *auto_rate_cur_p = FALSE;
96b3c83d 2947 } else {
ec278fa2
BZ
2948 /*OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED); */
2949 /*pAd->CommonCfg.bAutoTxRateSwitch = TRUE; */
ca97b838 2950 *auto_rate_cur_p = TRUE;
91980990
GKH
2951 }
2952
96b3c83d 2953 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
ca97b838
BZ
2954 pSupRate = &pAd->StaActive.SupRate[0];
2955 pExtRate = &pAd->StaActive.ExtRate[0];
2956 SupRateLen = pAd->StaActive.SupRateLen;
2957 ExtRateLen = pAd->StaActive.ExtRateLen;
96b3c83d 2958 } else {
ca97b838
BZ
2959 pSupRate = &pAd->CommonCfg.SupRate[0];
2960 pExtRate = &pAd->CommonCfg.ExtRate[0];
2961 SupRateLen = pAd->CommonCfg.SupRateLen;
2962 ExtRateLen = pAd->CommonCfg.ExtRateLen;
91980990
GKH
2963 }
2964
ec278fa2 2965 /* find max supported rate */
96b3c83d
BZ
2966 for (i = 0; i < SupRateLen; i++) {
2967 switch (pSupRate[i] & 0x7f) {
2968 case 2:
2969 Rate = RATE_1;
2970 if (pSupRate[i] & 0x80)
2971 BasicRateBitmap |= 0x0001;
2972 break;
2973 case 4:
2974 Rate = RATE_2;
2975 if (pSupRate[i] & 0x80)
2976 BasicRateBitmap |= 0x0002;
2977 break;
2978 case 11:
2979 Rate = RATE_5_5;
2980 if (pSupRate[i] & 0x80)
2981 BasicRateBitmap |= 0x0004;
2982 break;
2983 case 22:
2984 Rate = RATE_11;
2985 if (pSupRate[i] & 0x80)
2986 BasicRateBitmap |= 0x0008;
2987 break;
2988 case 12:
2989 Rate = RATE_6; /*if (pSupRate[i] & 0x80) */
2990 BasicRateBitmap |= 0x0010;
2991 break;
2992 case 18:
2993 Rate = RATE_9;
2994 if (pSupRate[i] & 0x80)
2995 BasicRateBitmap |= 0x0020;
2996 break;
2997 case 24:
2998 Rate = RATE_12; /*if (pSupRate[i] & 0x80) */
2999 BasicRateBitmap |= 0x0040;
3000 break;
3001 case 36:
3002 Rate = RATE_18;
3003 if (pSupRate[i] & 0x80)
3004 BasicRateBitmap |= 0x0080;
3005 break;
3006 case 48:
3007 Rate = RATE_24; /*if (pSupRate[i] & 0x80) */
3008 BasicRateBitmap |= 0x0100;
3009 break;
3010 case 72:
3011 Rate = RATE_36;
3012 if (pSupRate[i] & 0x80)
3013 BasicRateBitmap |= 0x0200;
3014 break;
3015 case 96:
3016 Rate = RATE_48;
3017 if (pSupRate[i] & 0x80)
3018 BasicRateBitmap |= 0x0400;
3019 break;
3020 case 108:
3021 Rate = RATE_54;
3022 if (pSupRate[i] & 0x80)
3023 BasicRateBitmap |= 0x0800;
3024 break;
3025 default:
3026 Rate = RATE_1;
3027 break;
3028 }
3029 if (MaxSupport < Rate)
3030 MaxSupport = Rate;
3031
3032 if (MinSupport > Rate)
3033 MinSupport = Rate;
3034 }
3035
3036 for (i = 0; i < ExtRateLen; i++) {
3037 switch (pExtRate[i] & 0x7f) {
3038 case 2:
3039 Rate = RATE_1;
3040 if (pExtRate[i] & 0x80)
3041 BasicRateBitmap |= 0x0001;
3042 break;
3043 case 4:
3044 Rate = RATE_2;
3045 if (pExtRate[i] & 0x80)
3046 BasicRateBitmap |= 0x0002;
3047 break;
3048 case 11:
3049 Rate = RATE_5_5;
3050 if (pExtRate[i] & 0x80)
3051 BasicRateBitmap |= 0x0004;
3052 break;
3053 case 22:
3054 Rate = RATE_11;
3055 if (pExtRate[i] & 0x80)
3056 BasicRateBitmap |= 0x0008;
3057 break;
3058 case 12:
3059 Rate = RATE_6; /*if (pExtRate[i] & 0x80) */
3060 BasicRateBitmap |= 0x0010;
3061 break;
3062 case 18:
3063 Rate = RATE_9;
3064 if (pExtRate[i] & 0x80)
3065 BasicRateBitmap |= 0x0020;
3066 break;
3067 case 24:
3068 Rate = RATE_12; /*if (pExtRate[i] & 0x80) */
3069 BasicRateBitmap |= 0x0040;
3070 break;
3071 case 36:
3072 Rate = RATE_18;
3073 if (pExtRate[i] & 0x80)
3074 BasicRateBitmap |= 0x0080;
3075 break;
3076 case 48:
3077 Rate = RATE_24; /*if (pExtRate[i] & 0x80) */
3078 BasicRateBitmap |= 0x0100;
3079 break;
3080 case 72:
3081 Rate = RATE_36;
3082 if (pExtRate[i] & 0x80)
3083 BasicRateBitmap |= 0x0200;
3084 break;
3085 case 96:
3086 Rate = RATE_48;
3087 if (pExtRate[i] & 0x80)
3088 BasicRateBitmap |= 0x0400;
3089 break;
3090 case 108:
3091 Rate = RATE_54;
3092 if (pExtRate[i] & 0x80)
3093 BasicRateBitmap |= 0x0800;
3094 break;
3095 default:
3096 Rate = RATE_1;
3097 break;
3098 }
3099 if (MaxSupport < Rate)
3100 MaxSupport = Rate;
3101
3102 if (MinSupport > Rate)
3103 MinSupport = Rate;
3104 }
3105
3106 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
91980990 3107
ec278fa2
BZ
3108 /* bug fix */
3109 /* pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap; */
ca97b838 3110
ec278fa2
BZ
3111 /* calculate the exptected ACK rate for each TX rate. This info is used to caculate */
3112 /* the DURATION field of outgoing uniicast DATA/MGMT frame */
96b3c83d 3113 for (i = 0; i < MAX_LEN_OF_SUPPORTED_RATES; i++) {
ca97b838 3114 if (BasicRateBitmap & (0x01 << i))
51126deb 3115 CurrBasicRate = (u8)i;
ca97b838 3116 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
91980990
GKH
3117 }
3118
96b3c83d
BZ
3119 DBGPRINT(RT_DEBUG_TRACE,
3120 ("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n",
3121 RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
ec278fa2 3122 /* max tx rate = min {max desire rate, max supported rate} */
ca97b838
BZ
3123 if (MaxSupport < MaxDesire)
3124 pAd->CommonCfg.MaxTxRate = MaxSupport;
3125 else
3126 pAd->CommonCfg.MaxTxRate = MaxDesire;
91980990 3127
ca97b838 3128 pAd->CommonCfg.MinTxRate = MinSupport;
ec278fa2
BZ
3129 /* 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success */
3130 /* ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending */
3131 /* on average RSSI */
3132 /* 1. RSSI >= -70db, start at 54 Mbps (short distance) */
3133 /* 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) */
3134 /* 3. -75 > RSSI, start at 11 Mbps (long distance) */
96b3c83d 3135 if (*auto_rate_cur_p) {
ca97b838 3136 short dbm = 0;
91980990 3137
ca97b838 3138 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
91980990 3139
ca97b838
BZ
3140 if (bLinkUp == TRUE)
3141 pAd->CommonCfg.TxRate = RATE_24;
3142 else
3143 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
91980990 3144
ca97b838
BZ
3145 if (dbm < -75)
3146 pAd->CommonCfg.TxRate = RATE_11;
3147 else if (dbm < -70)
3148 pAd->CommonCfg.TxRate = RATE_24;
91980990 3149
ec278fa2 3150 /* should never exceed MaxTxRate (consider 11B-only mode) */
ca97b838
BZ
3151 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3152 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
91980990 3153
ca97b838 3154 pAd->CommonCfg.TxRateIndex = 0;
96b3c83d 3155 } else {
ca97b838 3156 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
96b3c83d
BZ
3157 pHtPhy->field.MCS =
3158 (pAd->CommonCfg.MaxTxRate >
3159 3) ? (pAd->CommonCfg.MaxTxRate -
3160 4) : pAd->CommonCfg.MaxTxRate;
3161 pHtPhy->field.MODE =
3162 (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3163
3164 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC =
3165 pHtPhy->field.STBC;
3166 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI =
3167 pHtPhy->field.ShortGI;
3168 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS =
3169 pHtPhy->field.MCS;
3170 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE =
3171 pHtPhy->field.MODE;
3172 }
3173
3174 if (pAd->CommonCfg.TxRate <= RATE_11) {
ca97b838
BZ
3175 pMaxHtPhy->field.MODE = MODE_CCK;
3176 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3177 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
96b3c83d 3178 } else {
ca97b838
BZ
3179 pMaxHtPhy->field.MODE = MODE_OFDM;
3180 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
96b3c83d
BZ
3181 if (pAd->CommonCfg.MinTxRate >= RATE_6
3182 && (pAd->CommonCfg.MinTxRate <= RATE_54)) {
3183 pMinHtPhy->field.MCS =
3184 OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];
3185 } else {
3186 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3187 }
91980990 3188 }
91980990 3189
ca97b838 3190 pHtPhy->word = (pMaxHtPhy->word);
96b3c83d
BZ
3191 if (bLinkUp && (pAd->OpMode == OPMODE_STA)) {
3192 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3193 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word =
3194 pMaxHtPhy->word;
3195 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word =
3196 pMinHtPhy->word;
3197 } else {
3198 switch (pAd->CommonCfg.PhyMode) {
3199 case PHY_11BG_MIXED:
3200 case PHY_11B:
3201 case PHY_11BGN_MIXED:
3202 pAd->CommonCfg.MlmeRate = RATE_1;
3203 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3204 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
91980990 3205
ec278fa2 3206/*#ifdef WIFI_TEST */
96b3c83d 3207 pAd->CommonCfg.RtsRate = RATE_11;
ec278fa2
BZ
3208/*#else */
3209/* pAd->CommonCfg.RtsRate = RATE_1; */
3210/*#endif */
96b3c83d
BZ
3211 break;
3212 case PHY_11G:
3213 case PHY_11A:
3214 case PHY_11AGN_MIXED:
3215 case PHY_11GN_MIXED:
3216 case PHY_11N_2_4G:
3217 case PHY_11AN_MIXED:
3218 case PHY_11N_5G:
3219 pAd->CommonCfg.MlmeRate = RATE_6;
3220 pAd->CommonCfg.RtsRate = RATE_6;
3221 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3222 pAd->CommonCfg.MlmeTransmit.field.MCS =
3223 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3224 break;
3225 case PHY_11ABG_MIXED:
3226 case PHY_11ABGN_MIXED:
3227 if (pAd->CommonCfg.Channel <= 14) {
3228 pAd->CommonCfg.MlmeRate = RATE_1;
3229 pAd->CommonCfg.RtsRate = RATE_1;
3230 pAd->CommonCfg.MlmeTransmit.field.MODE =
3231 MODE_CCK;
3232 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3233 } else {
ca97b838
BZ
3234 pAd->CommonCfg.MlmeRate = RATE_6;
3235 pAd->CommonCfg.RtsRate = RATE_6;
96b3c83d
BZ
3236 pAd->CommonCfg.MlmeTransmit.field.MODE =
3237 MODE_OFDM;
3238 pAd->CommonCfg.MlmeTransmit.field.MCS =
3239 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3240 }
3241 break;
ec278fa2 3242 default: /* error */
96b3c83d
BZ
3243 pAd->CommonCfg.MlmeRate = RATE_6;
3244 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3245 pAd->CommonCfg.MlmeTransmit.field.MCS =
3246 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3247 pAd->CommonCfg.RtsRate = RATE_1;
3248 break;
ca97b838 3249 }
ec278fa2
BZ
3250 /* */
3251 /* Keep Basic Mlme Rate. */
3252 /* */
96b3c83d
BZ
3253 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word =
3254 pAd->CommonCfg.MlmeTransmit.word;
ca97b838 3255 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
96b3c83d
BZ
3256 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3257 OfdmRateToRxwiMCS[RATE_24];
ca97b838 3258 else
96b3c83d
BZ
3259 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS =
3260 RATE_1;
ca97b838 3261 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
91980990 3262 }
91980990 3263
96b3c83d
BZ
3264 DBGPRINT(RT_DEBUG_TRACE,
3265 (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3266 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport],
3267 RateIdToMbps[pAd->CommonCfg.MaxTxRate],
3268 RateIdToMbps[pAd->CommonCfg.MinTxRate],
3269 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED) */
3270 *auto_rate_cur_p));
3271 DBGPRINT(RT_DEBUG_TRACE,
3272 (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3273 RateIdToMbps[pAd->CommonCfg.TxRate],
3274 RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3275 DBGPRINT(RT_DEBUG_TRACE,
3276 ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3277 pAd->CommonCfg.MlmeTransmit.word,
3278 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word,
3279 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word,
3280 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word));
91980990
GKH
3281}
3282
ca97b838
BZ
3283/*
3284 ==========================================================================
3285 Description:
3286 This function update HT Rate setting.
3287 Input Wcid value is valid for 2 case :
3288 1. it's used for Station in infra mode that copy AP rate to Mactable.
3289 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
91980990
GKH
3290
3291 IRQL = DISPATCH_LEVEL
3292
ca97b838 3293 ==========================================================================
91980990 3294 */
62eb734b 3295void MlmeUpdateHtTxRates(struct rt_rtmp_adapter *pAd, u8 apidx)
91980990 3296{
51126deb
BZ
3297 u8 StbcMcs; /*j, StbcMcs, bitmask; */
3298 char i; /* 3*3 */
62eb734b
BZ
3299 struct rt_ht_capability *pRtHtCap = NULL;
3300 struct rt_ht_phy_info *pActiveHtPhy = NULL;
51126deb
BZ
3301 unsigned long BasicMCS;
3302 u8 j, bitmask;
62eb734b 3303 struct rt_ht_phy_info *pDesireHtPhy = NULL;
96b3c83d
BZ
3304 PHTTRANSMIT_SETTING pHtPhy = NULL;
3305 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3306 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3307 BOOLEAN *auto_rate_cur_p;
91980990 3308
96b3c83d 3309 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates===> \n"));
91980990 3310
ca97b838 3311 auto_rate_cur_p = NULL;
91980990 3312
ca97b838 3313 {
96b3c83d
BZ
3314 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3315 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3316 pHtPhy = &pAd->StaCfg.HTPhyMode;
3317 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3318 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
91980990 3319
ca97b838
BZ
3320 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3321 }
91980990 3322
96b3c83d 3323 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA)) {
ca97b838
BZ
3324 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3325 return;
91980990 3326
ca97b838
BZ
3327 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3328 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
51126deb 3329 StbcMcs = (u8)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
96b3c83d
BZ
3330 BasicMCS =
3331 pAd->MlmeAux.AddHtInfo.MCSSet[0] +
3332 (pAd->MlmeAux.AddHtInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3333 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3334 && (pAd->Antenna.field.TxPath == 2))
ca97b838
BZ
3335 pMaxHtPhy->field.STBC = STBC_USE;
3336 else
3337 pMaxHtPhy->field.STBC = STBC_NONE;
96b3c83d 3338 } else {
ca97b838
BZ
3339 if (pDesireHtPhy->bHtEnable == FALSE)
3340 return;
91980990 3341
ca97b838 3342 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
51126deb 3343 StbcMcs = (u8)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
96b3c83d
BZ
3344 BasicMCS =
3345 pAd->CommonCfg.AddHTInfo.MCSSet[0] +
3346 (pAd->CommonCfg.AddHTInfo.MCSSet[1] << 8) + (StbcMcs << 16);
3347 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC)
3348 && (pAd->Antenna.field.TxPath == 2))
ca97b838
BZ
3349 pMaxHtPhy->field.STBC = STBC_USE;
3350 else
3351 pMaxHtPhy->field.STBC = STBC_NONE;
3352 }
91980990 3353
ec278fa2 3354 /* Decide MAX ht rate. */
ca97b838
BZ
3355 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3356 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3357 else
3358 pMaxHtPhy->field.MODE = MODE_HTMIX;
91980990 3359
96b3c83d
BZ
3360 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth)
3361 && (pRtHtCap->ChannelWidth))
ca97b838
BZ
3362 pMaxHtPhy->field.BW = BW_40;
3363 else
3364 pMaxHtPhy->field.BW = BW_20;
91980990 3365
96b3c83d
BZ
3366 if (pMaxHtPhy->field.BW == BW_20)
3367 pMaxHtPhy->field.ShortGI =
3368 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->
3369 ShortGIfor20);
ca97b838 3370 else
96b3c83d
BZ
3371 pMaxHtPhy->field.ShortGI =
3372 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->
3373 ShortGIfor40);
91980990 3374
96b3c83d 3375 if (pDesireHtPhy->MCSSet[4] != 0) {
ca97b838
BZ
3376 pMaxHtPhy->field.MCS = 32;
3377 }
91980990 3378
ec278fa2 3379 for (i = 23; i >= 0; i--) /* 3*3 */
ca97b838 3380 {
96b3c83d
BZ
3381 j = i / 8;
3382 bitmask = (1 << (i - (j * 8)));
91980990 3383
96b3c83d
BZ
3384 if ((pActiveHtPhy->MCSSet[j] & bitmask)
3385 && (pDesireHtPhy->MCSSet[j] & bitmask)) {
ca97b838
BZ
3386 pMaxHtPhy->field.MCS = i;
3387 break;
96b3c83d 3388 }
91980990 3389
96b3c83d 3390 if (i == 0)
ca97b838
BZ
3391 break;
3392 }
91980990 3393
ec278fa2 3394 /* Copy MIN ht rate. rt2860??? */
ca97b838
BZ
3395 pMinHtPhy->field.BW = BW_20;
3396 pMinHtPhy->field.MCS = 0;
3397 pMinHtPhy->field.STBC = 0;
3398 pMinHtPhy->field.ShortGI = 0;
ec278fa2 3399 /*If STA assigns fixed rate. update to fixed here. */
96b3c83d
BZ
3400 if ((pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff)) {
3401 if (pDesireHtPhy->MCSSet[4] != 0) {
ca97b838
BZ
3402 pMaxHtPhy->field.MCS = 32;
3403 pMinHtPhy->field.MCS = 32;
96b3c83d
BZ
3404 DBGPRINT(RT_DEBUG_TRACE,
3405 ("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",
3406 pMinHtPhy->field.MCS));
3407 }
ca97b838 3408
51126deb 3409 for (i = 23; (char)i >= 0; i--) /* 3*3 */
91980990 3410 {
96b3c83d
BZ
3411 j = i / 8;
3412 bitmask = (1 << (i - (j * 8)));
3413 if ((pDesireHtPhy->MCSSet[j] & bitmask)
3414 && (pActiveHtPhy->MCSSet[j] & bitmask)) {
ca97b838
BZ
3415 pMaxHtPhy->field.MCS = i;
3416 pMinHtPhy->field.MCS = i;
3417 break;
96b3c83d
BZ
3418 }
3419 if (i == 0)
ca97b838 3420 break;
96b3c83d 3421 }
ca97b838 3422 }
ca97b838 3423
ec278fa2 3424 /* Decide ht rate */
ca97b838
BZ
3425 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3426 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3427 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3428 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3429 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3430
ec278fa2 3431 /* use default now. rt2860 */
ca97b838
BZ
3432 if (pDesireHtPhy->MCSSet[0] != 0xff)
3433 *auto_rate_cur_p = FALSE;
3434 else
3435 *auto_rate_cur_p = TRUE;
3436
96b3c83d
BZ
3437 DBGPRINT(RT_DEBUG_TRACE,
3438 (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n",
3439 pAd->CommonCfg.DesiredHtPhy.AmsduSize));
3440 DBGPRINT(RT_DEBUG_TRACE,
3441 ("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n",
3442 pActiveHtPhy->MCSSet[0], pHtPhy->field.MCS, pHtPhy->field.BW,
3443 pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3444 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateHtTxRates<=== \n"));
ca97b838
BZ
3445}
3446
62eb734b 3447void BATableInit(struct rt_rtmp_adapter *pAd, struct rt_ba_table *Tab)
ca97b838
BZ
3448{
3449 int i;
3450
3451 Tab->numAsOriginator = 0;
3452 Tab->numAsRecipient = 0;
3453 Tab->numDoneOriginator = 0;
3454 NdisAllocateSpinLock(&pAd->BATabLock);
96b3c83d 3455 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) {
ca97b838
BZ
3456 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3457 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3458 }
96b3c83d 3459 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) {
ca97b838 3460 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
91980990 3461 }
ca97b838 3462}
91980990 3463
ec278fa2 3464/* IRQL = DISPATCH_LEVEL */
62eb734b 3465void MlmeRadioOff(struct rt_rtmp_adapter *pAd)
ca97b838
BZ
3466{
3467 RTMP_MLME_RADIO_OFF(pAd);
3468}
3469
ec278fa2 3470/* IRQL = DISPATCH_LEVEL */
62eb734b 3471void MlmeRadioOn(struct rt_rtmp_adapter *pAd)
ca97b838
BZ
3472{
3473 RTMP_MLME_RADIO_ON(pAd);
91980990 3474}
91980990 3475
ec278fa2
BZ
3476/* =========================================================================================== */
3477/* bss_table.c */
3478/* =========================================================================================== */
91980990 3479
ca97b838
BZ
3480/*! \brief initialize BSS table
3481 * \param p_tab pointer to the table
3482 * \return none
3483 * \pre
91980990
GKH
3484 * \post
3485
3486 IRQL = PASSIVE_LEVEL
ca97b838 3487 IRQL = DISPATCH_LEVEL
91980990
GKH
3488
3489 */
62eb734b 3490void BssTableInit(struct rt_bss_table *Tab)
91980990 3491{
ca97b838 3492 int i;
91980990 3493
ca97b838 3494 Tab->BssNr = 0;
96b3c83d
BZ
3495 Tab->BssOverlapNr = 0;
3496 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) {
62eb734b 3497 NdisZeroMemory(&Tab->BssEntry[i], sizeof(struct rt_bss_entry));
ec278fa2 3498 Tab->BssEntry[i].Rssi = -127; /* initial the rssi as a minimum value */
ca97b838
BZ
3499 }
3500}
91980990 3501
ca97b838
BZ
3502/*! \brief search the BSS table by SSID
3503 * \param p_tab pointer to the bss table
3504 * \param ssid SSID string
3505 * \return index of the table, BSS_NOT_FOUND if not in the table
3506 * \pre
3507 * \post
3508 * \note search by sequential search
3509
3510 IRQL = DISPATCH_LEVEL
3511
3512 */
62eb734b 3513unsigned long BssTableSearch(struct rt_bss_table *Tab, u8 *pBssid, u8 Channel)
ca97b838 3514{
51126deb 3515 u8 i;
ca97b838 3516
96b3c83d 3517 for (i = 0; i < Tab->BssNr; i++) {
ec278fa2
BZ
3518 /* */
3519 /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3520 /* We should distinguish this case. */
3521 /* */
ca97b838 3522 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
96b3c83d
BZ
3523 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3524 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) {
ca97b838 3525 return i;
91980990
GKH
3526 }
3527 }
51126deb 3528 return (unsigned long)BSS_NOT_FOUND;
91980990
GKH
3529}
3530
62eb734b 3531unsigned long BssSsidTableSearch(struct rt_bss_table *Tab,
51126deb
BZ
3532 u8 *pBssid,
3533 u8 *pSsid, u8 SsidLen, u8 Channel)
ca97b838 3534{
51126deb 3535 u8 i;
91980990 3536
96b3c83d 3537 for (i = 0; i < Tab->BssNr; i++) {
ec278fa2
BZ
3538 /* */
3539 /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. */
3540 /* We should distinguish this case. */
3541 /* */
ca97b838 3542 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
96b3c83d
BZ
3543 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3544 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3545 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3546 Tab->BssEntry[i].SsidLen)) {
ca97b838
BZ
3547 return i;
3548 }
3549 }
51126deb 3550 return (unsigned long)BSS_NOT_FOUND;
ca97b838 3551}
91980990 3552
62eb734b 3553unsigned long BssTableSearchWithSSID(struct rt_bss_table *Tab,
51126deb
BZ
3554 u8 *Bssid,
3555 u8 *pSsid,
3556 u8 SsidLen, u8 Channel)
91980990 3557{
51126deb 3558 u8 i;
91980990 3559
96b3c83d 3560 for (i = 0; i < Tab->BssNr; i++) {
ca97b838 3561 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
96b3c83d
BZ
3562 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3563 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3564 (SSID_EQUAL
3565 (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3566 Tab->BssEntry[i].SsidLen)
3567 || (NdisEqualMemory(pSsid, ZeroSsid, SsidLen))
3568 ||
3569 (NdisEqualMemory
3570 (Tab->BssEntry[i].Ssid, ZeroSsid,
3571 Tab->BssEntry[i].SsidLen)))) {
ca97b838
BZ
3572 return i;
3573 }
91980990 3574 }
51126deb 3575 return (unsigned long)BSS_NOT_FOUND;
91980990
GKH
3576}
3577
62eb734b 3578unsigned long BssSsidTableSearchBySSID(struct rt_bss_table *Tab,
51126deb 3579 u8 *pSsid, u8 SsidLen)
ca97b838 3580{
51126deb 3581 u8 i;
91980990 3582
96b3c83d
BZ
3583 for (i = 0; i < Tab->BssNr; i++) {
3584 if (SSID_EQUAL
3585 (pSsid, SsidLen, Tab->BssEntry[i].Ssid,
3586 Tab->BssEntry[i].SsidLen)) {
ca97b838 3587 return i;
96b3c83d 3588 }
ca97b838 3589 }
51126deb 3590 return (unsigned long)BSS_NOT_FOUND;
ca97b838
BZ
3591}
3592
ec278fa2 3593/* IRQL = DISPATCH_LEVEL */
62eb734b 3594void BssTableDeleteEntry(struct rt_bss_table *Tab,
51126deb 3595 u8 *pBssid, u8 Channel)
91980990 3596{
51126deb 3597 u8 i, j;
ca97b838 3598
96b3c83d 3599 for (i = 0; i < Tab->BssNr; i++) {
ca97b838 3600 if ((Tab->BssEntry[i].Channel == Channel) &&
96b3c83d
BZ
3601 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))) {
3602 for (j = i; j < Tab->BssNr - 1; j++) {
3603 NdisMoveMemory(&(Tab->BssEntry[j]),
3604 &(Tab->BssEntry[j + 1]),
62eb734b 3605 sizeof(struct rt_bss_entry));
ca97b838 3606 }
96b3c83d 3607 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]),
62eb734b 3608 sizeof(struct rt_bss_entry));
ca97b838
BZ
3609 Tab->BssNr -= 1;
3610 return;
3611 }
3612 }
91980990
GKH
3613}
3614
3615/*
ca97b838
BZ
3616 ========================================================================
3617 Routine Description:
3618 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3619
3620 Arguments:
3621 // IRQL = DISPATCH_LEVEL
3622 ========================================================================
3623*/
62eb734b
BZ
3624void BATableDeleteORIEntry(struct rt_rtmp_adapter *pAd,
3625 struct rt_ba_ori_entry *pBAORIEntry)
91980990 3626{
91980990 3627
96b3c83d 3628 if (pBAORIEntry->ORI_BA_Status != Originator_NONE) {
ca97b838 3629 NdisAcquireSpinLock(&pAd->BATabLock);
96b3c83d 3630 if (pBAORIEntry->ORI_BA_Status == Originator_Done) {
ca97b838 3631 pAd->BATable.numAsOriginator -= 1;
96b3c83d
BZ
3632 DBGPRINT(RT_DEBUG_TRACE,
3633 ("BATableDeleteORIEntry numAsOriginator= %ld\n",
3634 pAd->BATable.numAsRecipient));
ec278fa2 3635 /* Erase Bitmap flag. */
ca97b838 3636 }
ec278fa2
BZ
3637 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1 << (pBAORIEntry->TID))); /* If STA mode, erase flag here */
3638 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; /* If STA mode, erase flag here */
ca97b838
BZ
3639 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3640 pBAORIEntry->Token = 1;
ec278fa2 3641 /* Not clear Sequence here. */
ca97b838
BZ
3642 NdisReleaseSpinLock(&pAd->BATabLock);
3643 }
3644}
91980990 3645
ca97b838
BZ
3646/*! \brief
3647 * \param
3648 * \return
3649 * \pre
3650 * \post
91980990 3651
ca97b838 3652 IRQL = DISPATCH_LEVEL
91980990 3653
91980990 3654 */
62eb734b 3655void BssEntrySet(struct rt_rtmp_adapter *pAd, struct rt_bss_entry *pBss, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * pCfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */
51126deb
BZ
3656 u8 HtCapabilityLen,
3657 u8 AddHtInfoLen,
3658 u8 NewExtChanOffset,
3659 u8 Channel,
3660 char Rssi,
96b3c83d 3661 IN LARGE_INTEGER TimeStamp,
51126deb 3662 u8 CkipFlag,
62eb734b
BZ
3663 struct rt_edca_parm *pEdcaParm,
3664 struct rt_qos_capability_parm *pQosCapability,
3665 struct rt_qbss_load_parm *pQbssLoad,
3666 u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
91980990 3667{
ca97b838 3668 COPY_MAC_ADDR(pBss->Bssid, pBssid);
ec278fa2 3669 /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID */
ca97b838 3670 pBss->Hidden = 1;
96b3c83d 3671 if (SsidLen > 0) {
ec278fa2
BZ
3672 /* For hidden SSID AP, it might send beacon with SSID len equal to 0 */
3673 /* Or send beacon /probe response with SSID len matching real SSID length, */
3674 /* but SSID is all zero. such as "00-00-00-00" with length 4. */
3675 /* We have to prevent this case overwrite correct table */
96b3c83d
BZ
3676 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0) {
3677 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
ca97b838
BZ
3678 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3679 pBss->SsidLen = SsidLen;
3680 pBss->Hidden = 0;
3681 }
96b3c83d 3682 } else
ca97b838
BZ
3683 pBss->SsidLen = 0;
3684 pBss->BssType = BssType;
3685 pBss->BeaconPeriod = BeaconPeriod;
96b3c83d
BZ
3686 if (BssType == BSS_INFRA) {
3687 if (pCfParm->bValid) {
ca97b838
BZ
3688 pBss->CfpCount = pCfParm->CfpCount;
3689 pBss->CfpPeriod = pCfParm->CfpPeriod;
3690 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3691 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3692 }
96b3c83d 3693 } else {
ca97b838
BZ
3694 pBss->AtimWin = AtimWin;
3695 }
91980990 3696
ca97b838 3697 pBss->CapabilityInfo = CapabilityInfo;
ec278fa2
BZ
3698 /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES */
3699 /* Combine with AuthMode, they will decide the connection methods. */
ca97b838
BZ
3700 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3701 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3702 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3703 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3704 else
96b3c83d
BZ
3705 NdisMoveMemory(pBss->SupRate, SupRate,
3706 MAX_LEN_OF_SUPPORTED_RATES);
ca97b838
BZ
3707 pBss->SupRateLen = SupRateLen;
3708 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3709 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3710 pBss->NewExtChanOffset = NewExtChanOffset;
3711 pBss->ExtRateLen = ExtRateLen;
3712 pBss->Channel = Channel;
3713 pBss->CentralChannel = Channel;
3714 pBss->Rssi = Rssi;
ec278fa2 3715 /* Update CkipFlag. if not exists, the value is 0x0 */
ca97b838 3716 pBss->CkipFlag = CkipFlag;
91980990 3717
ec278fa2 3718 /* New for microsoft Fixed IEs */
ca97b838
BZ
3719 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3720 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3721 pBss->FixIEs.Capabilities = CapabilityInfo;
91980990 3722
ec278fa2 3723 /* New for microsoft Variable IEs */
96b3c83d 3724 if (LengthVIE != 0) {
ca97b838
BZ
3725 pBss->VarIELen = LengthVIE;
3726 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
96b3c83d 3727 } else {
ca97b838
BZ
3728 pBss->VarIELen = 0;
3729 }
91980990 3730
ca97b838
BZ
3731 pBss->AddHtInfoLen = 0;
3732 pBss->HtCapabilityLen = 0;
96b3c83d 3733 if (HtCapabilityLen > 0) {
ca97b838 3734 pBss->HtCapabilityLen = HtCapabilityLen;
96b3c83d
BZ
3735 NdisMoveMemory(&pBss->HtCapability, pHtCapability,
3736 HtCapabilityLen);
3737 if (AddHtInfoLen > 0) {
ca97b838 3738 pBss->AddHtInfoLen = AddHtInfoLen;
96b3c83d
BZ
3739 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo,
3740 AddHtInfoLen);
3741
3742 if ((pAddHtInfo->ControlChan > 2)
3743 && (pAddHtInfo->AddHtInfo.ExtChanOffset ==
3744 EXTCHA_BELOW)
3745 && (pHtCapability->HtCapInfo.ChannelWidth ==
3746 BW_40)) {
3747 pBss->CentralChannel =
3748 pAddHtInfo->ControlChan - 2;
3749 } else
3750 if ((pAddHtInfo->AddHtInfo.ExtChanOffset ==
3751 EXTCHA_ABOVE)
3752 && (pHtCapability->HtCapInfo.ChannelWidth ==
3753 BW_40)) {
3754 pBss->CentralChannel =
3755 pAddHtInfo->ControlChan + 2;
3756 }
91980990 3757 }
91980990
GKH
3758 }
3759
ca97b838 3760 BssCipherParse(pBss);
91980990 3761
ec278fa2 3762 /* new for QOS */
ca97b838 3763 if (pEdcaParm)
62eb734b 3764 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(struct rt_edca_parm));
ca97b838
BZ
3765 else
3766 pBss->EdcaParm.bValid = FALSE;
3767 if (pQosCapability)
96b3c83d 3768 NdisMoveMemory(&pBss->QosCapability, pQosCapability,
62eb734b 3769 sizeof(struct rt_qos_capability_parm));
ca97b838
BZ
3770 else
3771 pBss->QosCapability.bValid = FALSE;
3772 if (pQbssLoad)
96b3c83d 3773 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad,
62eb734b 3774 sizeof(struct rt_qbss_load_parm));
ca97b838
BZ
3775 else
3776 pBss->QbssLoad.bValid = FALSE;
3777
3778 {
62eb734b 3779 struct rt_eid * pEid;
51126deb 3780 u16 Length = 0;
ca97b838
BZ
3781
3782 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3783 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
62eb734b 3784 pEid = (struct rt_eid *) pVIE;
51126deb 3785 while ((Length + 2 + (u16)pEid->Len) <= LengthVIE) {
96b3c83d
BZ
3786 switch (pEid->Eid) {
3787 case IE_WPA:
3788 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) {
3789 if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3790 pBss->WpaIE.IELen = 0;
3791 break;
91980990 3792 }
96b3c83d
BZ
3793 pBss->WpaIE.IELen = pEid->Len + 2;
3794 NdisMoveMemory(pBss->WpaIE.IE, pEid,
3795 pBss->WpaIE.IELen);
91980990
GKH
3796 }
3797 break;
96b3c83d
BZ
3798 case IE_RSN:
3799 if (NdisEqualMemory
3800 (pEid->Octet + 2, RSN_OUI, 3)) {
3801 if ((pEid->Len + 2) > MAX_CUSTOM_LEN) {
3802 pBss->RsnIE.IELen = 0;
3803 break;
91980990 3804 }
96b3c83d
BZ
3805 pBss->RsnIE.IELen = pEid->Len + 2;
3806 NdisMoveMemory(pBss->RsnIE.IE, pEid,
3807 pBss->RsnIE.IELen);
91980990
GKH
3808 }
3809 break;
96b3c83d 3810 }
51126deb 3811 Length = Length + 2 + (u16)pEid->Len; /* Eid[1] + Len[1]+ content[Len] */
62eb734b 3812 pEid = (struct rt_eid *) ((u8 *) pEid + 2 + pEid->Len);
ca97b838 3813 }
91980990 3814 }
91980990
GKH
3815}
3816
ca97b838
BZ
3817/*!
3818 * \brief insert an entry into the bss table
3819 * \param p_tab The BSS table
3820 * \param Bssid BSSID
3821 * \param ssid SSID
3822 * \param ssid_len Length of SSID
3823 * \param bss_type
3824 * \param beacon_period
3825 * \param timestamp
3826 * \param p_cf
3827 * \param atim_win
3828 * \param cap
3829 * \param rates
3830 * \param rates_len
3831 * \param channel_idx
3832 * \return none
3833 * \pre
3834 * \post
3835 * \note If SSID is identical, the old entry will be replaced by the new one
91980990 3836
ca97b838
BZ
3837 IRQL = DISPATCH_LEVEL
3838
3839 */
62eb734b 3840unsigned long BssTableSetEntry(struct rt_rtmp_adapter *pAd, struct rt_bss_table *Tab, u8 *pBssid, char Ssid[], u8 SsidLen, u8 BssType, u16 BeaconPeriod, struct rt_cf_parm * CfParm, u16 AtimWin, u16 CapabilityInfo, u8 SupRate[], u8 SupRateLen, u8 ExtRate[], u8 ExtRateLen, struct rt_ht_capability_ie * pHtCapability, struct rt_add_ht_info_ie * pAddHtInfo, /* AP might use this additional ht info IE */
51126deb
BZ
3841 u8 HtCapabilityLen,
3842 u8 AddHtInfoLen,
3843 u8 NewExtChanOffset,
3844 u8 ChannelNo,
3845 char Rssi,
96b3c83d 3846 IN LARGE_INTEGER TimeStamp,
51126deb 3847 u8 CkipFlag,
62eb734b
BZ
3848 struct rt_edca_parm *pEdcaParm,
3849 struct rt_qos_capability_parm *pQosCapability,
3850 struct rt_qbss_load_parm *pQbssLoad,
3851 u16 LengthVIE, struct rt_ndis_802_11_variable_ies *pVIE)
91980990 3852{
51126deb 3853 unsigned long Idx;
91980990 3854
96b3c83d 3855 Idx =
51126deb 3856 BssTableSearchWithSSID(Tab, pBssid, (u8 *) Ssid, SsidLen,
96b3c83d
BZ
3857 ChannelNo);
3858 if (Idx == BSS_NOT_FOUND) {
3859 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) {
ec278fa2
BZ
3860 /* */
3861 /* It may happen when BSS Table was full. */
3862 /* The desired AP will not be added into BSS Table */
3863 /* In this case, if we found the desired AP then overwrite BSS Table. */
3864 /* */
96b3c83d
BZ
3865 if (!OPSTATUS_TEST_FLAG
3866 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) {
3867 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid)
3868 || SSID_EQUAL(pAd->MlmeAux.Ssid,
3869 pAd->MlmeAux.SsidLen, Ssid,
3870 SsidLen)) {
ca97b838 3871 Idx = Tab->BssOverlapNr;
96b3c83d
BZ
3872 BssEntrySet(pAd, &Tab->BssEntry[Idx],
3873 pBssid, Ssid, SsidLen,
3874 BssType, BeaconPeriod,
3875 CfParm, AtimWin,
3876 CapabilityInfo, SupRate,
3877 SupRateLen, ExtRate,
3878 ExtRateLen, pHtCapability,
3879 pAddHtInfo, HtCapabilityLen,
3880 AddHtInfoLen,
3881 NewExtChanOffset, ChannelNo,
3882 Rssi, TimeStamp, CkipFlag,
3883 pEdcaParm, pQosCapability,
3884 pQbssLoad, LengthVIE, pVIE);
3885 Tab->BssOverlapNr =
3886 (Tab->BssOverlapNr++) %
3887 MAX_LEN_OF_BSS_TABLE;
91980990 3888 }
ca97b838 3889 return Idx;
96b3c83d
BZ
3890 } else {
3891 return BSS_NOT_FOUND;
3892 }
91980990 3893 }
ca97b838 3894 Idx = Tab->BssNr;
96b3c83d
BZ
3895 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen,
3896 BssType, BeaconPeriod, CfParm, AtimWin,
3897 CapabilityInfo, SupRate, SupRateLen, ExtRate,
3898 ExtRateLen, pHtCapability, pAddHtInfo,
3899 HtCapabilityLen, AddHtInfoLen, NewExtChanOffset,
3900 ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm,
3901 pQosCapability, pQbssLoad, LengthVIE, pVIE);
ca97b838 3902 Tab->BssNr++;
96b3c83d 3903 } else {
ca97b838 3904 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
96b3c83d
BZ
3905 if ((SSID_EQUAL
3906 (Ssid, SsidLen, Tab->BssEntry[Idx].Ssid,
3907 Tab->BssEntry[Idx].SsidLen))
3908 ||
3909 (NdisEqualMemory
3910 (Tab->BssEntry[Idx].Ssid, ZeroSsid,
3911 Tab->BssEntry[Idx].SsidLen))) {
3912 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid,
3913 SsidLen, BssType, BeaconPeriod, CfParm,
3914 AtimWin, CapabilityInfo, SupRate,
3915 SupRateLen, ExtRate, ExtRateLen,
3916 pHtCapability, pAddHtInfo, HtCapabilityLen,
3917 AddHtInfoLen, NewExtChanOffset, ChannelNo,
3918 Rssi, TimeStamp, CkipFlag, pEdcaParm,
3919 pQosCapability, pQbssLoad, LengthVIE, pVIE);
91980990
GKH
3920 }
3921 }
91980990 3922
ca97b838
BZ
3923 return Idx;
3924}
59fe2d89 3925
ec278fa2 3926/* IRQL = DISPATCH_LEVEL */
62eb734b
BZ
3927void BssTableSsidSort(struct rt_rtmp_adapter *pAd,
3928 struct rt_bss_table *OutTab, char Ssid[], u8 SsidLen)
59fe2d89 3929{
51126deb 3930 int i;
ca97b838 3931 BssTableInit(OutTab);
59fe2d89 3932
96b3c83d 3933 for (i = 0; i < pAd->ScanTab.BssNr; i++) {
62eb734b 3934 struct rt_bss_entry *pInBss = &pAd->ScanTab.BssEntry[i];
96b3c83d 3935 BOOLEAN bIsHiddenApIncluded = FALSE;
59fe2d89 3936
ca97b838 3937 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
96b3c83d
BZ
3938 (pAd->MlmeAux.Channel > 14) &&
3939 RadarChannelCheck(pAd, pInBss->Channel))
3940 ) {
ca97b838
BZ
3941 if (pInBss->Hidden)
3942 bIsHiddenApIncluded = TRUE;
96b3c83d 3943 }
59fe2d89 3944
ca97b838 3945 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
96b3c83d
BZ
3946 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen)
3947 || bIsHiddenApIncluded)) {
62eb734b 3948 struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
59fe2d89 3949
ec278fa2 3950 /* 2.4G/5G N only mode */
ca97b838 3951 if ((pInBss->HtCapabilityLen == 0) &&
96b3c83d
BZ
3952 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
3953 || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
3954 DBGPRINT(RT_DEBUG_TRACE,
3955 ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
ca97b838 3956 continue;
96b3c83d 3957 }
ec278fa2
BZ
3958 /* New for WPA2 */
3959 /* Check the Authmode first */
96b3c83d 3960 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
ec278fa2 3961 /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
96b3c83d
BZ
3962 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
3963 && (pAd->StaCfg.AuthMode !=
3964 pInBss->AuthModeAux))
ec278fa2 3965 /* None matched */
ca97b838 3966 continue;
59fe2d89 3967
ec278fa2 3968 /* Check cipher suite, AP must have more secured cipher than station setting */
96b3c83d
BZ
3969 if ((pAd->StaCfg.AuthMode ==
3970 Ndis802_11AuthModeWPA)
3971 || (pAd->StaCfg.AuthMode ==
3972 Ndis802_11AuthModeWPAPSK)) {
ec278fa2 3973 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
ca97b838 3974 if (pInBss->WPA.bMixMode == FALSE)
96b3c83d
BZ
3975 if (pAd->StaCfg.WepStatus !=
3976 pInBss->WPA.GroupCipher)
ca97b838 3977 continue;
91980990 3978
ec278fa2 3979 /* check group cipher */
96b3c83d
BZ
3980 if ((pAd->StaCfg.WepStatus <
3981 pInBss->WPA.GroupCipher)
3982 && (pInBss->WPA.GroupCipher !=
3983 Ndis802_11GroupWEP40Enabled)
3984 && (pInBss->WPA.GroupCipher !=
3985 Ndis802_11GroupWEP104Enabled))
ca97b838 3986 continue;
91980990 3987
ec278fa2
BZ
3988 /* check pairwise cipher, skip if none matched */
3989 /* If profile set to AES, let it pass without question. */
3990 /* If profile set to TKIP, we must find one mateched */
96b3c83d
BZ
3991 if ((pAd->StaCfg.WepStatus ==
3992 Ndis802_11Encryption2Enabled)
3993 && (pAd->StaCfg.WepStatus !=
3994 pInBss->WPA.PairCipher)
3995 && (pAd->StaCfg.WepStatus !=
3996 pInBss->WPA.PairCipherAux))
ca97b838 3997 continue;
96b3c83d
BZ
3998 } else
3999 if ((pAd->StaCfg.AuthMode ==
4000 Ndis802_11AuthModeWPA2)
4001 || (pAd->StaCfg.AuthMode ==
4002 Ndis802_11AuthModeWPA2PSK)) {
ec278fa2 4003 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
ca97b838 4004 if (pInBss->WPA2.bMixMode == FALSE)
96b3c83d
BZ
4005 if (pAd->StaCfg.WepStatus !=
4006 pInBss->WPA2.GroupCipher)
ca97b838
BZ
4007 continue;
4008
ec278fa2 4009 /* check group cipher */
96b3c83d
BZ
4010 if ((pAd->StaCfg.WepStatus <
4011 pInBss->WPA.GroupCipher)
4012 && (pInBss->WPA2.GroupCipher !=
4013 Ndis802_11GroupWEP40Enabled)
4014 && (pInBss->WPA2.GroupCipher !=
4015 Ndis802_11GroupWEP104Enabled))
ca97b838
BZ
4016 continue;
4017
ec278fa2
BZ
4018 /* check pairwise cipher, skip if none matched */
4019 /* If profile set to AES, let it pass without question. */
4020 /* If profile set to TKIP, we must find one mateched */
96b3c83d
BZ
4021 if ((pAd->StaCfg.WepStatus ==
4022 Ndis802_11Encryption2Enabled)
4023 && (pAd->StaCfg.WepStatus !=
4024 pInBss->WPA2.PairCipher)
4025 && (pAd->StaCfg.WepStatus !=
4026 pInBss->WPA2.PairCipherAux))
ca97b838
BZ
4027 continue;
4028 }
4029 }
ec278fa2
BZ
4030 /* Bss Type matched, SSID matched. */
4031 /* We will check wepstatus for qualification Bss */
96b3c83d
BZ
4032 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus) {
4033 DBGPRINT(RT_DEBUG_TRACE,
4034 ("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n",
4035 pAd->StaCfg.WepStatus,
4036 pInBss->WepStatus));
ec278fa2
BZ
4037 /* */
4038 /* For the SESv2 case, we will not qualify WepStatus. */
4039 /* */
ca97b838
BZ
4040 if (!pInBss->bSES)
4041 continue;
4042 }
ec278fa2
BZ
4043 /* Since the AP is using hidden SSID, and we are trying to connect to ANY */
4044 /* It definitely will fail. So, skip it. */
4045 /* CCX also require not even try to connect it!! */
ca97b838
BZ
4046 if (SsidLen == 0)
4047 continue;
4048
ec278fa2
BZ
4049 /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4050 /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
ca97b838 4051 if ((pInBss->CentralChannel != pInBss->Channel) &&
96b3c83d
BZ
4052 (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4053 BW_40)) {
4054 if (RTMPCheckChannel
4055 (pAd, pInBss->CentralChannel,
4056 pInBss->Channel) == FALSE) {
4057 pAd->CommonCfg.RegTransmitSetting.field.
4058 BW = BW_20;
ca97b838 4059 SetCommonHT(pAd);
96b3c83d
BZ
4060 pAd->CommonCfg.RegTransmitSetting.field.
4061 BW = BW_40;
4062 } else {
4063 if (pAd->CommonCfg.DesiredHtPhy.
4064 ChannelWidth == BAND_WIDTH_20) {
ca97b838
BZ
4065 SetCommonHT(pAd);
4066 }
96b3c83d
BZ
4067 }
4068 }
ec278fa2 4069 /* copy matching BSS from InTab to OutTab */
62eb734b 4070 NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
ca97b838
BZ
4071
4072 OutTab->BssNr++;
96b3c83d
BZ
4073 } else if ((pInBss->BssType == pAd->StaCfg.BssType)
4074 && (SsidLen == 0)) {
62eb734b 4075 struct rt_bss_entry *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
ca97b838 4076
ec278fa2 4077 /* 2.4G/5G N only mode */
ca97b838 4078 if ((pInBss->HtCapabilityLen == 0) &&
96b3c83d
BZ
4079 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G)
4080 || (pAd->CommonCfg.PhyMode == PHY_11N_5G))) {
4081 DBGPRINT(RT_DEBUG_TRACE,
4082 ("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
ca97b838
BZ
4083 continue;
4084 }
ec278fa2
BZ
4085 /* New for WPA2 */
4086 /* Check the Authmode first */
96b3c83d 4087 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA) {
ec278fa2 4088 /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode */
96b3c83d
BZ
4089 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode)
4090 && (pAd->StaCfg.AuthMode !=
4091 pInBss->AuthModeAux))
ec278fa2 4092 /* None matched */
ca97b838
BZ
4093 continue;
4094
ec278fa2 4095 /* Check cipher suite, AP must have more secured cipher than station setting */
96b3c83d
BZ
4096 if ((pAd->StaCfg.AuthMode ==
4097 Ndis802_11AuthModeWPA)
4098 || (pAd->StaCfg.AuthMode ==
4099 Ndis802_11AuthModeWPAPSK)) {
ec278fa2 4100 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
ca97b838 4101 if (pInBss->WPA.bMixMode == FALSE)
96b3c83d
BZ
4102 if (pAd->StaCfg.WepStatus !=
4103 pInBss->WPA.GroupCipher)
ca97b838 4104 continue;
91980990 4105
ec278fa2 4106 /* check group cipher */
96b3c83d
BZ
4107 if (pAd->StaCfg.WepStatus <
4108 pInBss->WPA.GroupCipher)
ca97b838 4109 continue;
59fe2d89 4110
ec278fa2
BZ
4111 /* check pairwise cipher, skip if none matched */
4112 /* If profile set to AES, let it pass without question. */
4113 /* If profile set to TKIP, we must find one mateched */
96b3c83d
BZ
4114 if ((pAd->StaCfg.WepStatus ==
4115 Ndis802_11Encryption2Enabled)
4116 && (pAd->StaCfg.WepStatus !=
4117 pInBss->WPA.PairCipher)
4118 && (pAd->StaCfg.WepStatus !=
4119 pInBss->WPA.PairCipherAux))
ca97b838 4120 continue;
96b3c83d
BZ
4121 } else
4122 if ((pAd->StaCfg.AuthMode ==
4123 Ndis802_11AuthModeWPA2)
4124 || (pAd->StaCfg.AuthMode ==
4125 Ndis802_11AuthModeWPA2PSK)) {
ec278fa2 4126 /* If it's not mixed mode, we should only let BSS pass with the same encryption */
ca97b838 4127 if (pInBss->WPA2.bMixMode == FALSE)
96b3c83d
BZ
4128 if (pAd->StaCfg.WepStatus !=
4129 pInBss->WPA2.GroupCipher)
ca97b838
BZ
4130 continue;
4131
ec278fa2 4132 /* check group cipher */
96b3c83d
BZ
4133 if (pAd->StaCfg.WepStatus <
4134 pInBss->WPA2.GroupCipher)
ca97b838
BZ
4135 continue;
4136
ec278fa2
BZ
4137 /* check pairwise cipher, skip if none matched */
4138 /* If profile set to AES, let it pass without question. */
4139 /* If profile set to TKIP, we must find one mateched */
96b3c83d
BZ
4140 if ((pAd->StaCfg.WepStatus ==
4141 Ndis802_11Encryption2Enabled)
4142 && (pAd->StaCfg.WepStatus !=
4143 pInBss->WPA2.PairCipher)
4144 && (pAd->StaCfg.WepStatus !=
4145 pInBss->WPA2.PairCipherAux))
ca97b838 4146 continue;
59fe2d89 4147 }
ca97b838 4148 }
ec278fa2
BZ
4149 /* Bss Type matched, SSID matched. */
4150 /* We will check wepstatus for qualification Bss */
ca97b838 4151 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
96b3c83d 4152 continue;
ca97b838 4153
ec278fa2
BZ
4154 /* If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region */
4155 /* If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead, */
ca97b838 4156 if ((pInBss->CentralChannel != pInBss->Channel) &&
96b3c83d
BZ
4157 (pAd->CommonCfg.RegTransmitSetting.field.BW ==
4158 BW_40)) {
4159 if (RTMPCheckChannel
4160 (pAd, pInBss->CentralChannel,
4161 pInBss->Channel) == FALSE) {
4162 pAd->CommonCfg.RegTransmitSetting.field.
4163 BW = BW_20;
ca97b838 4164 SetCommonHT(pAd);
96b3c83d
BZ
4165 pAd->CommonCfg.RegTransmitSetting.field.
4166 BW = BW_40;
59fe2d89 4167 }
96b3c83d 4168 }
ec278fa2 4169 /* copy matching BSS from InTab to OutTab */
62eb734b 4170 NdisMoveMemory(pOutBss, pInBss, sizeof(struct rt_bss_entry));
ca97b838
BZ
4171
4172 OutTab->BssNr++;
4173 }
4174
4175 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
96b3c83d
BZ
4176 break;
4177 }
59fe2d89 4178
ca97b838
BZ
4179 BssTableSortByRssi(OutTab);
4180}
91980990 4181
ec278fa2 4182/* IRQL = DISPATCH_LEVEL */
62eb734b 4183void BssTableSortByRssi(struct rt_bss_table *OutTab)
ca97b838 4184{
51126deb 4185 int i, j;
62eb734b 4186 struct rt_bss_entry TmpBss;
ca97b838 4187
96b3c83d
BZ
4188 for (i = 0; i < OutTab->BssNr - 1; i++) {
4189 for (j = i + 1; j < OutTab->BssNr; j++) {
4190 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi) {
4191 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j],
62eb734b 4192 sizeof(struct rt_bss_entry));
96b3c83d
BZ
4193 NdisMoveMemory(&OutTab->BssEntry[j],
4194 &OutTab->BssEntry[i],
62eb734b 4195 sizeof(struct rt_bss_entry));
96b3c83d 4196 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss,
62eb734b 4197 sizeof(struct rt_bss_entry));
96b3c83d
BZ
4198 }
4199 }
4200 }
ca97b838 4201}
91980990 4202
62eb734b 4203void BssCipherParse(struct rt_bss_entry *pBss)
ca97b838 4204{
62eb734b 4205 struct rt_eid * pEid;
51126deb 4206 u8 *pTmp;
62eb734b
BZ
4207 struct rt_rsn_ie_header * pRsnHeader;
4208 struct rt_cipher_suite_struct * pCipher;
4209 struct rt_akm_suite * pAKM;
51126deb
BZ
4210 u16 Count;
4211 int Length;
96b3c83d 4212 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
91980990 4213
ec278fa2
BZ
4214 /* */
4215 /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame. */
4216 /* */
96b3c83d
BZ
4217 if (pBss->Privacy) {
4218 pBss->WepStatus = Ndis802_11WEPEnabled;
4219 } else {
4220 pBss->WepStatus = Ndis802_11WEPDisabled;
4221 }
ec278fa2 4222 /* Set default to disable & open authentication before parsing variable IE */
96b3c83d
BZ
4223 pBss->AuthMode = Ndis802_11AuthModeOpen;
4224 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
91980990 4225
ec278fa2 4226 /* Init WPA setting */
96b3c83d 4227 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
ca97b838 4228 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
96b3c83d 4229 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
ca97b838 4230 pBss->WPA.RsnCapability = 0;
96b3c83d 4231 pBss->WPA.bMixMode = FALSE;
91980990 4232
ec278fa2 4233 /* Init WPA2 setting */
96b3c83d 4234 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
ca97b838 4235 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
96b3c83d 4236 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
ca97b838 4237 pBss->WPA2.RsnCapability = 0;
96b3c83d 4238 pBss->WPA2.bMixMode = FALSE;
91980990 4239
51126deb 4240 Length = (int)pBss->VarIELen;
91980990 4241
96b3c83d 4242 while (Length > 0) {
ec278fa2 4243 /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently */
51126deb 4244 pTmp = ((u8 *)pBss->VarIEs) + pBss->VarIELen - Length;
62eb734b 4245 pEid = (struct rt_eid *) pTmp;
96b3c83d
BZ
4246 switch (pEid->Eid) {
4247 case IE_WPA:
4248 if (NdisEqualMemory(pEid->Octet, SES_OUI, 3)
4249 && (pEid->Len == 7)) {
4250 pBss->bSES = TRUE;
4251 break;
4252 } else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) !=
4253 1) {
ec278fa2 4254 /* if unsupported vendor specific IE */
96b3c83d
BZ
4255 break;
4256 }
ec278fa2
BZ
4257 /* Skip OUI, version, and multicast suite */
4258 /* This part should be improved in the future when AP supported multiple cipher suite. */
4259 /* For now, it's OK since almost all APs have fixed cipher suite supported. */
51126deb 4260 /* pTmp = (u8 *)pEid->Octet; */
96b3c83d
BZ
4261 pTmp += 11;
4262
ec278fa2
BZ
4263 /* Cipher Suite Selectors from Spec P802.11i/D3.2 P26. */
4264 /* Value Meaning */
4265 /* 0 None */
4266 /* 1 WEP-40 */
4267 /* 2 Tkip */
4268 /* 3 WRAP */
4269 /* 4 AES */
4270 /* 5 WEP-104 */
4271 /* Parse group cipher */
96b3c83d
BZ
4272 switch (*pTmp) {
4273 case 1:
4274 pBss->WPA.GroupCipher =
4275 Ndis802_11GroupWEP40Enabled;
4276 break;
4277 case 5:
4278 pBss->WPA.GroupCipher =
4279 Ndis802_11GroupWEP104Enabled;
4280 break;
4281 case 2:
4282 pBss->WPA.GroupCipher =
4283 Ndis802_11Encryption2Enabled;
4284 break;
4285 case 4:
4286 pBss->WPA.GroupCipher =
4287 Ndis802_11Encryption3Enabled;
4288 break;
4289 default:
4290 break;
4291 }
ec278fa2 4292 /* number of unicast suite */
96b3c83d
BZ
4293 pTmp += 1;
4294
ec278fa2 4295 /* skip all unicast cipher suites */
51126deb 4296 /*Count = *(u16 *)pTmp; */
96b3c83d 4297 Count = (pTmp[1] << 8) + pTmp[0];
51126deb 4298 pTmp += sizeof(u16);
96b3c83d 4299
ec278fa2 4300 /* Parsing all unicast cipher suite */
96b3c83d 4301 while (Count > 0) {
ec278fa2 4302 /* Skip OUI */
96b3c83d
BZ
4303 pTmp += 3;
4304 TmpCipher = Ndis802_11WEPDisabled;
4305 switch (*pTmp) {
4306 case 1:
ec278fa2 4307 case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
96b3c83d
BZ
4308 TmpCipher =
4309 Ndis802_11Encryption1Enabled;
ca97b838 4310 break;
96b3c83d
BZ
4311 case 2:
4312 TmpCipher =
4313 Ndis802_11Encryption2Enabled;
4314 break;
4315 case 4:
4316 TmpCipher =
4317 Ndis802_11Encryption3Enabled;
4318 break;
4319 default:
ca97b838 4320 break;
ca97b838 4321 }
96b3c83d 4322 if (TmpCipher > pBss->WPA.PairCipher) {
ec278fa2 4323 /* Move the lower cipher suite to PairCipherAux */
96b3c83d
BZ
4324 pBss->WPA.PairCipherAux =
4325 pBss->WPA.PairCipher;
4326 pBss->WPA.PairCipher = TmpCipher;
4327 } else {
4328 pBss->WPA.PairCipherAux = TmpCipher;
4329 }
4330 pTmp++;
4331 Count--;
4332 }
ca97b838 4333
ec278fa2 4334 /* 4. get AKM suite counts */
51126deb 4335 /*Count = *(u16 *)pTmp; */
96b3c83d 4336 Count = (pTmp[1] << 8) + pTmp[0];
51126deb 4337 pTmp += sizeof(u16);
96b3c83d
BZ
4338 pTmp += 3;
4339
4340 switch (*pTmp) {
4341 case 1:
ec278fa2 4342 /* Set AP support WPA-enterprise mode */
96b3c83d
BZ
4343 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4344 pBss->AuthMode = Ndis802_11AuthModeWPA;
4345 else
4346 pBss->AuthModeAux =
4347 Ndis802_11AuthModeWPA;
4348 break;
4349 case 2:
ec278fa2 4350 /* Set AP support WPA-PSK mode */
96b3c83d
BZ
4351 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4352 pBss->AuthMode =
4353 Ndis802_11AuthModeWPAPSK;
4354 else
4355 pBss->AuthModeAux =
4356 Ndis802_11AuthModeWPAPSK;
4357 break;
4358 default:
4359 break;
4360 }
4361 pTmp += 1;
4362
ec278fa2 4363 /* Fixed for WPA-None */
96b3c83d
BZ
4364 if (pBss->BssType == BSS_ADHOC) {
4365 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4366 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4367 pBss->WepStatus = pBss->WPA.GroupCipher;
ec278fa2 4368 /* Patched bugs for old driver */
96b3c83d
BZ
4369 if (pBss->WPA.PairCipherAux ==
4370 Ndis802_11WEPDisabled)
4371 pBss->WPA.PairCipherAux =
4372 pBss->WPA.GroupCipher;
4373 } else
4374 pBss->WepStatus = pBss->WPA.PairCipher;
4375
ec278fa2 4376 /* Check the Pair & Group, if different, turn on mixed mode flag */
96b3c83d
BZ
4377 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4378 pBss->WPA.bMixMode = TRUE;
ca97b838 4379
96b3c83d 4380 break;
91980990 4381
96b3c83d 4382 case IE_RSN:
62eb734b 4383 pRsnHeader = (struct rt_rsn_ie_header *) pTmp;
91980990 4384
ec278fa2 4385 /* 0. Version must be 1 */
96b3c83d 4386 if (le2cpu16(pRsnHeader->Version) != 1)
ca97b838 4387 break;
62eb734b 4388 pTmp += sizeof(struct rt_rsn_ie_header);
91980990 4389
ec278fa2 4390 /* 1. Check group cipher */
62eb734b 4391 pCipher = (struct rt_cipher_suite_struct *) pTmp;
96b3c83d
BZ
4392 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4393 break;
91980990 4394
ec278fa2 4395 /* Parse group cipher */
96b3c83d
BZ
4396 switch (pCipher->Type) {
4397 case 1:
4398 pBss->WPA2.GroupCipher =
4399 Ndis802_11GroupWEP40Enabled;
4400 break;
4401 case 5:
4402 pBss->WPA2.GroupCipher =
4403 Ndis802_11GroupWEP104Enabled;
4404 break;
4405 case 2:
4406 pBss->WPA2.GroupCipher =
4407 Ndis802_11Encryption2Enabled;
4408 break;
4409 case 4:
4410 pBss->WPA2.GroupCipher =
4411 Ndis802_11Encryption3Enabled;
4412 break;
4413 default:
4414 break;
4415 }
ec278fa2 4416 /* set to correct offset for next parsing */
62eb734b 4417 pTmp += sizeof(struct rt_cipher_suite_struct);
96b3c83d 4418
ec278fa2 4419 /* 2. Get pairwise cipher counts */
51126deb 4420 /*Count = *(u16 *)pTmp; */
96b3c83d 4421 Count = (pTmp[1] << 8) + pTmp[0];
51126deb 4422 pTmp += sizeof(u16);
96b3c83d 4423
ec278fa2
BZ
4424 /* 3. Get pairwise cipher */
4425 /* Parsing all unicast cipher suite */
96b3c83d 4426 while (Count > 0) {
ec278fa2 4427 /* Skip OUI */
62eb734b 4428 pCipher = (struct rt_cipher_suite_struct *) pTmp;
96b3c83d
BZ
4429 TmpCipher = Ndis802_11WEPDisabled;
4430 switch (pCipher->Type) {
4431 case 1:
ec278fa2 4432 case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */
96b3c83d
BZ
4433 TmpCipher =
4434 Ndis802_11Encryption1Enabled;
4435 break;
4436 case 2:
4437 TmpCipher =
4438 Ndis802_11Encryption2Enabled;
4439 break;
4440 case 4:
4441 TmpCipher =
4442 Ndis802_11Encryption3Enabled;
4443 break;
4444 default:
4445 break;
91980990 4446 }
96b3c83d 4447 if (TmpCipher > pBss->WPA2.PairCipher) {
ec278fa2 4448 /* Move the lower cipher suite to PairCipherAux */
96b3c83d
BZ
4449 pBss->WPA2.PairCipherAux =
4450 pBss->WPA2.PairCipher;
4451 pBss->WPA2.PairCipher = TmpCipher;
4452 } else {
4453 pBss->WPA2.PairCipherAux = TmpCipher;
4454 }
62eb734b 4455 pTmp += sizeof(struct rt_cipher_suite_struct);
96b3c83d
BZ
4456 Count--;
4457 }
91980990 4458
ec278fa2 4459 /* 4. get AKM suite counts */
51126deb 4460 /*Count = *(u16 *)pTmp; */
96b3c83d 4461 Count = (pTmp[1] << 8) + pTmp[0];
51126deb 4462 pTmp += sizeof(u16);
91980990 4463
ec278fa2
BZ
4464 /* 5. Get AKM ciphers */
4465 /* Parsing all AKM ciphers */
96b3c83d 4466 while (Count > 0) {
62eb734b 4467 pAKM = (struct rt_akm_suite *) pTmp;
96b3c83d
BZ
4468 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4469 break;
91980990 4470
96b3c83d
BZ
4471 switch (pAKM->Type) {
4472 case 1:
ec278fa2 4473 /* Set AP support WPA-enterprise mode */
96b3c83d
BZ
4474 if (pBss->AuthMode ==
4475 Ndis802_11AuthModeOpen)
4476 pBss->AuthMode =
4477 Ndis802_11AuthModeWPA2;
4478 else
4479 pBss->AuthModeAux =
4480 Ndis802_11AuthModeWPA2;
4481 break;
4482 case 2:
ec278fa2 4483 /* Set AP support WPA-PSK mode */
96b3c83d
BZ
4484 if (pBss->AuthMode ==
4485 Ndis802_11AuthModeOpen)
4486 pBss->AuthMode =
4487 Ndis802_11AuthModeWPA2PSK;
4488 else
4489 pBss->AuthModeAux =
4490 Ndis802_11AuthModeWPA2PSK;
4491 break;
4492 default:
4493 if (pBss->AuthMode ==
4494 Ndis802_11AuthModeOpen)
4495 pBss->AuthMode =
4496 Ndis802_11AuthModeMax;
4497 else
4498 pBss->AuthModeAux =
4499 Ndis802_11AuthModeMax;
4500 break;
91980990 4501 }
62eb734b 4502 pTmp += (Count * sizeof(struct rt_akm_suite));
96b3c83d 4503 Count--;
91980990
GKH
4504 }
4505
ec278fa2 4506 /* Fixed for WPA-None */
96b3c83d
BZ
4507 if (pBss->BssType == BSS_ADHOC) {
4508 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4509 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4510 pBss->WPA.PairCipherAux =
4511 pBss->WPA2.PairCipherAux;
4512 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4513 pBss->WepStatus = pBss->WPA.GroupCipher;
ec278fa2 4514 /* Patched bugs for old driver */
96b3c83d
BZ
4515 if (pBss->WPA.PairCipherAux ==
4516 Ndis802_11WEPDisabled)
4517 pBss->WPA.PairCipherAux =
4518 pBss->WPA.GroupCipher;
4519 }
4520 pBss->WepStatus = pBss->WPA2.PairCipher;
91980990 4521
ec278fa2 4522 /* 6. Get RSN capability */
51126deb 4523 /*pBss->WPA2.RsnCapability = *(u16 *)pTmp; */
96b3c83d 4524 pBss->WPA2.RsnCapability = (pTmp[1] << 8) + pTmp[0];
51126deb 4525 pTmp += sizeof(u16);
91980990 4526
ec278fa2 4527 /* Check the Pair & Group, if different, turn on mixed mode flag */
96b3c83d
BZ
4528 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4529 pBss->WPA2.bMixMode = TRUE;
91980990 4530
96b3c83d
BZ
4531 break;
4532 default:
4533 break;
ca97b838
BZ
4534 }
4535 Length -= (pEid->Len + 2);
4536 }
4537}
91980990 4538
ec278fa2
BZ
4539/* =========================================================================================== */
4540/* mac_table.c */
4541/* =========================================================================================== */
91980990 4542
ca97b838
BZ
4543/*! \brief generates a random mac address value for IBSS BSSID
4544 * \param Addr the bssid location
4545 * \return none
4546 * \pre
4547 * \post
91980990 4548 */
62eb734b 4549void MacAddrRandomBssid(struct rt_rtmp_adapter *pAd, u8 *pAddr)
91980990 4550{
51126deb 4551 int i;
91980990 4552
96b3c83d 4553 for (i = 0; i < MAC_ADDR_LEN; i++) {
ca97b838 4554 pAddr[i] = RandomByte(pAd);
91980990 4555 }
ca97b838 4556
ec278fa2 4557 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; /* the first 2 bits must be 01xxxxxxxx */
91980990
GKH
4558}
4559
ca97b838
BZ
4560/*! \brief init the management mac frame header
4561 * \param p_hdr mac header
4562 * \param subtype subtype of the frame
4563 * \param p_ds destination address, don't care if it is a broadcast address
4564 * \return none
4565 * \pre the station has the following information in the pAd->StaCfg
4566 * - bssid
4567 * - station address
4568 * \post
4569 * \note this function initializes the following field
91980990
GKH
4570
4571 IRQL = PASSIVE_LEVEL
4572 IRQL = DISPATCH_LEVEL
4573
91980990 4574 */
62eb734b
BZ
4575void MgtMacHeaderInit(struct rt_rtmp_adapter *pAd,
4576 struct rt_header_802_11 * pHdr80211,
51126deb
BZ
4577 u8 SubType,
4578 u8 ToDs, u8 *pDA, u8 *pBssid)
91980990 4579{
62eb734b 4580 NdisZeroMemory(pHdr80211, sizeof(struct rt_header_802_11));
91980990 4581
ca97b838
BZ
4582 pHdr80211->FC.Type = BTYPE_MGMT;
4583 pHdr80211->FC.SubType = SubType;
ec278fa2
BZ
4584/* if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type */
4585/* pHdr80211->FC.Type = BTYPE_CNTL; */
ca97b838
BZ
4586 pHdr80211->FC.ToDs = ToDs;
4587 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
96b3c83d 4588 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
ca97b838 4589 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
91980990
GKH
4590}
4591
ec278fa2
BZ
4592/* =========================================================================================== */
4593/* mem_mgmt.c */
4594/* =========================================================================================== */
ca97b838
BZ
4595
4596/*!***************************************************************************
4597 * This routine build an outgoing frame, and fill all information specified
4598 * in argument list to the frame body. The actual frame size is the summation
4599 * of all arguments.
4600 * input params:
4601 * Buffer - pointer to a pre-allocated memory segment
4602 * args - a list of <int arg_size, arg> pairs.
4603 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4604 * function will FAIL!!!
4605 * return:
4606 * Size of the buffer
4607 * usage:
4608 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
91980990 4609
ca97b838 4610 IRQL = PASSIVE_LEVEL
91980990
GKH
4611 IRQL = DISPATCH_LEVEL
4612
ca97b838 4613 ****************************************************************************/
51126deb 4614unsigned long MakeOutgoingFrame(u8 * Buffer, unsigned long * FrameLen, ...)
91980990 4615{
51126deb 4616 u8 *p;
96b3c83d 4617 int leng;
51126deb 4618 unsigned long TotLeng;
ca97b838 4619 va_list Args;
6a28a69a 4620
ec278fa2 4621 /* calculates the total length */
ca97b838
BZ
4622 TotLeng = 0;
4623 va_start(Args, FrameLen);
96b3c83d 4624 do {
ca97b838 4625 leng = va_arg(Args, int);
96b3c83d 4626 if (leng == END_OF_ARGS) {
ca97b838 4627 break;
96b3c83d 4628 }
51126deb 4629 p = va_arg(Args, void *);
ca97b838
BZ
4630 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4631 TotLeng = TotLeng + leng;
96b3c83d 4632 } while (TRUE);
6a28a69a 4633
96b3c83d 4634 va_end(Args); /* clean up */
ca97b838
BZ
4635 *FrameLen = TotLeng;
4636 return TotLeng;
91980990
GKH
4637}
4638
ec278fa2
BZ
4639/* =========================================================================================== */
4640/* mlme_queue.c */
4641/* =========================================================================================== */
91980990 4642
ca97b838
BZ
4643/*! \brief Initialize The MLME Queue, used by MLME Functions
4644 * \param *Queue The MLME Queue
4645 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4646 * \pre
4647 * \post
4648 * \note Because this is done only once (at the init stage), no need to be locked
4649
4650 IRQL = PASSIVE_LEVEL
91980990 4651
91980990 4652 */
62eb734b 4653int MlmeQueueInit(struct rt_mlme_queue *Queue)
91980990 4654{
51126deb 4655 int i;
91980990 4656
ca97b838 4657 NdisAllocateSpinLock(&Queue->Lock);
91980990 4658
96b3c83d 4659 Queue->Num = 0;
ca97b838
BZ
4660 Queue->Head = 0;
4661 Queue->Tail = 0;
59fe2d89 4662
96b3c83d 4663 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) {
ca97b838
BZ
4664 Queue->Entry[i].Occupied = FALSE;
4665 Queue->Entry[i].MsgLen = 0;
4666 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
59fe2d89 4667 }
91980990 4668
ca97b838 4669 return NDIS_STATUS_SUCCESS;
91980990
GKH
4670}
4671
ca97b838
BZ
4672/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4673 * \param *Queue The MLME Queue
4674 * \param Machine The State Machine Id
4675 * \param MsgType The Message Type
4676 * \param MsgLen The Message length
4677 * \param *Msg The message pointer
4678 * \return TRUE if enqueue is successful, FALSE if the queue is full
4679 * \pre
4680 * \post
4681 * \note The message has to be initialized
91980990
GKH
4682
4683 IRQL = PASSIVE_LEVEL
4684 IRQL = DISPATCH_LEVEL
4685
91980990 4686 */
62eb734b 4687BOOLEAN MlmeEnqueue(struct rt_rtmp_adapter *pAd,
51126deb
BZ
4688 unsigned long Machine,
4689 unsigned long MsgType, unsigned long MsgLen, void * Msg)
91980990 4690{
51126deb 4691 int Tail;
62eb734b 4692 struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
91980990 4693
ec278fa2
BZ
4694 /* Do nothing if the driver is starting halt state. */
4695 /* This might happen when timer already been fired before cancel timer with mlmehalt */
96b3c83d
BZ
4696 if (RTMP_TEST_FLAG
4697 (pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
ca97b838 4698 return FALSE;
91980990 4699
ec278fa2 4700 /* First check the size, it MUST not exceed the mlme queue size */
96b3c83d
BZ
4701 if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
4702 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n",
4703 MsgLen));
ca97b838
BZ
4704 return FALSE;
4705 }
4706
96b3c83d 4707 if (MlmeQueueFull(Queue)) {
ca97b838 4708 return FALSE;
96b3c83d 4709 }
ca97b838
BZ
4710
4711 NdisAcquireSpinLock(&(Queue->Lock));
4712 Tail = Queue->Tail;
4713 Queue->Tail++;
4714 Queue->Num++;
96b3c83d 4715 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
ca97b838 4716 Queue->Tail = 0;
96b3c83d 4717 }
ca97b838
BZ
4718
4719 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4720 Queue->Entry[Tail].Occupied = TRUE;
4721 Queue->Entry[Tail].Machine = Machine;
4722 Queue->Entry[Tail].MsgType = MsgType;
96b3c83d 4723 Queue->Entry[Tail].MsgLen = MsgLen;
ca97b838 4724
96b3c83d 4725 if (Msg != NULL) {
ca97b838 4726 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
96b3c83d 4727 }
91980990 4728
ca97b838
BZ
4729 NdisReleaseSpinLock(&(Queue->Lock));
4730 return TRUE;
4731}
91980990 4732
ca97b838
BZ
4733/*! \brief This function is used when Recv gets a MLME message
4734 * \param *Queue The MLME Queue
4735 * \param TimeStampHigh The upper 32 bit of timestamp
4736 * \param TimeStampLow The lower 32 bit of timestamp
4737 * \param Rssi The receiving RSSI strength
4738 * \param MsgLen The length of the message
4739 * \param *Msg The message pointer
4740 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4741 * \pre
4742 * \post
91980990 4743
ca97b838 4744 IRQL = DISPATCH_LEVEL
91980990 4745
ca97b838 4746 */
62eb734b 4747BOOLEAN MlmeEnqueueForRecv(struct rt_rtmp_adapter *pAd,
51126deb
BZ
4748 unsigned long Wcid,
4749 unsigned long TimeStampHigh,
4750 unsigned long TimeStampLow,
4751 u8 Rssi0,
4752 u8 Rssi1,
4753 u8 Rssi2,
4754 unsigned long MsgLen, void * Msg, u8 Signal)
ca97b838 4755{
51126deb 4756 int Tail, Machine;
62eb734b 4757 struct rt_frame_802_11 * pFrame = (struct rt_frame_802_11 *) Msg;
51126deb 4758 int MsgType;
62eb734b 4759 struct rt_mlme_queue *Queue = (struct rt_mlme_queue *)& pAd->Mlme.Queue;
91980990 4760
ec278fa2
BZ
4761 /* Do nothing if the driver is starting halt state. */
4762 /* This might happen when timer already been fired before cancel timer with mlmehalt */
96b3c83d
BZ
4763 if (RTMP_TEST_FLAG
4764 (pAd,
4765 fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) {
ca97b838
BZ
4766 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4767 return FALSE;
4768 }
ec278fa2 4769 /* First check the size, it MUST not exceed the mlme queue size */
96b3c83d 4770 if (MsgLen > MGMT_DMA_BUFFER_SIZE) {
ca97b838
BZ
4771 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4772 return FALSE;
4773 }
6a28a69a 4774
96b3c83d 4775 if (MlmeQueueFull(Queue)) {
ca97b838
BZ
4776 return FALSE;
4777 }
59fe2d89 4778
96b3c83d
BZ
4779 {
4780 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) {
4781 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n", pFrame->Hdr.FC.SubType));
ca97b838 4782 return FALSE;
91980990 4783 }
96b3c83d 4784 }
91980990 4785
ec278fa2 4786 /* OK, we got all the informations, it is time to put things into queue */
ca97b838
BZ
4787 NdisAcquireSpinLock(&(Queue->Lock));
4788 Tail = Queue->Tail;
4789 Queue->Tail++;
4790 Queue->Num++;
96b3c83d 4791 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) {
ca97b838 4792 Queue->Tail = 0;
96b3c83d 4793 }
ca97b838
BZ
4794 Queue->Entry[Tail].Occupied = TRUE;
4795 Queue->Entry[Tail].Machine = Machine;
4796 Queue->Entry[Tail].MsgType = MsgType;
96b3c83d 4797 Queue->Entry[Tail].MsgLen = MsgLen;
ca97b838
BZ
4798 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4799 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4800 Queue->Entry[Tail].Rssi0 = Rssi0;
4801 Queue->Entry[Tail].Rssi1 = Rssi1;
4802 Queue->Entry[Tail].Rssi2 = Rssi2;
4803 Queue->Entry[Tail].Signal = Signal;
51126deb 4804 Queue->Entry[Tail].Wcid = (u8)Wcid;
91980990 4805
ca97b838 4806 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
91980990 4807
96b3c83d 4808 if (Msg != NULL) {
ca97b838
BZ
4809 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4810 }
6a28a69a 4811
ca97b838 4812 NdisReleaseSpinLock(&(Queue->Lock));
91980990 4813
ca97b838 4814 RTMP_MLME_HANDLER(pAd);
91980990 4815
ca97b838 4816 return TRUE;
91980990
GKH
4817}
4818
ca97b838
BZ
4819/*! \brief Dequeue a message from the MLME Queue
4820 * \param *Queue The MLME Queue
4821 * \param *Elem The message dequeued from MLME Queue
4822 * \return TRUE if the Elem contains something, FALSE otherwise
4823 * \pre
4824 * \post
4825
4826 IRQL = DISPATCH_LEVEL
91980990 4827
91980990 4828 */
62eb734b 4829BOOLEAN MlmeDequeue(struct rt_mlme_queue *Queue, struct rt_mlme_queue_elem ** Elem)
91980990 4830{
ca97b838
BZ
4831 NdisAcquireSpinLock(&(Queue->Lock));
4832 *Elem = &(Queue->Entry[Queue->Head]);
4833 Queue->Num--;
4834 Queue->Head++;
96b3c83d 4835 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) {
ca97b838 4836 Queue->Head = 0;
91980990 4837 }
ca97b838
BZ
4838 NdisReleaseSpinLock(&(Queue->Lock));
4839 return TRUE;
91980990
GKH
4840}
4841
ec278fa2 4842/* IRQL = DISPATCH_LEVEL */
62eb734b 4843void MlmeRestartStateMachine(struct rt_rtmp_adapter *pAd)
91980990 4844{
ca97b838 4845#ifdef RTMP_MAC_PCI
62eb734b 4846 struct rt_mlme_queue_elem *Elem = NULL;
ec278fa2 4847#endif /* RTMP_MAC_PCI // */
96b3c83d 4848 BOOLEAN Cancelled;
91980990 4849
ca97b838 4850 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
91980990 4851
ca97b838
BZ
4852#ifdef RTMP_MAC_PCI
4853 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
96b3c83d 4854 if (pAd->Mlme.bRunning) {
ca97b838
BZ
4855 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4856 return;
96b3c83d 4857 } else {
ca97b838 4858 pAd->Mlme.bRunning = TRUE;
91980990 4859 }
ca97b838 4860 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
59fe2d89 4861
ec278fa2 4862 /* Remove all Mlme queues elements */
96b3c83d 4863 while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) {
ec278fa2 4864 /*From message type, determine which state machine I should drive */
96b3c83d 4865 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) {
ec278fa2 4866 /* free MLME element */
ca97b838
BZ
4867 Elem->Occupied = FALSE;
4868 Elem->MsgLen = 0;
91980990 4869
96b3c83d 4870 } else {
ca97b838 4871 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
96b3c83d 4872 }
91980990 4873 }
ec278fa2 4874#endif /* RTMP_MAC_PCI // */
ca97b838 4875
91980990 4876 {
ec278fa2
BZ
4877 /* Cancel all timer events */
4878 /* Be careful to cancel new added timer */
96b3c83d
BZ
4879 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4880 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4881 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4882 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4883 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4884 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
91980990 4885
ca97b838 4886 }
91980990 4887
ec278fa2 4888 /* Change back to original channel in case of doing scan */
ca97b838
BZ
4889 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4890 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
91980990 4891
ec278fa2 4892 /* Resume MSDU which is turned off durning scan */
ca97b838 4893 RTMPResumeMsduTransmission(pAd);
91980990 4894
91980990 4895 {
ec278fa2 4896 /* Set all state machines back IDLE */
96b3c83d
BZ
4897 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4898 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4899 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
ca97b838 4900 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
96b3c83d
BZ
4901 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4902 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
91980990 4903 }
91980990 4904
ca97b838 4905#ifdef RTMP_MAC_PCI
ec278fa2 4906 /* Remove running state */
ca97b838
BZ
4907 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4908 pAd->Mlme.bRunning = FALSE;
4909 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
ec278fa2 4910#endif /* RTMP_MAC_PCI // */
91980990
GKH
4911}
4912
ca97b838
BZ
4913/*! \brief test if the MLME Queue is empty
4914 * \param *Queue The MLME Queue
4915 * \return TRUE if the Queue is empty, FALSE otherwise
4916 * \pre
4917 * \post
91980990 4918
ca97b838 4919 IRQL = DISPATCH_LEVEL
91980990 4920
ca97b838 4921 */
62eb734b 4922BOOLEAN MlmeQueueEmpty(struct rt_mlme_queue *Queue)
91980990 4923{
ca97b838 4924 BOOLEAN Ans;
91980990 4925
ca97b838
BZ
4926 NdisAcquireSpinLock(&(Queue->Lock));
4927 Ans = (Queue->Num == 0);
4928 NdisReleaseSpinLock(&(Queue->Lock));
91980990 4929
ca97b838 4930 return Ans;
91980990
GKH
4931}
4932
ca97b838
BZ
4933/*! \brief test if the MLME Queue is full
4934 * \param *Queue The MLME Queue
4935 * \return TRUE if the Queue is empty, FALSE otherwise
4936 * \pre
4937 * \post
4938
4939 IRQL = PASSIVE_LEVEL
4940 IRQL = DISPATCH_LEVEL
4941
4942 */
62eb734b 4943BOOLEAN MlmeQueueFull(struct rt_mlme_queue *Queue)
91980990 4944{
ca97b838 4945 BOOLEAN Ans;
91980990 4946
ca97b838 4947 NdisAcquireSpinLock(&(Queue->Lock));
96b3c83d
BZ
4948 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE
4949 || Queue->Entry[Queue->Tail].Occupied);
ca97b838 4950 NdisReleaseSpinLock(&(Queue->Lock));
91980990 4951
ca97b838
BZ
4952 return Ans;
4953}
91980990 4954
ca97b838
BZ
4955/*! \brief The destructor of MLME Queue
4956 * \param
4957 * \return
4958 * \pre
4959 * \post
4960 * \note Clear Mlme Queue, Set Queue->Num to Zero.
91980990 4961
ca97b838 4962 IRQL = PASSIVE_LEVEL
91980990 4963
ca97b838 4964 */
62eb734b 4965void MlmeQueueDestroy(struct rt_mlme_queue *pQueue)
ca97b838
BZ
4966{
4967 NdisAcquireSpinLock(&(pQueue->Lock));
96b3c83d 4968 pQueue->Num = 0;
ca97b838
BZ
4969 pQueue->Head = 0;
4970 pQueue->Tail = 0;
4971 NdisReleaseSpinLock(&(pQueue->Lock));
4972 NdisFreeSpinLock(&(pQueue->Lock));
4973}
91980990 4974
ca97b838
BZ
4975/*! \brief To substitute the message type if the message is coming from external
4976 * \param pFrame The frame received
4977 * \param *Machine The state machine
4978 * \param *MsgType the message type for the state machine
4979 * \return TRUE if the substitution is successful, FALSE otherwise
4980 * \pre
4981 * \post
91980990 4982
ca97b838 4983 IRQL = DISPATCH_LEVEL
91980990 4984
ca97b838 4985 */
62eb734b
BZ
4986BOOLEAN MsgTypeSubst(struct rt_rtmp_adapter *pAd,
4987 struct rt_frame_802_11 * pFrame,
51126deb 4988 int * Machine, int * MsgType)
91980990 4989{
51126deb
BZ
4990 u16 Seq, Alg;
4991 u8 EAPType;
4992 u8 *pData;
91980990 4993
ec278fa2 4994 /* Pointer to start of data frames including SNAP header */
51126deb 4995 pData = (u8 *)pFrame + LENGTH_802_11;
91980990 4996
ec278fa2 4997 /* The only data type will pass to this function is EAPOL frame */
96b3c83d 4998 if (pFrame->Hdr.FC.Type == BTYPE_DATA) {
91980990 4999 {
96b3c83d
BZ
5000 *Machine = WPA_STATE_MACHINE;
5001 EAPType =
51126deb 5002 *((u8 *) pFrame + LENGTH_802_11 +
96b3c83d 5003 LENGTH_802_1_H + 1);
51126deb 5004 return (WpaMsgTypeSubst(EAPType, (int *) MsgType));
91980990
GKH
5005 }
5006 }
91980990 5007
96b3c83d
BZ
5008 switch (pFrame->Hdr.FC.SubType) {
5009 case SUBTYPE_ASSOC_REQ:
5010 *Machine = ASSOC_STATE_MACHINE;
5011 *MsgType = MT2_PEER_ASSOC_REQ;
5012 break;
5013 case SUBTYPE_ASSOC_RSP:
5014 *Machine = ASSOC_STATE_MACHINE;
5015 *MsgType = MT2_PEER_ASSOC_RSP;
5016 break;
5017 case SUBTYPE_REASSOC_REQ:
5018 *Machine = ASSOC_STATE_MACHINE;
5019 *MsgType = MT2_PEER_REASSOC_REQ;
5020 break;
5021 case SUBTYPE_REASSOC_RSP:
5022 *Machine = ASSOC_STATE_MACHINE;
5023 *MsgType = MT2_PEER_REASSOC_RSP;
5024 break;
5025 case SUBTYPE_PROBE_REQ:
5026 *Machine = SYNC_STATE_MACHINE;
5027 *MsgType = MT2_PEER_PROBE_REQ;
5028 break;
5029 case SUBTYPE_PROBE_RSP:
5030 *Machine = SYNC_STATE_MACHINE;
5031 *MsgType = MT2_PEER_PROBE_RSP;
5032 break;
5033 case SUBTYPE_BEACON:
5034 *Machine = SYNC_STATE_MACHINE;
5035 *MsgType = MT2_PEER_BEACON;
5036 break;
5037 case SUBTYPE_ATIM:
5038 *Machine = SYNC_STATE_MACHINE;
5039 *MsgType = MT2_PEER_ATIM;
5040 break;
5041 case SUBTYPE_DISASSOC:
5042 *Machine = ASSOC_STATE_MACHINE;
5043 *MsgType = MT2_PEER_DISASSOC_REQ;
5044 break;
5045 case SUBTYPE_AUTH:
ec278fa2 5046 /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */
51126deb
BZ
5047 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(u16));
5048 NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(u16));
96b3c83d 5049 if (Seq == 1 || Seq == 3) {
ca97b838 5050 *Machine = AUTH_RSP_STATE_MACHINE;
96b3c83d
BZ
5051 *MsgType = MT2_PEER_AUTH_ODD;
5052 } else if (Seq == 2 || Seq == 4) {
5053 if (Alg == AUTH_MODE_OPEN || Alg == AUTH_MODE_KEY) {
5054 *Machine = AUTH_STATE_MACHINE;
5055 *MsgType = MT2_PEER_AUTH_EVEN;
5056 }
5057 } else {
5058 return FALSE;
91980990 5059 }
96b3c83d
BZ
5060 break;
5061 case SUBTYPE_DEAUTH:
5062 *Machine = AUTH_RSP_STATE_MACHINE;
5063 *MsgType = MT2_PEER_DEAUTH;
5064 break;
5065 case SUBTYPE_ACTION:
5066 *Machine = ACTION_STATE_MACHINE;
ec278fa2 5067 /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
96b3c83d
BZ
5068 if ((pFrame->Octet[0] & 0x7F) > MAX_PEER_CATE_MSG) {
5069 *MsgType = MT2_ACT_INVALID;
5070 } else {
5071 *MsgType = (pFrame->Octet[0] & 0x7F);
91980990 5072 }
96b3c83d
BZ
5073 break;
5074 default:
5075 return FALSE;
5076 break;
91980990
GKH
5077 }
5078
ca97b838 5079 return TRUE;
91980990
GKH
5080}
5081
ec278fa2
BZ
5082/* =========================================================================================== */
5083/* state_machine.c */
5084/* =========================================================================================== */
91980990 5085
ca97b838
BZ
5086/*! \brief Initialize the state machine.
5087 * \param *S pointer to the state machine
5088 * \param Trans State machine transition function
5089 * \param StNr number of states
5090 * \param MsgNr number of messages
5091 * \param DefFunc default function, when there is invalid state/message combination
5092 * \param InitState initial state of the state machine
5093 * \param Base StateMachine base, internal use only
5094 * \pre p_sm should be a legal pointer
5095 * \post
91980990 5096
ca97b838
BZ
5097 IRQL = PASSIVE_LEVEL
5098
5099 */
62eb734b 5100void StateMachineInit(struct rt_state_machine *S,
96b3c83d 5101 IN STATE_MACHINE_FUNC Trans[],
51126deb
BZ
5102 unsigned long StNr,
5103 unsigned long MsgNr,
96b3c83d 5104 IN STATE_MACHINE_FUNC DefFunc,
51126deb 5105 unsigned long InitState, unsigned long Base)
91980990 5106{
51126deb 5107 unsigned long i, j;
91980990 5108
ec278fa2 5109 /* set number of states and messages */
ca97b838 5110 S->NrState = StNr;
96b3c83d
BZ
5111 S->NrMsg = MsgNr;
5112 S->Base = Base;
91980990 5113
96b3c83d 5114 S->TransFunc = Trans;
ca97b838 5115
ec278fa2 5116 /* init all state transition to default function */
96b3c83d
BZ
5117 for (i = 0; i < StNr; i++) {
5118 for (j = 0; j < MsgNr; j++) {
ca97b838 5119 S->TransFunc[i * MsgNr + j] = DefFunc;
91980990 5120 }
91980990
GKH
5121 }
5122
ec278fa2 5123 /* set the starting state */
ca97b838
BZ
5124 S->CurrState = InitState;
5125}
5126
5127/*! \brief This function fills in the function pointer into the cell in the state machine
5128 * \param *S pointer to the state machine
5129 * \param St state
5130 * \param Msg incoming message
5131 * \param f the function to be executed when (state, message) combination occurs at the state machine
5132 * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state
5133 * \post
5134
5135 IRQL = PASSIVE_LEVEL
5136
5137 */
62eb734b 5138void StateMachineSetAction(struct rt_state_machine *S,
51126deb
BZ
5139 unsigned long St,
5140 unsigned long Msg, IN STATE_MACHINE_FUNC Func)
ca97b838 5141{
51126deb 5142 unsigned long MsgIdx;
ca97b838
BZ
5143
5144 MsgIdx = Msg - S->Base;
5145
96b3c83d 5146 if (St < S->NrState && MsgIdx < S->NrMsg) {
ec278fa2 5147 /* boundary checking before setting the action */
ca97b838 5148 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
91980990
GKH
5149 }
5150}
ca97b838
BZ
5151
5152/*! \brief This function does the state transition
5153 * \param *Adapter the NIC adapter pointer
5154 * \param *S the state machine
5155 * \param *Elem the message to be executed
5156 * \return None
5157
5158 IRQL = DISPATCH_LEVEL
5159
5160 */
62eb734b
BZ
5161void StateMachinePerformAction(struct rt_rtmp_adapter *pAd,
5162 struct rt_state_machine *S, struct rt_mlme_queue_elem *Elem)
ca97b838 5163{
96b3c83d
BZ
5164 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))
5165 (pAd, Elem);
ca97b838
BZ
5166}
5167
91980990 5168/*
ca97b838 5169 ==========================================================================
91980990 5170 Description:
ca97b838
BZ
5171 The drop function, when machine executes this, the message is simply
5172 ignored. This function does nothing, the message is freed in
5173 StateMachinePerformAction()
5174 ==========================================================================
5175 */
62eb734b 5176void Drop(struct rt_rtmp_adapter *pAd, struct rt_mlme_queue_elem *Elem)
91980990 5177{
91980990
GKH
5178}
5179
ec278fa2
BZ
5180/* =========================================================================================== */
5181/* lfsr.c */
5182/* =========================================================================================== */
91980990 5183
ca97b838
BZ
5184/*
5185 ==========================================================================
5186 Description:
91980990 5187
ca97b838 5188 IRQL = PASSIVE_LEVEL
91980990 5189
ca97b838
BZ
5190 ==========================================================================
5191 */
62eb734b 5192void LfsrInit(struct rt_rtmp_adapter *pAd, unsigned long Seed)
91980990 5193{
ca97b838
BZ
5194 if (Seed == 0)
5195 pAd->Mlme.ShiftReg = 1;
5196 else
5197 pAd->Mlme.ShiftReg = Seed;
5198}
91980990 5199
ca97b838
BZ
5200/*
5201 ==========================================================================
5202 Description:
5203 ==========================================================================
5204 */
62eb734b 5205u8 RandomByte(struct rt_rtmp_adapter *pAd)
ca97b838 5206{
51126deb
BZ
5207 unsigned long i;
5208 u8 R, Result;
91980990 5209
ca97b838 5210 R = 0;
91980990 5211
ca97b838 5212 if (pAd->Mlme.ShiftReg == 0)
51126deb 5213 NdisGetSystemUpTime((unsigned long *) & pAd->Mlme.ShiftReg);
91980990 5214
96b3c83d
BZ
5215 for (i = 0; i < 8; i++) {
5216 if (pAd->Mlme.ShiftReg & 0x00000001) {
5217 pAd->Mlme.ShiftReg =
5218 ((pAd->Mlme.
5219 ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
ca97b838 5220 Result = 1;
96b3c83d 5221 } else {
ca97b838
BZ
5222 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5223 Result = 0;
5224 }
5225 R = (R << 1) | Result;
91980990 5226 }
91980990 5227
ca97b838 5228 return R;
91980990 5229}
ca97b838 5230
91980990
GKH
5231/*
5232 ========================================================================
5233
5234 Routine Description:
5235 Verify the support rate for different PHY type
5236
5237 Arguments:
5238 pAd Pointer to our adapter
5239
5240 Return Value:
5241 None
5242
5243 IRQL = PASSIVE_LEVEL
5244
5245 ========================================================================
5246*/
62eb734b 5247void RTMPCheckRates(struct rt_rtmp_adapter *pAd,
51126deb 5248 IN u8 SupRate[], IN u8 * SupRateLen)
91980990 5249{
51126deb
BZ
5250 u8 RateIdx, i, j;
5251 u8 NewRate[12], NewRateLen;
91980990
GKH
5252
5253 NewRateLen = 0;
5254
5255 if (pAd->CommonCfg.PhyMode == PHY_11B)
5256 RateIdx = 4;
5257 else
5258 RateIdx = 12;
5259
ec278fa2 5260 /* Check for support rates exclude basic rate bit */
91980990
GKH
5261 for (i = 0; i < *SupRateLen; i++)
5262 for (j = 0; j < RateIdx; j++)
5263 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
5264 NewRate[NewRateLen++] = SupRate[i];
5265
5266 *SupRateLen = NewRateLen;
5267 NdisMoveMemory(SupRate, NewRate, NewRateLen);
5268}
5269
62eb734b 5270BOOLEAN RTMPCheckChannel(struct rt_rtmp_adapter *pAd,
51126deb 5271 u8 CentralChannel, u8 Channel)
91980990 5272{
51126deb
BZ
5273 u8 k;
5274 u8 UpperChannel = 0, LowerChannel = 0;
5275 u8 NoEffectChannelinList = 0;
91980990 5276
ec278fa2 5277 /* Find upper and lower channel according to 40MHz current operation. */
96b3c83d 5278 if (CentralChannel < Channel) {
91980990
GKH
5279 UpperChannel = Channel;
5280 if (CentralChannel > 2)
5281 LowerChannel = CentralChannel - 2;
5282 else
5283 return FALSE;
96b3c83d 5284 } else if (CentralChannel > Channel) {
91980990
GKH
5285 UpperChannel = CentralChannel + 2;
5286 LowerChannel = Channel;
5287 }
5288
96b3c83d
BZ
5289 for (k = 0; k < pAd->ChannelListNum; k++) {
5290 if (pAd->ChannelList[k].Channel == UpperChannel) {
5291 NoEffectChannelinList++;
91980990 5292 }
96b3c83d
BZ
5293 if (pAd->ChannelList[k].Channel == LowerChannel) {
5294 NoEffectChannelinList++;
91980990
GKH
5295 }
5296 }
5297
96b3c83d
BZ
5298 DBGPRINT(RT_DEBUG_TRACE,
5299 ("Total Channel in Channel List = [%d]\n",
5300 NoEffectChannelinList));
91980990
GKH
5301 if (NoEffectChannelinList == 2)
5302 return TRUE;
5303 else
5304 return FALSE;
5305}
5306
5307/*
5308 ========================================================================
5309
5310 Routine Description:
5311 Verify the support rate for HT phy type
5312
5313 Arguments:
5314 pAd Pointer to our adapter
5315
5316 Return Value:
5317 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
5318
5319 IRQL = PASSIVE_LEVEL
5320
5321 ========================================================================
5322*/
62eb734b 5323BOOLEAN RTMPCheckHt(struct rt_rtmp_adapter *pAd,
51126deb 5324 u8 Wcid,
62eb734b
BZ
5325 struct rt_ht_capability_ie * pHtCapability,
5326 struct rt_add_ht_info_ie * pAddHtInfo)
91980990
GKH
5327{
5328 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
5329 return FALSE;
5330
ec278fa2 5331 /* If use AMSDU, set flag. */
91980990 5332 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
96b3c83d
BZ
5333 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5334 fCLIENT_STATUS_AMSDU_INUSED);
ec278fa2 5335 /* Save Peer Capability */
91980990 5336 if (pHtCapability->HtCapInfo.ShortGIfor20)
96b3c83d
BZ
5337 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5338 fCLIENT_STATUS_SGI20_CAPABLE);
91980990 5339 if (pHtCapability->HtCapInfo.ShortGIfor40)
96b3c83d
BZ
5340 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5341 fCLIENT_STATUS_SGI40_CAPABLE);
91980990 5342 if (pHtCapability->HtCapInfo.TxSTBC)
96b3c83d
BZ
5343 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5344 fCLIENT_STATUS_TxSTBC_CAPABLE);
91980990 5345 if (pHtCapability->HtCapInfo.RxSTBC)
96b3c83d
BZ
5346 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5347 fCLIENT_STATUS_RxSTBC_CAPABLE);
5348 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport) {
5349 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid],
5350 fCLIENT_STATUS_RDG_CAPABLE);
91980990
GKH
5351 }
5352
96b3c83d
BZ
5353 if (Wcid < MAX_LEN_OF_MAC_TABLE) {
5354 pAd->MacTab.Content[Wcid].MpduDensity =
5355 pHtCapability->HtCapParm.MpduDensity;
91980990 5356 }
ec278fa2 5357 /* Will check ChannelWidth for MCSSet[4] below */
91980990 5358 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
96b3c83d
BZ
5359 switch (pAd->CommonCfg.RxStream) {
5360 case 1:
5361 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5362 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
5363 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5364 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5365 break;
5366 case 2:
5367 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5368 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5369 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
5370 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5371 break;
5372 case 3:
5373 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
5374 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
5375 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
5376 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
5377 break;
5378 }
5379
5380 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth =
5381 pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.
5382 ChannelWidth;
5383
5384 DBGPRINT(RT_DEBUG_TRACE,
5385 ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
5386 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth,
5387 pAddHtInfo->AddHtInfo.RecomWidth,
5388 pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
5389 pAd->NicConfig2.field.BW40MAvailForA,
5390 pAd->NicConfig2.field.BW40MAvailForG,
5391 pAd->CommonCfg.PhyMode));
5392
5393 pAd->MlmeAux.HtCapability.HtCapInfo.GF =
5394 pHtCapability->HtCapInfo.GF & pAd->CommonCfg.DesiredHtPhy.GF;
91980990 5395
ec278fa2 5396 /* Send Assoc Req with my HT capability. */
96b3c83d
BZ
5397 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize =
5398 pAd->CommonCfg.DesiredHtPhy.AmsduSize;
5399 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs =
5400 pAd->CommonCfg.DesiredHtPhy.MimoPs;
5401 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 =
5402 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->
5403 HtCapInfo.
5404 ShortGIfor20);
5405 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 =
5406 (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->
5407 HtCapInfo.
5408 ShortGIfor40);
5409 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC =
5410 (pAd->CommonCfg.DesiredHtPhy.TxSTBC) & (pHtCapability->HtCapInfo.
5411 RxSTBC);
5412 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC =
5413 (pAd->CommonCfg.DesiredHtPhy.RxSTBC) & (pHtCapability->HtCapInfo.
5414 TxSTBC);
5415 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor =
5416 pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
5417 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity =
5418 pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
5419 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC =
5420 pHtCapability->ExtHtCapInfo.PlusHTC;
5421 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC =
5422 pHtCapability->ExtHtCapInfo.PlusHTC;
5423 if (pAd->CommonCfg.bRdg) {
5424 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport =
5425 pHtCapability->ExtHtCapInfo.RDGSupport;
5426 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
5427 }
5428
5429 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
ec278fa2 5430 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; /* BW20 can't transmit MCS32 */
91980990
GKH
5431
5432 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
5433 return TRUE;
5434}
91980990
GKH
5435
5436/*
5437 ========================================================================
5438
5439 Routine Description:
5440 Verify the support rate for different PHY type
5441
5442 Arguments:
5443 pAd Pointer to our adapter
5444
5445 Return Value:
5446 None
5447
5448 IRQL = PASSIVE_LEVEL
5449
5450 ========================================================================
5451*/
62eb734b 5452void RTMPUpdateMlmeRate(struct rt_rtmp_adapter *pAd)
91980990 5453{
51126deb
BZ
5454 u8 MinimumRate;
5455 u8 ProperMlmeRate; /*= RATE_54; */
5456 u8 i, j, RateIdx = 12; /*1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
96b3c83d
BZ
5457 BOOLEAN bMatch = FALSE;
5458
5459 switch (pAd->CommonCfg.PhyMode) {
5460 case PHY_11B:
5461 ProperMlmeRate = RATE_11;
5462 MinimumRate = RATE_1;
5463 break;
5464 case PHY_11BG_MIXED:
5465 case PHY_11ABGN_MIXED:
5466 case PHY_11BGN_MIXED:
5467 if ((pAd->MlmeAux.SupRateLen == 4) &&
5468 (pAd->MlmeAux.ExtRateLen == 0))
ec278fa2 5469 /* B only AP */
91980990 5470 ProperMlmeRate = RATE_11;
96b3c83d 5471 else
91980990 5472 ProperMlmeRate = RATE_24;
96b3c83d
BZ
5473
5474 if (pAd->MlmeAux.Channel <= 14)
5475 MinimumRate = RATE_1;
5476 else
91980990 5477 MinimumRate = RATE_6;
96b3c83d
BZ
5478 break;
5479 case PHY_11A:
ec278fa2 5480 case PHY_11N_2_4G: /* rt2860 need to check mlmerate for 802.11n */
96b3c83d
BZ
5481 case PHY_11GN_MIXED:
5482 case PHY_11AGN_MIXED:
5483 case PHY_11AN_MIXED:
5484 case PHY_11N_5G:
5485 ProperMlmeRate = RATE_24;
5486 MinimumRate = RATE_6;
5487 break;
5488 case PHY_11ABG_MIXED:
5489 ProperMlmeRate = RATE_24;
5490 if (pAd->MlmeAux.Channel <= 14)
91980990 5491 MinimumRate = RATE_1;
96b3c83d
BZ
5492 else
5493 MinimumRate = RATE_6;
5494 break;
ec278fa2 5495 default: /* error */
96b3c83d
BZ
5496 ProperMlmeRate = RATE_1;
5497 MinimumRate = RATE_1;
5498 break;
5499 }
5500
5501 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++) {
5502 for (j = 0; j < RateIdx; j++) {
5503 if ((pAd->MlmeAux.SupRate[i] & 0x7f) ==
5504 RateIdTo500Kbps[j]) {
5505 if (j == ProperMlmeRate) {
91980990
GKH
5506 bMatch = TRUE;
5507 break;
5508 }
5509 }
5510 }
5511
5512 if (bMatch)
5513 break;
5514 }
5515
96b3c83d
BZ
5516 if (bMatch == FALSE) {
5517 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++) {
5518 for (j = 0; j < RateIdx; j++) {
5519 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) ==
5520 RateIdTo500Kbps[j]) {
5521 if (j == ProperMlmeRate) {
91980990
GKH
5522 bMatch = TRUE;
5523 break;
5524 }
5525 }
5526 }
5527
5528 if (bMatch)
5529 break;
5530 }
5531 }
5532
96b3c83d 5533 if (bMatch == FALSE) {
91980990
GKH
5534 ProperMlmeRate = MinimumRate;
5535 }
5536
5537 pAd->CommonCfg.MlmeRate = MinimumRate;
5538 pAd->CommonCfg.RtsRate = ProperMlmeRate;
96b3c83d 5539 if (pAd->CommonCfg.MlmeRate >= RATE_6) {
91980990 5540 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
96b3c83d
BZ
5541 pAd->CommonCfg.MlmeTransmit.field.MCS =
5542 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5543 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5544 MODE_OFDM;
5545 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5546 OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
5547 } else {
91980990
GKH
5548 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
5549 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
96b3c83d
BZ
5550 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE =
5551 MODE_CCK;
5552 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS =
5553 pAd->CommonCfg.MlmeRate;
91980990
GKH
5554 }
5555
96b3c83d
BZ
5556 DBGPRINT(RT_DEBUG_TRACE,
5557 ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n",
5558 pAd->CommonCfg.MlmeTransmit.word));
91980990
GKH
5559}
5560
62eb734b 5561char RTMPMaxRssi(struct rt_rtmp_adapter *pAd,
51126deb 5562 char Rssi0, char Rssi1, char Rssi2)
91980990 5563{
51126deb 5564 char larger = -127;
91980990 5565
96b3c83d 5566 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0)) {
91980990
GKH
5567 larger = Rssi0;
5568 }
5569
96b3c83d 5570 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0)) {
91980990
GKH
5571 larger = max(Rssi0, Rssi1);
5572 }
5573
96b3c83d 5574 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0)) {
91980990
GKH
5575 larger = max(larger, Rssi2);
5576 }
5577
5578 if (larger == -127)
5579 larger = 0;
5580
5581 return larger;
5582}
5583
5584/*
5585 ========================================================================
5586 Routine Description:
5587 Periodic evaluate antenna link status
5588
5589 Arguments:
5590 pAd - Adapter pointer
5591
5592 Return Value:
5593 None
5594
5595 ========================================================================
5596*/
62eb734b 5597void AsicEvaluateRxAnt(struct rt_rtmp_adapter *pAd)
91980990 5598{
51126deb 5599 u8 BBPR3 = 0;
91980990 5600
e932e724 5601 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
96b3c83d
BZ
5602 fRTMP_ADAPTER_HALT_IN_PROGRESS |
5603 fRTMP_ADAPTER_RADIO_OFF |
5604 fRTMP_ADAPTER_NIC_NOT_EXIST |
5605 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
5606 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
ca97b838 5607#ifdef RT30xx
96b3c83d 5608 || (pAd->EepromAccess)
ec278fa2 5609#endif /* RT30xx // */
e44fd1cf 5610#ifdef RT3090
96b3c83d 5611 || (pAd->bPCIclkOff == TRUE)
ec278fa2 5612#endif /* RT3090 // */
96b3c83d
BZ
5613 )
5614 return;
59fe2d89 5615
ca97b838 5616 {
ec278fa2
BZ
5617 /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5618 /* return; */
59fe2d89 5619
96b3c83d 5620 {
ca97b838 5621
96b3c83d
BZ
5622 if (pAd->StaCfg.Psm == PWR_SAVE)
5623 return;
59fe2d89 5624
96b3c83d
BZ
5625 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5626 BBPR3 &= (~0x18);
5627 if (pAd->Antenna.field.RxPath == 3) {
5628 BBPR3 |= (0x10);
5629 } else if (pAd->Antenna.field.RxPath == 2) {
5630 BBPR3 |= (0x8);
5631 } else if (pAd->Antenna.field.RxPath == 1) {
5632 BBPR3 |= (0x0);
5633 }
5634 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
ca97b838 5635#ifdef RTMP_MAC_PCI
96b3c83d 5636 pAd->StaCfg.BBPR3 = BBPR3;
ec278fa2 5637#endif /* RTMP_MAC_PCI // */
96b3c83d
BZ
5638 if (OPSTATUS_TEST_FLAG
5639 (pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5640 ) {
51126deb 5641 unsigned long TxTotalCnt =
96b3c83d
BZ
5642 pAd->RalinkCounters.OneSecTxNoRetryOkCount +
5643 pAd->RalinkCounters.OneSecTxRetryOkCount +
5644 pAd->RalinkCounters.OneSecTxFailCount;
5645
ec278fa2 5646 /* dynamic adjust antenna evaluation period according to the traffic */
96b3c83d
BZ
5647 if (TxTotalCnt > 50) {
5648 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5649 20);
5650 pAd->Mlme.bLowThroughput = FALSE;
5651 } else {
5652 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer,
5653 300);
5654 pAd->Mlme.bLowThroughput = TRUE;
5655 }
5656 }
ca97b838
BZ
5657 }
5658
5659 }
5660
91980990
GKH
5661}
5662
5663/*
5664 ========================================================================
5665 Routine Description:
5666 After evaluation, check antenna link status
5667
5668 Arguments:
5669 pAd - Adapter pointer
5670
5671 Return Value:
5672 None
5673
5674 ========================================================================
5675*/
51126deb
BZ
5676void AsicRxAntEvalTimeout(void *SystemSpecific1,
5677 void *FunctionContext,
5678 void *SystemSpecific2, void *SystemSpecific3)
91980990 5679{
62eb734b 5680 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
51126deb
BZ
5681 u8 BBPR3 = 0;
5682 char larger = -127, rssi0, rssi1, rssi2;
96b3c83d
BZ
5683
5684 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
5685 fRTMP_ADAPTER_HALT_IN_PROGRESS |
5686 fRTMP_ADAPTER_RADIO_OFF |
5687 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
5688 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
ca97b838 5689#ifdef RT30xx
96b3c83d 5690 || (pAd->EepromAccess)
ec278fa2 5691#endif /* RT30xx // */
e44fd1cf 5692#ifdef RT3090
96b3c83d 5693 || (pAd->bPCIclkOff == TRUE)
ec278fa2 5694#endif /* RT3090 // */
96b3c83d 5695 )
59fe2d89
BZ
5696 return;
5697
5698 {
ec278fa2
BZ
5699 /*if (pAd->StaCfg.Psm == PWR_SAVE) */
5700 /* return; */
59fe2d89
BZ
5701 {
5702 if (pAd->StaCfg.Psm == PWR_SAVE)
5703 return;
5704
ec278fa2 5705 /* if the traffic is low, use average rssi as the criteria */
96b3c83d 5706 if (pAd->Mlme.bLowThroughput == TRUE) {
59fe2d89
BZ
5707 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
5708 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
5709 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
96b3c83d 5710 } else {
59fe2d89
BZ
5711 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
5712 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
5713 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
5714 }
5715
96b3c83d 5716 if (pAd->Antenna.field.RxPath == 3) {
59fe2d89
BZ
5717 larger = max(rssi0, rssi1);
5718
5719 if (larger > (rssi2 + 20))
5720 pAd->Mlme.RealRxPath = 2;
5721 else
5722 pAd->Mlme.RealRxPath = 3;
96b3c83d 5723 } else if (pAd->Antenna.field.RxPath == 2) {
59fe2d89
BZ
5724 if (rssi0 > (rssi1 + 20))
5725 pAd->Mlme.RealRxPath = 1;
5726 else
5727 pAd->Mlme.RealRxPath = 2;
5728 }
5729
5730 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
5731 BBPR3 &= (~0x18);
96b3c83d 5732 if (pAd->Mlme.RealRxPath == 3) {
59fe2d89 5733 BBPR3 |= (0x10);
96b3c83d 5734 } else if (pAd->Mlme.RealRxPath == 2) {
59fe2d89 5735 BBPR3 |= (0x8);
96b3c83d 5736 } else if (pAd->Mlme.RealRxPath == 1) {
59fe2d89
BZ
5737 BBPR3 |= (0x0);
5738 }
5739 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
ca97b838 5740#ifdef RTMP_MAC_PCI
331e0c16 5741 pAd->StaCfg.BBPR3 = BBPR3;
ec278fa2 5742#endif /* RTMP_MAC_PCI // */
59fe2d89
BZ
5743 }
5744 }
ca97b838 5745
91980990
GKH
5746}
5747
51126deb
BZ
5748void APSDPeriodicExec(void *SystemSpecific1,
5749 void *FunctionContext,
5750 void *SystemSpecific2, void *SystemSpecific3)
91980990 5751{
62eb734b 5752 struct rt_rtmp_adapter *pAd = (struct rt_rtmp_adapter *)FunctionContext;
91980990
GKH
5753
5754 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
5755 return;
5756
5757 pAd->CommonCfg.TriggerTimerCount++;
5758
ec278fa2 5759/* Driver should not send trigger frame, it should be send by application layer */
ca97b838
BZ
5760/*
5761 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
5762 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
5763 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
5764 {
5765 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
5766 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
5767 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
5768 pAd->CommonCfg.TriggerTimerCount = 0;
5769 pAd->CommonCfg.bInServicePeriod = TRUE;
5770 }*/
91980990
GKH
5771}
5772
5773/*
5774 ========================================================================
5775 Routine Description:
5776 Set/reset MAC registers according to bPiggyBack parameter
5777
5778 Arguments:
5779 pAd - Adapter pointer
5780 bPiggyBack - Enable / Disable Piggy-Back
5781
5782 Return Value:
5783 None
5784
5785 ========================================================================
5786*/
62eb734b 5787void RTMPSetPiggyBack(struct rt_rtmp_adapter *pAd, IN BOOLEAN bPiggyBack)
91980990 5788{
96b3c83d 5789 TX_LINK_CFG_STRUC TxLinkCfg;
91980990
GKH
5790
5791 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
5792
5793 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
5794 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
5795}
5796
5797/*
5798 ========================================================================
5799 Routine Description:
5800 check if this entry need to switch rate automatically
5801
5802 Arguments:
5803 pAd
5804 pEntry
5805
5806 Return Value:
5807 TURE
5808 FALSE
5809
5810 ========================================================================
5811*/
62eb734b
BZ
5812BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(struct rt_rtmp_adapter *pAd,
5813 struct rt_mac_table_entry *pEntry)
91980990 5814{
96b3c83d 5815 BOOLEAN result = TRUE;
91980990 5816
91980990 5817 {
ec278fa2 5818 /* only associated STA counts */
96b3c83d
BZ
5819 if (pEntry && (pEntry->ValidAsCLI)
5820 && (pEntry->Sst == SST_ASSOC)) {
91980990 5821 result = pAd->StaCfg.bAutoTxRateSwitch;
96b3c83d 5822 } else
91980990 5823 result = FALSE;
91980990 5824 }
91980990
GKH
5825
5826 return result;
5827}
5828
62eb734b 5829BOOLEAN RTMPAutoRateSwitchCheck(struct rt_rtmp_adapter *pAd)
91980990 5830{
ca97b838 5831 {
96b3c83d
BZ
5832 if (pAd->StaCfg.bAutoTxRateSwitch)
5833 return TRUE;
ca97b838 5834 }
91980990
GKH
5835 return FALSE;
5836}
5837
91980990
GKH
5838/*
5839 ========================================================================
5840 Routine Description:
5841 check if this entry need to fix tx legacy rate
5842
5843 Arguments:
5844 pAd
5845 pEntry
5846
5847 Return Value:
5848 TURE
5849 FALSE
5850
5851 ========================================================================
5852*/
62eb734b 5853u8 RTMPStaFixedTxMode(struct rt_rtmp_adapter *pAd, struct rt_mac_table_entry *pEntry)
91980990 5854{
51126deb 5855 u8 tx_mode = FIXED_TXMODE_HT;
91980990 5856
ca97b838 5857 {
96b3c83d 5858 tx_mode =
51126deb 5859 (u8)pAd->StaCfg.DesiredTransmitSetting.field.
96b3c83d 5860 FixedTxMode;
ca97b838 5861 }
91980990
GKH
5862
5863 return tx_mode;
5864}
5865
5866/*
5867 ========================================================================
5868 Routine Description:
5869 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
5870
5871 Arguments:
5872 pAd
5873 pEntry
5874
5875 Return Value:
5876 TURE
5877 FALSE
5878
5879 ========================================================================
5880*/
62eb734b 5881void RTMPUpdateLegacyTxSetting(u8 fixed_tx_mode, struct rt_mac_table_entry *pEntry)
91980990
GKH
5882{
5883 HTTRANSMIT_SETTING TransmitSetting;
5884
5885 if (fixed_tx_mode == FIXED_TXMODE_HT)
5886 return;
5887
5888 TransmitSetting.word = 0;
5889
5890 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
5891 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
5892
96b3c83d 5893 if (fixed_tx_mode == FIXED_TXMODE_CCK) {
91980990 5894 TransmitSetting.field.MODE = MODE_CCK;
ec278fa2 5895 /* CCK mode allow MCS 0~3 */
91980990
GKH
5896 if (TransmitSetting.field.MCS > MCS_3)
5897 TransmitSetting.field.MCS = MCS_3;
96b3c83d 5898 } else {
91980990 5899 TransmitSetting.field.MODE = MODE_OFDM;
ec278fa2 5900 /* OFDM mode allow MCS 0~7 */
91980990
GKH
5901 if (TransmitSetting.field.MCS > MCS_7)
5902 TransmitSetting.field.MCS = MCS_7;
5903 }
5904
96b3c83d 5905 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) {
91980990 5906 pEntry->HTPhyMode.word = TransmitSetting.word;
96b3c83d
BZ
5907 DBGPRINT(RT_DEBUG_TRACE,
5908 ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
5909 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE),
5910 pEntry->HTPhyMode.field.MCS));
91980990
GKH
5911 }
5912}
5913
91980990
GKH
5914/*
5915 ==========================================================================
5916 Description:
5917 dynamic tune BBP R66 to find a balance between sensibility and
5918 noise isolation
5919
5920 IRQL = DISPATCH_LEVEL
5921
5922 ==========================================================================
5923 */
62eb734b 5924void AsicStaBbpTuning(struct rt_rtmp_adapter *pAd)
91980990 5925{
51126deb
BZ
5926 u8 OrigR66Value = 0, R66; /*, R66UpperBound = 0x30, R66LowerBound = 0x30; */
5927 char Rssi;
91980990 5928
ec278fa2 5929 /* 2860C did not support Fase CCA, therefore can't tune */
91980990
GKH
5930 if (pAd->MACVersion == 0x28600100)
5931 return;
5932
ec278fa2
BZ
5933 /* */
5934 /* work as a STA */
5935 /* */
5936 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) /* no R66 tuning when SCANNING */
91980990
GKH
5937 return;
5938
5939 if ((pAd->OpMode == OPMODE_STA)
96b3c83d
BZ
5940 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
5941 )
5942 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
ca97b838 5943#ifdef RTMP_MAC_PCI
96b3c83d 5944 && (pAd->bPCIclkOff == FALSE)
ec278fa2 5945#endif /* RTMP_MAC_PCI // */
96b3c83d 5946 ) {
91980990
GKH
5947 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
5948 R66 = OrigR66Value;
5949
5950 if (pAd->Antenna.field.RxPath > 1)
96b3c83d
BZ
5951 Rssi =
5952 (pAd->StaCfg.RssiSample.AvgRssi0 +
5953 pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
91980990
GKH
5954 else
5955 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
5956
ec278fa2 5957 if (pAd->LatchRfRegs.Channel <= 14) { /*BG band */
ca97b838 5958#ifdef RT30xx
ec278fa2
BZ
5959 /* RT3070 is a no LNA solution, it should have different control regarding to AGC gain control */
5960 /* Otherwise, it will have some throughput side effect when low RSSI */
ca97b838 5961
96b3c83d
BZ
5962 if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
5963 || IS_RT3390(pAd)) {
5964 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5965 R66 =
5966 0x1C + 2 * GET_LNA_GAIN(pAd) + 0x20;
5967 if (OrigR66Value != R66) {
5968 RTMP_BBP_IO_WRITE8_BY_REG_ID
5969 (pAd, BBP_R66, R66);
5970 }
5971 } else {
5972 R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
5973 if (OrigR66Value != R66) {
5974 RTMP_BBP_IO_WRITE8_BY_REG_ID
5975 (pAd, BBP_R66, R66);
5976 }
59fe2d89 5977 }
96b3c83d 5978 } else
ec278fa2 5979#endif /* RT30xx // */
91980990 5980 {
96b3c83d 5981 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
91980990 5982 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
96b3c83d
BZ
5983 if (OrigR66Value != R66) {
5984 RTMP_BBP_IO_WRITE8_BY_REG_ID
5985 (pAd, BBP_R66, R66);
91980990 5986 }
96b3c83d 5987 } else {
91980990 5988 R66 = 0x2E + GET_LNA_GAIN(pAd);
96b3c83d
BZ
5989 if (OrigR66Value != R66) {
5990 RTMP_BBP_IO_WRITE8_BY_REG_ID
5991 (pAd, BBP_R66, R66);
91980990
GKH
5992 }
5993 }
5994 }
ec278fa2 5995 } else { /*A band */
96b3c83d
BZ
5996 if (pAd->CommonCfg.BBPCurrentBW == BW_20) {
5997 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
5998 R66 =
5999 0x32 + (GET_LNA_GAIN(pAd) * 5) / 3 +
6000 0x10;
6001 if (OrigR66Value != R66) {
6002 RTMP_BBP_IO_WRITE8_BY_REG_ID
6003 (pAd, BBP_R66, R66);
91980990 6004 }
96b3c83d
BZ
6005 } else {
6006 R66 =
6007 0x32 + (GET_LNA_GAIN(pAd) * 5) / 3;
6008 if (OrigR66Value != R66) {
6009 RTMP_BBP_IO_WRITE8_BY_REG_ID
6010 (pAd, BBP_R66, R66);
91980990
GKH
6011 }
6012 }
96b3c83d
BZ
6013 } else {
6014 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY) {
6015 R66 =
6016 0x3A + (GET_LNA_GAIN(pAd) * 5) / 3 +
6017 0x10;
6018 if (OrigR66Value != R66) {
6019 RTMP_BBP_IO_WRITE8_BY_REG_ID
6020 (pAd, BBP_R66, R66);
91980990 6021 }
96b3c83d
BZ
6022 } else {
6023 R66 =
6024 0x3A + (GET_LNA_GAIN(pAd) * 5) / 3;
6025 if (OrigR66Value != R66) {
6026 RTMP_BBP_IO_WRITE8_BY_REG_ID
6027 (pAd, BBP_R66, R66);
91980990
GKH
6028 }
6029 }
6030 }
6031 }
6032
91980990
GKH
6033 }
6034}
ed291e80 6035
62eb734b 6036void RTMPSetAGCInitValue(struct rt_rtmp_adapter *pAd, u8 BandWidth)
91980990 6037{
51126deb 6038 u8 R66 = 0x30;
91980990 6039
ec278fa2 6040 if (pAd->LatchRfRegs.Channel <= 14) { /* BG band */
ca97b838
BZ
6041#ifdef RT30xx
6042 /* Gary was verified Amazon AP and find that RT307x has BBP_R66 invalid default value */
6043
96b3c83d
BZ
6044 if (IS_RT3070(pAd) || IS_RT3090(pAd) || IS_RT3572(pAd)
6045 || IS_RT3390(pAd)) {
6046 R66 = 0x1C + 2 * GET_LNA_GAIN(pAd);
ca97b838 6047 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
96b3c83d 6048 } else
ec278fa2 6049#endif /* RT30xx // */
ca97b838 6050 {
96b3c83d 6051 R66 = 0x2E + GET_LNA_GAIN(pAd);
91980990
GKH
6052 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6053 }
ec278fa2 6054 } else { /*A band */
91980990 6055 {
96b3c83d
BZ
6056 if (BandWidth == BW_20) {
6057 R66 =
51126deb 6058 (u8)(0x32 +
96b3c83d
BZ
6059 (GET_LNA_GAIN(pAd) * 5) / 3);
6060 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6061 } else {
6062 R66 =
51126deb 6063 (u8)(0x3A +
96b3c83d
BZ
6064 (GET_LNA_GAIN(pAd) * 5) / 3);
6065 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
6066 }
91980990 6067 }
91980990 6068 }
91980990 6069
91980990 6070}