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