Staging: rt2860: remove dead DOT11N_DRAFT3 code
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / rt2860 / common / mlme.c
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 #ifdef CONFIG_STA_SUPPORT
54 #ifdef DOT11_N_SUPPORT
55 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
56 #endif // DOT11_N_SUPPORT //
57 #endif // CONFIG_STA_SUPPORT //
58
59 UCHAR RateSwitchTable[] = {
60 // 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)
61 0x11, 0x00, 0, 0, 0, // Initial used item after association
62 0x00, 0x00, 0, 40, 101,
63 0x01, 0x00, 1, 40, 50,
64 0x02, 0x00, 2, 35, 45,
65 0x03, 0x00, 3, 20, 45,
66 0x04, 0x21, 0, 30, 50,
67 0x05, 0x21, 1, 20, 50,
68 0x06, 0x21, 2, 20, 50,
69 0x07, 0x21, 3, 15, 50,
70 0x08, 0x21, 4, 15, 30,
71 0x09, 0x21, 5, 10, 25,
72 0x0a, 0x21, 6, 8, 25,
73 0x0b, 0x21, 7, 8, 25,
74 0x0c, 0x20, 12, 15, 30,
75 0x0d, 0x20, 13, 8, 20,
76 0x0e, 0x20, 14, 8, 20,
77 0x0f, 0x20, 15, 8, 25,
78 0x10, 0x22, 15, 8, 25,
79 0x11, 0x00, 0, 0, 0,
80 0x12, 0x00, 0, 0, 0,
81 0x13, 0x00, 0, 0, 0,
82 0x14, 0x00, 0, 0, 0,
83 0x15, 0x00, 0, 0, 0,
84 0x16, 0x00, 0, 0, 0,
85 0x17, 0x00, 0, 0, 0,
86 0x18, 0x00, 0, 0, 0,
87 0x19, 0x00, 0, 0, 0,
88 0x1a, 0x00, 0, 0, 0,
89 0x1b, 0x00, 0, 0, 0,
90 0x1c, 0x00, 0, 0, 0,
91 0x1d, 0x00, 0, 0, 0,
92 0x1e, 0x00, 0, 0, 0,
93 0x1f, 0x00, 0, 0, 0,
94 };
95
96 UCHAR RateSwitchTable11B[] = {
97 // 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)
98 0x04, 0x03, 0, 0, 0, // Initial used item after association
99 0x00, 0x00, 0, 40, 101,
100 0x01, 0x00, 1, 40, 50,
101 0x02, 0x00, 2, 35, 45,
102 0x03, 0x00, 3, 20, 45,
103 };
104
105 UCHAR RateSwitchTable11BG[] = {
106 // 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)
107 0x0a, 0x00, 0, 0, 0, // Initial used item after association
108 0x00, 0x00, 0, 40, 101,
109 0x01, 0x00, 1, 40, 50,
110 0x02, 0x00, 2, 35, 45,
111 0x03, 0x00, 3, 20, 45,
112 0x04, 0x10, 2, 20, 35,
113 0x05, 0x10, 3, 16, 35,
114 0x06, 0x10, 4, 10, 25,
115 0x07, 0x10, 5, 16, 25,
116 0x08, 0x10, 6, 10, 25,
117 0x09, 0x10, 7, 10, 13,
118 };
119
120 UCHAR RateSwitchTable11G[] = {
121 // 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)
122 0x08, 0x00, 0, 0, 0, // Initial used item after association
123 0x00, 0x10, 0, 20, 101,
124 0x01, 0x10, 1, 20, 35,
125 0x02, 0x10, 2, 20, 35,
126 0x03, 0x10, 3, 16, 35,
127 0x04, 0x10, 4, 10, 25,
128 0x05, 0x10, 5, 16, 25,
129 0x06, 0x10, 6, 10, 25,
130 0x07, 0x10, 7, 10, 13,
131 };
132
133 #ifdef DOT11_N_SUPPORT
134 UCHAR RateSwitchTable11N1S[] = {
135 // 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)
136 0x09, 0x00, 0, 0, 0, // Initial used item after association
137 0x00, 0x21, 0, 30, 101,
138 0x01, 0x21, 1, 20, 50,
139 0x02, 0x21, 2, 20, 50,
140 0x03, 0x21, 3, 15, 50,
141 0x04, 0x21, 4, 15, 30,
142 0x05, 0x21, 5, 10, 25,
143 0x06, 0x21, 6, 8, 14,
144 0x07, 0x21, 7, 8, 14,
145 0x08, 0x23, 7, 8, 14,
146 };
147
148 UCHAR RateSwitchTable11N2S[] = {
149 // 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)
150 0x0a, 0x00, 0, 0, 0, // Initial used item after association
151 0x00, 0x21, 0, 30, 101,
152 0x01, 0x21, 1, 20, 50,
153 0x02, 0x21, 2, 20, 50,
154 0x03, 0x21, 3, 15, 50,
155 0x04, 0x21, 4, 15, 30,
156 0x05, 0x20, 12, 15, 30,
157 0x06, 0x20, 13, 8, 20,
158 0x07, 0x20, 14, 8, 20,
159 0x08, 0x20, 15, 8, 25,
160 0x09, 0x22, 15, 8, 25,
161 };
162
163 UCHAR RateSwitchTable11N3S[] = {
164 // 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)
165 0x0a, 0x00, 0, 0, 0, // Initial used item after association
166 0x00, 0x21, 0, 30, 101,
167 0x01, 0x21, 1, 20, 50,
168 0x02, 0x21, 2, 20, 50,
169 0x03, 0x21, 3, 15, 50,
170 0x04, 0x21, 4, 15, 30,
171 0x05, 0x20, 12, 15, 30,
172 0x06, 0x20, 13, 8, 20,
173 0x07, 0x20, 14, 8, 20,
174 0x08, 0x20, 15, 8, 25,
175 0x09, 0x22, 15, 8, 25,
176 };
177
178 UCHAR RateSwitchTable11N2SForABand[] = {
179 // 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)
180 0x0b, 0x09, 0, 0, 0, // Initial used item after association
181 0x00, 0x21, 0, 30, 101,
182 0x01, 0x21, 1, 20, 50,
183 0x02, 0x21, 2, 20, 50,
184 0x03, 0x21, 3, 15, 50,
185 0x04, 0x21, 4, 15, 30,
186 0x05, 0x21, 5, 15, 30,
187 0x06, 0x20, 12, 15, 30,
188 0x07, 0x20, 13, 8, 20,
189 0x08, 0x20, 14, 8, 20,
190 0x09, 0x20, 15, 8, 25,
191 0x0a, 0x22, 15, 8, 25,
192 };
193
194 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
195 // 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)
196 0x0b, 0x09, 0, 0, 0, // Initial used item after association
197 0x00, 0x21, 0, 30, 101,
198 0x01, 0x21, 1, 20, 50,
199 0x02, 0x21, 2, 20, 50,
200 0x03, 0x21, 3, 15, 50,
201 0x04, 0x21, 4, 15, 30,
202 0x05, 0x21, 5, 15, 30,
203 0x06, 0x20, 12, 15, 30,
204 0x07, 0x20, 13, 8, 20,
205 0x08, 0x20, 14, 8, 20,
206 0x09, 0x20, 15, 8, 25,
207 0x0a, 0x22, 15, 8, 25,
208 };
209
210 UCHAR RateSwitchTable11BGN1S[] = {
211 // 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)
212 0x0d, 0x00, 0, 0, 0, // Initial used item after association
213 0x00, 0x00, 0, 40, 101,
214 0x01, 0x00, 1, 40, 50,
215 0x02, 0x00, 2, 35, 45,
216 0x03, 0x00, 3, 20, 45,
217 0x04, 0x21, 0, 30,101, //50
218 0x05, 0x21, 1, 20, 50,
219 0x06, 0x21, 2, 20, 50,
220 0x07, 0x21, 3, 15, 50,
221 0x08, 0x21, 4, 15, 30,
222 0x09, 0x21, 5, 10, 25,
223 0x0a, 0x21, 6, 8, 14,
224 0x0b, 0x21, 7, 8, 14,
225 0x0c, 0x23, 7, 8, 14,
226 };
227
228 UCHAR RateSwitchTable11BGN2S[] = {
229 // 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)
230 0x0a, 0x00, 0, 0, 0, // Initial used item after association
231 0x00, 0x21, 0, 30,101, //50
232 0x01, 0x21, 1, 20, 50,
233 0x02, 0x21, 2, 20, 50,
234 0x03, 0x21, 3, 15, 50,
235 0x04, 0x21, 4, 15, 30,
236 0x05, 0x20, 12, 15, 30,
237 0x06, 0x20, 13, 8, 20,
238 0x07, 0x20, 14, 8, 20,
239 0x08, 0x20, 15, 8, 25,
240 0x09, 0x22, 15, 8, 25,
241 };
242
243 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
244 // 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)
245 0x0a, 0x00, 0, 0, 0, // Initial used item after association
246 0x00, 0x21, 0, 30,101, //50
247 0x01, 0x21, 1, 20, 50,
248 0x02, 0x21, 2, 20, 50,
249 0x03, 0x21, 3, 20, 50,
250 0x04, 0x21, 4, 15, 50,
251 0x05, 0x20, 20, 15, 30,
252 0x06, 0x20, 21, 8, 20,
253 0x07, 0x20, 22, 8, 20,
254 0x08, 0x20, 23, 8, 25,
255 0x09, 0x22, 23, 8, 25,
256 };
257
258 UCHAR RateSwitchTable11BGN2SForABand[] = {
259 // 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)
260 0x0b, 0x09, 0, 0, 0, // Initial used item after association
261 0x00, 0x21, 0, 30,101, //50
262 0x01, 0x21, 1, 20, 50,
263 0x02, 0x21, 2, 20, 50,
264 0x03, 0x21, 3, 15, 50,
265 0x04, 0x21, 4, 15, 30,
266 0x05, 0x21, 5, 15, 30,
267 0x06, 0x20, 12, 15, 30,
268 0x07, 0x20, 13, 8, 20,
269 0x08, 0x20, 14, 8, 20,
270 0x09, 0x20, 15, 8, 25,
271 0x0a, 0x22, 15, 8, 25,
272 };
273
274 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
275 // 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)
276 0x0c, 0x09, 0, 0, 0, // Initial used item after association
277 0x00, 0x21, 0, 30,101, //50
278 0x01, 0x21, 1, 20, 50,
279 0x02, 0x21, 2, 20, 50,
280 0x03, 0x21, 3, 15, 50,
281 0x04, 0x21, 4, 15, 30,
282 0x05, 0x21, 5, 15, 30,
283 0x06, 0x21, 12, 15, 30,
284 0x07, 0x20, 20, 15, 30,
285 0x08, 0x20, 21, 8, 20,
286 0x09, 0x20, 22, 8, 20,
287 0x0a, 0x20, 23, 8, 25,
288 0x0b, 0x22, 23, 8, 25,
289 };
290 #endif // DOT11_N_SUPPORT //
291
292 PUCHAR ReasonString[] = {
293 /* 0 */ "Reserved",
294 /* 1 */ "Unspecified Reason",
295 /* 2 */ "Previous Auth no longer valid",
296 /* 3 */ "STA is leaving / has left",
297 /* 4 */ "DIS-ASSOC due to inactivity",
298 /* 5 */ "AP unable to hanle all associations",
299 /* 6 */ "class 2 error",
300 /* 7 */ "class 3 error",
301 /* 8 */ "STA is leaving / has left",
302 /* 9 */ "require auth before assoc/re-assoc",
303 /* 10 */ "Reserved",
304 /* 11 */ "Reserved",
305 /* 12 */ "Reserved",
306 /* 13 */ "invalid IE",
307 /* 14 */ "MIC error",
308 /* 15 */ "4-way handshake timeout",
309 /* 16 */ "2-way (group key) handshake timeout",
310 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
311 /* 18 */
312 };
313
314 extern UCHAR OfdmRateToRxwiMCS[];
315 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
316 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
317 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
318 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
319 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
320
321 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
322 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
323 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
324
325 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
326 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
327 // clean environment.
328 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
329 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
330
331 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
332 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
333
334 UCHAR SsidIe = IE_SSID;
335 UCHAR SupRateIe = IE_SUPP_RATES;
336 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
337 #ifdef DOT11_N_SUPPORT
338 UCHAR HtCapIe = IE_HT_CAP;
339 UCHAR AddHtInfoIe = IE_ADD_HT;
340 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
341 #endif // DOT11_N_SUPPORT //
342 UCHAR ErpIe = IE_ERP;
343 UCHAR DsIe = IE_DS_PARM;
344 UCHAR TimIe = IE_TIM;
345 UCHAR WpaIe = IE_WPA;
346 UCHAR Wpa2Ie = IE_WPA2;
347 UCHAR IbssIe = IE_IBSS_PARM;
348 UCHAR Ccx2Ie = IE_CCX_V2;
349
350 extern UCHAR WPA_OUI[];
351
352 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
353
354 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
355 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
356
357 // Reset the RFIC setting to new series
358 RTMP_RF_REGS RF2850RegTable[] = {
359 // ch R1 R2 R3(TX0~4=0) R4
360 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
361 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
362 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
363 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
364 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
365 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
366 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
367 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
368 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
369 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
370 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
371 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
372 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
373 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
374
375 // 802.11 UNI / HyperLan 2
376 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
377 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
378 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
379 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
380 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
381 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
382 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
383 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
384 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
385 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
386 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
387 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
388
389 // 802.11 HyperLan 2
390 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
391
392 // 2008.04.30 modified
393 // The system team has AN to improve the EVM value
394 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
395 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
396 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
397 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
398
399 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
400 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
401 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
402 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
403 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
404 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
405 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
406 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
407 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
408 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
409 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
410 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
411
412 // 802.11 UNII
413 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
414 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
415 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
416 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
417 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
418 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
419 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
420
421 // Japan
422 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
423 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
424 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
425 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
426 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
427 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
428 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
429
430 // still lack of MMAC(Japan) ch 34,38,42,46
431 };
432 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
433
434 FREQUENCY_ITEM FreqItems3020[] =
435 {
436 /**************************************************/
437 // ISM : 2.4 to 2.483 GHz //
438 /**************************************************/
439 // 11g
440 /**************************************************/
441 //-CH---N-------R---K-----------
442 {1, 241, 2, 2},
443 {2, 241, 2, 7},
444 {3, 242, 2, 2},
445 {4, 242, 2, 7},
446 {5, 243, 2, 2},
447 {6, 243, 2, 7},
448 {7, 244, 2, 2},
449 {8, 244, 2, 7},
450 {9, 245, 2, 2},
451 {10, 245, 2, 7},
452 {11, 246, 2, 2},
453 {12, 246, 2, 7},
454 {13, 247, 2, 2},
455 {14, 248, 2, 4},
456 };
457 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
458
459 /*
460 ==========================================================================
461 Description:
462 initialize the MLME task and its data structure (queue, spinlock,
463 timer, state machines).
464
465 IRQL = PASSIVE_LEVEL
466
467 Return:
468 always return NDIS_STATUS_SUCCESS
469
470 ==========================================================================
471 */
472 NDIS_STATUS MlmeInit(
473 IN PRTMP_ADAPTER pAd)
474 {
475 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
476
477 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
478
479 do
480 {
481 Status = MlmeQueueInit(&pAd->Mlme.Queue);
482 if(Status != NDIS_STATUS_SUCCESS)
483 break;
484
485 pAd->Mlme.bRunning = FALSE;
486 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
487
488 #ifdef CONFIG_STA_SUPPORT
489 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
490 {
491 BssTableInit(&pAd->ScanTab);
492
493 // init STA state machines
494 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
495 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
496 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
497 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
498 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
499 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
500
501 // Since we are using switch/case to implement it, the init is different from the above
502 // state machine init
503 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
504 }
505 #endif // CONFIG_STA_SUPPORT //
506
507
508
509 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
510
511 // Init mlme periodic timer
512 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
513
514 // Set mlme periodic timer
515 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
516
517 // software-based RX Antenna diversity
518 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
519
520
521 #ifdef CONFIG_STA_SUPPORT
522 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
523 {
524 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
525 {
526 // only PCIe cards need these two timers
527 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
528 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
529 }
530 }
531 #endif // CONFIG_STA_SUPPORT //
532
533 } while (FALSE);
534
535 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
536
537 return Status;
538 }
539
540 /*
541 ==========================================================================
542 Description:
543 main loop of the MLME
544 Pre:
545 Mlme has to be initialized, and there are something inside the queue
546 Note:
547 This function is invoked from MPSetInformation and MPReceive;
548 This task guarantee only one MlmeHandler will run.
549
550 IRQL = DISPATCH_LEVEL
551
552 ==========================================================================
553 */
554 VOID MlmeHandler(
555 IN PRTMP_ADAPTER pAd)
556 {
557 MLME_QUEUE_ELEM *Elem = NULL;
558
559 // Only accept MLME and Frame from peer side, no other (control/data) frame should
560 // get into this state machine
561
562 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
563 if(pAd->Mlme.bRunning)
564 {
565 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
566 return;
567 }
568 else
569 {
570 pAd->Mlme.bRunning = TRUE;
571 }
572 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
573
574 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
575 {
576 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
577 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
578 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
579 {
580 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
581 break;
582 }
583
584 //From message type, determine which state machine I should drive
585 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
586 {
587
588 // if dequeue success
589 switch (Elem->Machine)
590 {
591 // STA state machines
592 #ifdef CONFIG_STA_SUPPORT
593 case ASSOC_STATE_MACHINE:
594 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
595 break;
596 case AUTH_STATE_MACHINE:
597 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
598 break;
599 case AUTH_RSP_STATE_MACHINE:
600 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
601 break;
602 case SYNC_STATE_MACHINE:
603 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
604 break;
605 case MLME_CNTL_STATE_MACHINE:
606 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
607 break;
608 case WPA_PSK_STATE_MACHINE:
609 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
610 break;
611 case AIRONET_STATE_MACHINE:
612 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
613 break;
614 #endif // CONFIG_STA_SUPPORT //
615
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
661 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
662
663 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
664 {
665 // disable BEACON generation and other BEACON related hardware timers
666 AsicDisableSync(pAd);
667 }
668
669 #ifdef CONFIG_STA_SUPPORT
670 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
671 {
672 // Cancel pending timers
673 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
674 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
675 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
676 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
677 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
678 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
679 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
680 {
681 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
682 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
683 }
684 }
685 #endif // CONFIG_STA_SUPPORT //
686
687 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
688 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
689
690
691
692 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
693 {
694 // Set LED
695 RTMPSetLED(pAd, LED_HALT);
696 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
697 }
698
699 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
700
701 MlmeQueueDestroy(&pAd->Mlme.Queue);
702 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
703
704 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
705 }
706
707 VOID MlmeResetRalinkCounters(
708 IN PRTMP_ADAPTER pAd)
709 {
710 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
711 // clear all OneSecxxx counters.
712 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
713 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
714 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
715 pAd->RalinkCounters.OneSecRxOkCnt = 0;
716 pAd->RalinkCounters.OneSecTxFailCount = 0;
717 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
718 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
719 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
720
721 // TODO: for debug only. to be removed
722 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
723 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
724 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
725 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
726 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
727 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
728 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
729 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
730 pAd->RalinkCounters.OneSecTxDoneCount = 0;
731 pAd->RalinkCounters.OneSecRxCount = 0;
732 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
733 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
734
735 return;
736 }
737
738 unsigned long rx_AMSDU;
739 unsigned long rx_Total;
740
741 /*
742 ==========================================================================
743 Description:
744 This routine is executed periodically to -
745 1. Decide if it's a right time to turn on PwrMgmt bit of all
746 outgoiing frames
747 2. Calculate ChannelQuality based on statistics of the last
748 period, so that TX rate won't toggling very frequently between a
749 successful TX and a failed TX.
750 3. If the calculated ChannelQuality indicated current connection not
751 healthy, then a ROAMing attempt is tried here.
752
753 IRQL = DISPATCH_LEVEL
754
755 ==========================================================================
756 */
757 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
758 VOID MlmePeriodicExec(
759 IN PVOID SystemSpecific1,
760 IN PVOID FunctionContext,
761 IN PVOID SystemSpecific2,
762 IN PVOID SystemSpecific3)
763 {
764 ULONG TxTotalCnt;
765 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
766
767 //Baron 2008/07/10
768 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
769 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
770 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
771 if(pAd->StaCfg.WepStatus<2)
772 {
773 pAd->StaCfg.WpaSupplicantUP = 0;
774 }
775 else
776 {
777 pAd->StaCfg.WpaSupplicantUP = 1;
778 }
779
780 #ifdef CONFIG_STA_SUPPORT
781 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
782 {
783 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
784 // Move code to here, because following code will return when radio is off
785 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
786 (pAd->StaCfg.bHardwareRadio == TRUE) &&
787 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
788 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
789 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
790 {
791 UINT32 data = 0;
792
793 // Read GPIO pin2 as Hardware controlled radio state
794 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
795 if (data & 0x04)
796 {
797 pAd->StaCfg.bHwRadio = TRUE;
798 }
799 else
800 {
801 pAd->StaCfg.bHwRadio = FALSE;
802 }
803 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
804 {
805 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
806 if (pAd->StaCfg.bRadio == TRUE)
807 {
808 MlmeRadioOn(pAd);
809 // Update extra information
810 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
811 }
812 else
813 {
814 MlmeRadioOff(pAd);
815 // Update extra information
816 pAd->ExtraInfo = HW_RADIO_OFF;
817 }
818 }
819 }
820 }
821 #endif // CONFIG_STA_SUPPORT //
822
823 // Do nothing if the driver is starting halt state.
824 // This might happen when timer already been fired before cancel timer with mlmehalt
825 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
826 fRTMP_ADAPTER_RADIO_OFF |
827 fRTMP_ADAPTER_RADIO_MEASUREMENT |
828 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
829 return;
830
831 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
832 {
833 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
834 {
835 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
836 pAd->SameRxByteCount++;
837 }
838 else
839 pAd->SameRxByteCount = 0;
840
841 // If after BBP, still not work...need to check to reset PBF&MAC.
842 if (pAd->SameRxByteCount == 702)
843 {
844 pAd->SameRxByteCount = 0;
845 AsicResetPBF(pAd);
846 AsicResetMAC(pAd);
847 }
848
849 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
850 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
851 {
852 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
853 {
854 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
855 pAd->SameRxByteCount = 700;
856 AsicResetBBP(pAd);
857 }
858 }
859
860 // Update lastReceiveByteCount.
861 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
862
863 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
864 {
865 pAd->CheckDmaBusyCount = 0;
866 AsicResetFromDMABusy(pAd);
867 }
868 }
869
870 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
871
872 #ifdef CONFIG_STA_SUPPORT
873 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
874 {
875 // Do nothing if monitor mode is on
876 if (MONITOR_ON(pAd))
877 return;
878
879 if (pAd->Mlme.PeriodicRound & 0x1)
880 {
881 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
882 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
883 (STA_TGN_WIFI_ON(pAd)) &&
884 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
885
886 {
887 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
888 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
889 }
890 else if ((STA_TGN_WIFI_ON(pAd)) &&
891 ((pAd->MACVersion & 0xffff) == 0x0101))
892 {
893 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
894 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
895 }
896 }
897 }
898 #endif // CONFIG_STA_SUPPORT //
899
900 pAd->bUpdateBcnCntDone = FALSE;
901
902 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
903 pAd->Mlme.PeriodicRound ++;
904
905 // execute every 500ms
906 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
907 {
908 #ifdef CONFIG_STA_SUPPORT
909 // perform dynamic tx rate switching based on past TX history
910 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
911 {
912 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
913 )
914 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
915 MlmeDynamicTxRateSwitching(pAd);
916 }
917 #endif // CONFIG_STA_SUPPORT //
918 }
919
920 // Normal 1 second Mlme PeriodicExec.
921 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
922 {
923 pAd->Mlme.OneSecPeriodicRound ++;
924
925 if (rx_Total)
926 {
927
928 // reset counters
929 rx_AMSDU = 0;
930 rx_Total = 0;
931 }
932
933 // Media status changed, report to NDIS
934 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
935 {
936 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
937 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
938 {
939 pAd->IndicateMediaState = NdisMediaStateConnected;
940 RTMP_IndicateMediaState(pAd);
941
942 }
943 else
944 {
945 pAd->IndicateMediaState = NdisMediaStateDisconnected;
946 RTMP_IndicateMediaState(pAd);
947 }
948 }
949
950 NdisGetSystemUpTime(&pAd->Mlme.Now32);
951
952 // add the most up-to-date h/w raw counters into software variable, so that
953 // the dynamic tuning mechanism below are based on most up-to-date information
954 NICUpdateRawCounters(pAd);
955
956
957 #ifdef DOT11_N_SUPPORT
958 // Need statistics after read counter. So put after NICUpdateRawCounters
959 ORIBATimerTimeout(pAd);
960 #endif // DOT11_N_SUPPORT //
961
962
963 // The time period for checking antenna is according to traffic
964 if (pAd->Mlme.bEnableAutoAntennaCheck)
965 {
966 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
967 pAd->RalinkCounters.OneSecTxRetryOkCount +
968 pAd->RalinkCounters.OneSecTxFailCount;
969
970 if (TxTotalCnt > 50)
971 {
972 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
973 {
974 AsicEvaluateRxAnt(pAd);
975 }
976 }
977 else
978 {
979 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
980 {
981 AsicEvaluateRxAnt(pAd);
982 }
983 }
984 }
985
986 #ifdef CONFIG_STA_SUPPORT
987 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
988 STAMlmePeriodicExec(pAd);
989 #endif // CONFIG_STA_SUPPORT //
990
991 MlmeResetRalinkCounters(pAd);
992
993 #ifdef CONFIG_STA_SUPPORT
994 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
995 {
996 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
997 {
998 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
999 // and sending CTS-to-self over and over.
1000 // Software Patch Solution:
1001 // 1. Polling debug state register 0x10F4 every one second.
1002 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1003 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1004
1005 UINT32 MacReg = 0;
1006
1007 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1008 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1009 {
1010 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1011 RTMPusecDelay(1);
1012 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1013
1014 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1015 }
1016 }
1017 }
1018 #endif // CONFIG_STA_SUPPORT //
1019
1020 RT28XX_MLME_HANDLER(pAd);
1021 }
1022
1023
1024 pAd->bUpdateBcnCntDone = FALSE;
1025 }
1026
1027 #ifdef CONFIG_STA_SUPPORT
1028 VOID STAMlmePeriodicExec(
1029 PRTMP_ADAPTER pAd)
1030 {
1031 ULONG TxTotalCnt;
1032
1033 #ifdef WPA_SUPPLICANT_SUPPORT
1034 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1035 #endif // WPA_SUPPLICANT_SUPPORT //
1036 {
1037 // WPA MIC error should block association attempt for 60 seconds
1038 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1039 pAd->StaCfg.bBlockAssoc = FALSE;
1040 }
1041
1042 //Baron 2008/07/10
1043 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1044 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1045 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1046 if(pAd->StaCfg.WepStatus<2)
1047 {
1048 pAd->StaCfg.WpaSupplicantUP = 0;
1049 }
1050 else
1051 {
1052 pAd->StaCfg.WpaSupplicantUP = 1;
1053 }
1054
1055 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1056 {
1057 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1058 {
1059 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1060 }
1061 pAd->PreMediaState = pAd->IndicateMediaState;
1062 }
1063
1064 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1065 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1066 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1067 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1068 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1069 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1070 {
1071 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1072 }
1073
1074
1075
1076 AsicStaBbpTuning(pAd);
1077
1078 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1079 pAd->RalinkCounters.OneSecTxRetryOkCount +
1080 pAd->RalinkCounters.OneSecTxFailCount;
1081
1082 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1083 {
1084 // update channel quality for Roaming and UI LinkQuality display
1085 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1086 }
1087
1088 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1089 // Radio is currently in noisy environment
1090 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1091 AsicAdjustTxPower(pAd);
1092
1093 if (INFRA_ON(pAd))
1094 {
1095 // Is PSM bit consistent with user power management policy?
1096 // This is the only place that will set PSM bit ON.
1097 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1098 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1099
1100 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1101
1102 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1103 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1104 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1105 {
1106 RTMPSetAGCInitValue(pAd, BW_20);
1107 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1108 }
1109
1110 {
1111 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1112 {
1113 // When APSD is enabled, the period changes as 20 sec
1114 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1115 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1116 }
1117 else
1118 {
1119 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1120 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1121 {
1122 if (pAd->CommonCfg.bWmmCapable)
1123 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1124 else
1125 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1126 }
1127 }
1128 }
1129
1130 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1131 {
1132 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1133 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1134 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1135
1136 // Lost AP, send disconnect & link down event
1137 LinkDown(pAd, FALSE);
1138
1139 #ifdef WPA_SUPPLICANT_SUPPORT
1140 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1141 if (pAd->StaCfg.WpaSupplicantUP)
1142 {
1143 union iwreq_data wrqu;
1144 //send disassociate event to wpa_supplicant
1145 memset(&wrqu, 0, sizeof(wrqu));
1146 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1147 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1148 }
1149 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1150 #endif // WPA_SUPPLICANT_SUPPORT //
1151
1152 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1153 {
1154 union iwreq_data wrqu;
1155 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1156 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1157 }
1158 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1159
1160 MlmeAutoReconnectLastSSID(pAd);
1161 }
1162 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1163 {
1164 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1165 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1166 MlmeAutoReconnectLastSSID(pAd);
1167 }
1168
1169 // Add auto seamless roaming
1170 if (pAd->StaCfg.bFastRoaming)
1171 {
1172 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1173
1174 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));
1175
1176 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1177 {
1178 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1179 }
1180 }
1181 }
1182 else if (ADHOC_ON(pAd))
1183 {
1184 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1185 // the "TX BEACON competition" for the entire past 1 sec.
1186 // So that even when ASIC's BEACONgen engine been blocked
1187 // by peer's BEACON due to slower system clock, this STA still can send out
1188 // minimum BEACON to tell the peer I'm alive.
1189 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1190 // EnqueueBeaconFrame(pAd); // software send BEACON
1191
1192 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1193 // restore outgoing BEACON to support B/G-mixed mode
1194 if ((pAd->CommonCfg.Channel <= 14) &&
1195 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1196 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1197 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1198 {
1199 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1200 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1201 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1202 MlmeUpdateTxRates(pAd, FALSE, 0);
1203 MakeIbssBeacon(pAd); // re-build BEACON frame
1204 AsicEnableIbssSync(pAd); // copy to on-chip memory
1205 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1206 }
1207
1208 #ifdef DOT11_N_SUPPORT
1209 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1210 {
1211 if ((pAd->StaCfg.AdhocBGJoined) &&
1212 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1213 {
1214 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1215 pAd->StaCfg.AdhocBGJoined = FALSE;
1216 }
1217
1218 if ((pAd->StaCfg.Adhoc20NJoined) &&
1219 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1220 {
1221 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1222 pAd->StaCfg.Adhoc20NJoined = FALSE;
1223 }
1224 }
1225 #endif // DOT11_N_SUPPORT //
1226
1227 //radar detect
1228 if ((pAd->CommonCfg.Channel > 14)
1229 && (pAd->CommonCfg.bIEEE80211H == 1)
1230 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1231 {
1232 RadarDetectPeriodic(pAd);
1233 }
1234
1235 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1236 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1237 // join later.
1238 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1239 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1240 {
1241 MLME_START_REQ_STRUCT StartReq;
1242
1243 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1244 LinkDown(pAd, FALSE);
1245
1246 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1247 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1248 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1249 }
1250 }
1251 else // no INFRA nor ADHOC connection
1252 {
1253
1254 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1255 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1256 goto SKIP_AUTO_SCAN_CONN;
1257 else
1258 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1259
1260 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1261 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1262 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1263 {
1264 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1265 {
1266 MLME_SCAN_REQ_STRUCT ScanReq;
1267
1268 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1269 {
1270 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1271 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1272 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1273 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1274 // Reset Missed scan number
1275 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1276 }
1277 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1278 MlmeAutoReconnectLastSSID(pAd);
1279 }
1280 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1281 {
1282 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1283 {
1284 MlmeAutoScan(pAd);
1285 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1286 }
1287 else
1288 {
1289 MlmeAutoReconnectLastSSID(pAd);
1290 }
1291 }
1292 }
1293 }
1294
1295 SKIP_AUTO_SCAN_CONN:
1296
1297 #ifdef DOT11_N_SUPPORT
1298 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1299 {
1300 pAd->MacTab.fAnyBASession = TRUE;
1301 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1302 }
1303 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1304 {
1305 pAd->MacTab.fAnyBASession = FALSE;
1306 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1307 }
1308 #endif // DOT11_N_SUPPORT //
1309
1310 return;
1311 }
1312
1313 // Link down report
1314 VOID LinkDownExec(
1315 IN PVOID SystemSpecific1,
1316 IN PVOID FunctionContext,
1317 IN PVOID SystemSpecific2,
1318 IN PVOID SystemSpecific3)
1319 {
1320
1321 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1322
1323 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1324 RTMP_IndicateMediaState(pAd);
1325 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1326 }
1327
1328 // IRQL = DISPATCH_LEVEL
1329 VOID MlmeAutoScan(
1330 IN PRTMP_ADAPTER pAd)
1331 {
1332 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1333 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1334 {
1335 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1336 MlmeEnqueue(pAd,
1337 MLME_CNTL_STATE_MACHINE,
1338 OID_802_11_BSSID_LIST_SCAN,
1339 0,
1340 NULL);
1341 RT28XX_MLME_HANDLER(pAd);
1342 }
1343 }
1344
1345 // IRQL = DISPATCH_LEVEL
1346 VOID MlmeAutoReconnectLastSSID(
1347 IN PRTMP_ADAPTER pAd)
1348 {
1349
1350
1351 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1352 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1353 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1354 {
1355 NDIS_802_11_SSID OidSsid;
1356 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1357 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1358
1359 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1360 MlmeEnqueue(pAd,
1361 MLME_CNTL_STATE_MACHINE,
1362 OID_802_11_SSID,
1363 sizeof(NDIS_802_11_SSID),
1364 &OidSsid);
1365 RT28XX_MLME_HANDLER(pAd);
1366 }
1367 }
1368 #endif // CONFIG_STA_SUPPORT //
1369
1370 /*
1371 ==========================================================================
1372 Validate SSID for connection try and rescan purpose
1373 Valid SSID will have visible chars only.
1374 The valid length is from 0 to 32.
1375 IRQL = DISPATCH_LEVEL
1376 ==========================================================================
1377 */
1378 BOOLEAN MlmeValidateSSID(
1379 IN PUCHAR pSsid,
1380 IN UCHAR SsidLen)
1381 {
1382 int index;
1383
1384 if (SsidLen > MAX_LEN_OF_SSID)
1385 return (FALSE);
1386
1387 // Check each character value
1388 for (index = 0; index < SsidLen; index++)
1389 {
1390 if (pSsid[index] < 0x20)
1391 return (FALSE);
1392 }
1393
1394 // All checked
1395 return (TRUE);
1396 }
1397
1398 VOID MlmeSelectTxRateTable(
1399 IN PRTMP_ADAPTER pAd,
1400 IN PMAC_TABLE_ENTRY pEntry,
1401 IN PUCHAR *ppTable,
1402 IN PUCHAR pTableSize,
1403 IN PUCHAR pInitTxRateIdx)
1404 {
1405 do
1406 {
1407 // decide the rate table for tuning
1408 if (pAd->CommonCfg.TxRateTableSize > 0)
1409 {
1410 *ppTable = RateSwitchTable;
1411 *pTableSize = RateSwitchTable[0];
1412 *pInitTxRateIdx = RateSwitchTable[1];
1413
1414 break;
1415 }
1416
1417 #ifdef CONFIG_STA_SUPPORT
1418 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1419 {
1420 #ifdef DOT11_N_SUPPORT
1421 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1422 !pAd->StaCfg.AdhocBOnlyJoined &&
1423 !pAd->StaCfg.AdhocBGJoined &&
1424 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1425 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1426 {// 11N 1S Adhoc
1427 *ppTable = RateSwitchTable11N1S;
1428 *pTableSize = RateSwitchTable11N1S[0];
1429 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1430
1431 }
1432 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1433 !pAd->StaCfg.AdhocBOnlyJoined &&
1434 !pAd->StaCfg.AdhocBGJoined &&
1435 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1436 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1437 (pAd->Antenna.field.TxPath == 2))
1438 {// 11N 2S Adhoc
1439 if (pAd->LatchRfRegs.Channel <= 14)
1440 {
1441 *ppTable = RateSwitchTable11N2S;
1442 *pTableSize = RateSwitchTable11N2S[0];
1443 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1444 }
1445 else
1446 {
1447 *ppTable = RateSwitchTable11N2SForABand;
1448 *pTableSize = RateSwitchTable11N2SForABand[0];
1449 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1450 }
1451
1452 }
1453 else
1454 #endif // DOT11_N_SUPPORT //
1455 if (pAd->CommonCfg.PhyMode == PHY_11B)
1456 {
1457 *ppTable = RateSwitchTable11B;
1458 *pTableSize = RateSwitchTable11B[0];
1459 *pInitTxRateIdx = RateSwitchTable11B[1];
1460
1461 }
1462 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1463 {
1464 // USe B Table when Only b-only Station in my IBSS .
1465 *ppTable = RateSwitchTable11B;
1466 *pTableSize = RateSwitchTable11B[0];
1467 *pInitTxRateIdx = RateSwitchTable11B[1];
1468
1469 }
1470 else if (pAd->LatchRfRegs.Channel <= 14)
1471 {
1472 *ppTable = RateSwitchTable11BG;
1473 *pTableSize = RateSwitchTable11BG[0];
1474 *pInitTxRateIdx = RateSwitchTable11BG[1];
1475
1476 }
1477 else
1478 {
1479 *ppTable = RateSwitchTable11G;
1480 *pTableSize = RateSwitchTable11G[0];
1481 *pInitTxRateIdx = RateSwitchTable11G[1];
1482
1483 }
1484 break;
1485 }
1486 #endif // CONFIG_STA_SUPPORT //
1487
1488 #ifdef DOT11_N_SUPPORT
1489 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1490 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1491 {// 11BGN 1S AP
1492 *ppTable = RateSwitchTable11BGN1S;
1493 *pTableSize = RateSwitchTable11BGN1S[0];
1494 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1495
1496 break;
1497 }
1498
1499 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1500 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1501 {// 11BGN 2S AP
1502 if (pAd->LatchRfRegs.Channel <= 14)
1503 {
1504 *ppTable = RateSwitchTable11BGN2S;
1505 *pTableSize = RateSwitchTable11BGN2S[0];
1506 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1507
1508 }
1509 else
1510 {
1511 *ppTable = RateSwitchTable11BGN2SForABand;
1512 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1513 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1514
1515 }
1516 break;
1517 }
1518
1519 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1520 {// 11N 1S AP
1521 *ppTable = RateSwitchTable11N1S;
1522 *pTableSize = RateSwitchTable11N1S[0];
1523 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1524
1525 break;
1526 }
1527
1528 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1529 {// 11N 2S AP
1530 if (pAd->LatchRfRegs.Channel <= 14)
1531 {
1532 *ppTable = RateSwitchTable11N2S;
1533 *pTableSize = RateSwitchTable11N2S[0];
1534 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1535 }
1536 else
1537 {
1538 *ppTable = RateSwitchTable11N2SForABand;
1539 *pTableSize = RateSwitchTable11N2SForABand[0];
1540 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1541 }
1542
1543 break;
1544 }
1545 #endif // DOT11_N_SUPPORT //
1546 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1547 if ((pEntry->RateLen == 4)
1548 #ifdef DOT11_N_SUPPORT
1549 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1550 #endif // DOT11_N_SUPPORT //
1551 )
1552 {// B only AP
1553 *ppTable = RateSwitchTable11B;
1554 *pTableSize = RateSwitchTable11B[0];
1555 *pInitTxRateIdx = RateSwitchTable11B[1];
1556
1557 break;
1558 }
1559
1560 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1561 if ((pEntry->RateLen > 8)
1562 #ifdef DOT11_N_SUPPORT
1563 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1564 #endif // DOT11_N_SUPPORT //
1565 )
1566 {// B/G mixed AP
1567 *ppTable = RateSwitchTable11BG;
1568 *pTableSize = RateSwitchTable11BG[0];
1569 *pInitTxRateIdx = RateSwitchTable11BG[1];
1570
1571 break;
1572 }
1573
1574 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1575 if ((pEntry->RateLen == 8)
1576 #ifdef DOT11_N_SUPPORT
1577 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1578 #endif // DOT11_N_SUPPORT //
1579 )
1580 {// G only AP
1581 *ppTable = RateSwitchTable11G;
1582 *pTableSize = RateSwitchTable11G[0];
1583 *pInitTxRateIdx = RateSwitchTable11G[1];
1584
1585 break;
1586 }
1587 #ifdef DOT11_N_SUPPORT
1588 #endif // DOT11_N_SUPPORT //
1589
1590 #ifdef CONFIG_STA_SUPPORT
1591 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1592 {
1593 #ifdef DOT11_N_SUPPORT
1594 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1595 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1596 #endif // DOT11_N_SUPPORT //
1597 { // Legacy mode
1598 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1599 {
1600 *ppTable = RateSwitchTable11B;
1601 *pTableSize = RateSwitchTable11B[0];
1602 *pInitTxRateIdx = RateSwitchTable11B[1];
1603 }
1604 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1605 {
1606 *ppTable = RateSwitchTable11G;
1607 *pTableSize = RateSwitchTable11G[0];
1608 *pInitTxRateIdx = RateSwitchTable11G[1];
1609
1610 }
1611 else
1612 {
1613 *ppTable = RateSwitchTable11BG;
1614 *pTableSize = RateSwitchTable11BG[0];
1615 *pInitTxRateIdx = RateSwitchTable11BG[1];
1616 }
1617 break;
1618 }
1619 #ifdef DOT11_N_SUPPORT
1620 if (pAd->LatchRfRegs.Channel <= 14)
1621 {
1622 if (pAd->CommonCfg.TxStream == 1)
1623 {
1624 *ppTable = RateSwitchTable11N1S;
1625 *pTableSize = RateSwitchTable11N1S[0];
1626 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1627 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1628 }
1629 else
1630 {
1631 *ppTable = RateSwitchTable11N2S;
1632 *pTableSize = RateSwitchTable11N2S[0];
1633 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1634 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1635 }
1636 }
1637 else
1638 {
1639 if (pAd->CommonCfg.TxStream == 1)
1640 {
1641 *ppTable = RateSwitchTable11N1S;
1642 *pTableSize = RateSwitchTable11N1S[0];
1643 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1644 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1645 }
1646 else
1647 {
1648 *ppTable = RateSwitchTable11N2SForABand;
1649 *pTableSize = RateSwitchTable11N2SForABand[0];
1650 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1651 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1652 }
1653 }
1654 #endif // DOT11_N_SUPPORT //
1655 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1656 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1657 }
1658 #endif // CONFIG_STA_SUPPORT //
1659 } while(FALSE);
1660 }
1661
1662 #ifdef CONFIG_STA_SUPPORT
1663 /*
1664 ==========================================================================
1665 Description:
1666 This routine checks if there're other APs out there capable for
1667 roaming. Caller should call this routine only when Link up in INFRA mode
1668 and channel quality is below CQI_GOOD_THRESHOLD.
1669
1670 IRQL = DISPATCH_LEVEL
1671
1672 Output:
1673 ==========================================================================
1674 */
1675 VOID MlmeCheckForRoaming(
1676 IN PRTMP_ADAPTER pAd,
1677 IN ULONG Now32)
1678 {
1679 USHORT i;
1680 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1681 BSS_ENTRY *pBss;
1682
1683 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1684 // put all roaming candidates into RoamTab, and sort in RSSI order
1685 BssTableInit(pRoamTab);
1686 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1687 {
1688 pBss = &pAd->ScanTab.BssEntry[i];
1689
1690 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1691 continue; // AP disappear
1692 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1693 continue; // RSSI too weak. forget it.
1694 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1695 continue; // skip current AP
1696 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1697 continue; // only AP with stronger RSSI is eligible for roaming
1698
1699 // AP passing all above rules is put into roaming candidate table
1700 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1701 pRoamTab->BssNr += 1;
1702 }
1703
1704 if (pRoamTab->BssNr > 0)
1705 {
1706 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1707 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1708 {
1709 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1710 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1711 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1712 RT28XX_MLME_HANDLER(pAd);
1713 }
1714 }
1715 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1716 }
1717
1718 /*
1719 ==========================================================================
1720 Description:
1721 This routine checks if there're other APs out there capable for
1722 roaming. Caller should call this routine only when link up in INFRA mode
1723 and channel quality is below CQI_GOOD_THRESHOLD.
1724
1725 IRQL = DISPATCH_LEVEL
1726
1727 Output:
1728 ==========================================================================
1729 */
1730 VOID MlmeCheckForFastRoaming(
1731 IN PRTMP_ADAPTER pAd,
1732 IN ULONG Now)
1733 {
1734 USHORT i;
1735 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1736 BSS_ENTRY *pBss;
1737
1738 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1739 // put all roaming candidates into RoamTab, and sort in RSSI order
1740 BssTableInit(pRoamTab);
1741 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1742 {
1743 pBss = &pAd->ScanTab.BssEntry[i];
1744
1745 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1746 continue; // RSSI too weak. forget it.
1747 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1748 continue; // skip current AP
1749 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1750 continue; // skip different SSID
1751 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1752 continue; // skip AP without better RSSI
1753
1754 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));
1755 // AP passing all above rules is put into roaming candidate table
1756 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1757 pRoamTab->BssNr += 1;
1758 }
1759
1760 if (pRoamTab->BssNr > 0)
1761 {
1762 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1763 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1764 {
1765 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1766 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1767 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1768 RT28XX_MLME_HANDLER(pAd);
1769 }
1770 }
1771 // Maybe site survey required
1772 else
1773 {
1774 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1775 {
1776 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1777 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1778 pAd->StaCfg.ScanCnt = 2;
1779 pAd->StaCfg.LastScanTime = Now;
1780 MlmeAutoScan(pAd);
1781 }
1782 }
1783
1784 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1785 }
1786
1787 /*
1788 ==========================================================================
1789 Description:
1790 This routine calculates TxPER, RxPER of the past N-sec period. And
1791 according to the calculation result, ChannelQuality is calculated here
1792 to decide if current AP is still doing the job.
1793
1794 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1795 Output:
1796 StaCfg.ChannelQuality - 0..100
1797
1798 IRQL = DISPATCH_LEVEL
1799
1800 NOTE: This routine decide channle quality based on RX CRC error ratio.
1801 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1802 is performed right before this routine, so that this routine can decide
1803 channel quality based on the most up-to-date information
1804 ==========================================================================
1805 */
1806 VOID MlmeCalculateChannelQuality(
1807 IN PRTMP_ADAPTER pAd,
1808 IN ULONG Now32)
1809 {
1810 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1811 ULONG RxCnt, RxPER;
1812 UCHAR NorRssi;
1813 CHAR MaxRssi;
1814 ULONG BeaconLostTime = BEACON_LOST_TIME;
1815
1816 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1817
1818 //
1819 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1820 //
1821 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1822 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1823 if (TxCnt < 5)
1824 {
1825 TxPER = 0;
1826 TxPRR = 0;
1827 }
1828 else
1829 {
1830 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1831 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1832 }
1833
1834 //
1835 // calculate RX PER - don't take RxPER into consideration if too few sample
1836 //
1837 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1838 if (RxCnt < 5)
1839 RxPER = 0;
1840 else
1841 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1842
1843 //
1844 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1845 //
1846 if (INFRA_ON(pAd) &&
1847 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1848 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1849 {
1850 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1851 pAd->Mlme.ChannelQuality = 0;
1852 }
1853 else
1854 {
1855 // Normalize Rssi
1856 if (MaxRssi > -40)
1857 NorRssi = 100;
1858 else if (MaxRssi < -90)
1859 NorRssi = 0;
1860 else
1861 NorRssi = (MaxRssi + 90) * 2;
1862
1863 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1864 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1865 TX_WEIGHTING * (100 - TxPRR) +
1866 RX_WEIGHTING* (100 - RxPER)) / 100;
1867 if (pAd->Mlme.ChannelQuality >= 100)
1868 pAd->Mlme.ChannelQuality = 100;
1869 }
1870
1871 }
1872
1873 VOID MlmeSetTxRate(
1874 IN PRTMP_ADAPTER pAd,
1875 IN PMAC_TABLE_ENTRY pEntry,
1876 IN PRTMP_TX_RATE_SWITCH pTxRate)
1877 {
1878 UCHAR MaxMode = MODE_OFDM;
1879
1880 #ifdef DOT11_N_SUPPORT
1881 MaxMode = MODE_HTGREENFIELD;
1882
1883 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1884 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1885 else
1886 #endif // DOT11_N_SUPPORT //
1887 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1888
1889 if (pTxRate->CurrMCS < MCS_AUTO)
1890 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1891
1892 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1893 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1894
1895 if (ADHOC_ON(pAd))
1896 {
1897 // If peer adhoc is b-only mode, we can't send 11g rate.
1898 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1899 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1900
1901 //
1902 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1903 //
1904 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1905 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1906 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1907
1908 // Patch speed error in status page
1909 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1910 }
1911 else
1912 {
1913 if (pTxRate->Mode <= MaxMode)
1914 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1915
1916 #ifdef DOT11_N_SUPPORT
1917 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1918 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1919 else
1920 #endif // DOT11_N_SUPPORT //
1921 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1922
1923 #ifdef DOT11_N_SUPPORT
1924 // Reexam each bandwidth's SGI support.
1925 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1926 {
1927 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1928 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1929 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1930 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1931 }
1932
1933 // Turn RTS/CTS rate to 6Mbps.
1934 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1935 {
1936 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1937 if (pAd->MacTab.fAnyBASession)
1938 {
1939 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1940 }
1941 else
1942 {
1943 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1944 }
1945 }
1946 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1947 {
1948 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1949 if (pAd->MacTab.fAnyBASession)
1950 {
1951 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1952 }
1953 else
1954 {
1955 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1956 }
1957 }
1958 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1959 {
1960 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1961
1962 }
1963 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1964 {
1965 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1966 }
1967 #endif // DOT11_N_SUPPORT //
1968
1969 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1970 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1971 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1972 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1973 #ifdef DOT11_N_SUPPORT
1974 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1975 pAd->WIFItestbed.bGreenField)
1976 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1977 #endif // DOT11_N_SUPPORT //
1978 }
1979
1980 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1981 }
1982
1983 /*
1984 ==========================================================================
1985 Description:
1986 This routine calculates the acumulated TxPER of eaxh TxRate. And
1987 according to the calculation result, change CommonCfg.TxRate which
1988 is the stable TX Rate we expect the Radio situation could sustained.
1989
1990 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1991 Output:
1992 CommonCfg.TxRate -
1993
1994 IRQL = DISPATCH_LEVEL
1995
1996 NOTE:
1997 call this routine every second
1998 ==========================================================================
1999 */
2000 VOID MlmeDynamicTxRateSwitching(
2001 IN PRTMP_ADAPTER pAd)
2002 {
2003 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2004 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2005 ULONG TxErrorRatio = 0;
2006 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2007 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2008 PUCHAR pTable;
2009 UCHAR TableSize = 0;
2010 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2011 CHAR Rssi, RssiOffset = 0;
2012 TX_STA_CNT1_STRUC StaTx1;
2013 TX_STA_CNT0_STRUC TxStaCnt0;
2014 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2015 MAC_TABLE_ENTRY *pEntry;
2016
2017 /*if (pAd->Antenna.field.RxPath > 1)
2018 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2019 else
2020 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
2021
2022 //
2023 // walk through MAC table, see if need to change AP's TX rate toward each entry
2024 //
2025 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2026 {
2027 pEntry = &pAd->MacTab.Content[i];
2028
2029 // check if this entry need to switch rate automatically
2030 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2031 continue;
2032
2033 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2034 {
2035 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2036
2037 // Update statistic counter
2038 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2039 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2040 pAd->bUpdateBcnCntDone = TRUE;
2041 TxRetransmit = StaTx1.field.TxRetransmit;
2042 TxSuccess = StaTx1.field.TxSuccess;
2043 TxFailCount = TxStaCnt0.field.TxFailCount;
2044 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2045
2046 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2047 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2048 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2049 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2050 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2051 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2052
2053 // if no traffic in the past 1-sec period, don't change TX rate,
2054 // but clear all bad history. because the bad history may affect the next
2055 // Chariot throughput test
2056 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2057 pAd->RalinkCounters.OneSecTxRetryOkCount +
2058 pAd->RalinkCounters.OneSecTxFailCount;
2059
2060 if (TxTotalCnt)
2061 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2062 }
2063 else
2064 {
2065 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2066
2067 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2068 pEntry->OneSecTxRetryOkCount +
2069 pEntry->OneSecTxFailCount;
2070
2071 if (TxTotalCnt)
2072 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2073 }
2074
2075 CurrRateIdx = pEntry->CurrTxRateIndex;
2076
2077 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2078
2079 if (CurrRateIdx >= TableSize)
2080 {
2081 CurrRateIdx = TableSize - 1;
2082 }
2083
2084 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2085 // So need to sync here.
2086 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2087 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2088 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2089 )
2090 {
2091
2092 // Need to sync Real Tx rate and our record.
2093 // Then return for next DRS.
2094 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2095 pEntry->CurrTxRateIndex = InitTxRateIdx;
2096 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2097
2098 // reset all OneSecTx counters
2099 RESET_ONE_SEC_TX_CNT(pEntry);
2100 continue;
2101 }
2102
2103 // decide the next upgrade rate and downgrade rate, if any
2104 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2105 {
2106 UpRateIdx = CurrRateIdx + 1;
2107 DownRateIdx = CurrRateIdx -1;
2108 }
2109 else if (CurrRateIdx == 0)
2110 {
2111 UpRateIdx = CurrRateIdx + 1;
2112 DownRateIdx = CurrRateIdx;
2113 }
2114 else if (CurrRateIdx == (TableSize - 1))
2115 {
2116 UpRateIdx = CurrRateIdx;
2117 DownRateIdx = CurrRateIdx - 1;
2118 }
2119
2120 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2121
2122 #ifdef DOT11_N_SUPPORT
2123 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2124 {
2125 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2126 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2127 }
2128 else
2129 #endif // DOT11_N_SUPPORT //
2130 {
2131 TrainUp = pCurrTxRate->TrainUp;
2132 TrainDown = pCurrTxRate->TrainDown;
2133 }
2134
2135 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2136
2137 //
2138 // Keep the last time TxRateChangeAction status.
2139 //
2140 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2141
2142
2143
2144 //
2145 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2146 // (criteria copied from RT2500 for Netopia case)
2147 //
2148 if (TxTotalCnt <= 15)
2149 {
2150 CHAR idx = 0;
2151 UCHAR TxRateIdx;
2152 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2153 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2154 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2155 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2156
2157 // check the existence and index of each needed MCS
2158 while (idx < pTable[0])
2159 {
2160 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2161
2162 if (pCurrTxRate->CurrMCS == MCS_0)
2163 {
2164 MCS0 = idx;
2165 }
2166 else if (pCurrTxRate->CurrMCS == MCS_1)
2167 {
2168 MCS1 = idx;
2169 }
2170 else if (pCurrTxRate->CurrMCS == MCS_2)
2171 {
2172 MCS2 = idx;
2173 }
2174 else if (pCurrTxRate->CurrMCS == MCS_3)
2175 {
2176 MCS3 = idx;
2177 }
2178 else if (pCurrTxRate->CurrMCS == MCS_4)
2179 {
2180 MCS4 = idx;
2181 }
2182 else if (pCurrTxRate->CurrMCS == MCS_5)
2183 {
2184 MCS5 = idx;
2185 }
2186 else if (pCurrTxRate->CurrMCS == MCS_6)
2187 {
2188 MCS6 = idx;
2189 }
2190 //else if (pCurrTxRate->CurrMCS == MCS_7)
2191 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2192 {
2193 MCS7 = idx;
2194 }
2195 else if (pCurrTxRate->CurrMCS == MCS_12)
2196 {
2197 MCS12 = idx;
2198 }
2199 else if (pCurrTxRate->CurrMCS == MCS_13)
2200 {
2201 MCS13 = idx;
2202 }
2203 else if (pCurrTxRate->CurrMCS == MCS_14)
2204 {
2205 MCS14 = idx;
2206 }
2207 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2208 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
2209 {
2210 MCS15 = idx;
2211 }
2212 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2213 {
2214 MCS20 = idx;
2215 }
2216 else if (pCurrTxRate->CurrMCS == MCS_21)
2217 {
2218 MCS21 = idx;
2219 }
2220 else if (pCurrTxRate->CurrMCS == MCS_22)
2221 {
2222 MCS22 = idx;
2223 }
2224 else if (pCurrTxRate->CurrMCS == MCS_23)
2225 {
2226 MCS23 = idx;
2227 }
2228 idx ++;
2229 }
2230
2231 if (pAd->LatchRfRegs.Channel <= 14)
2232 {
2233 if (pAd->NicConfig2.field.ExternalLNAForG)
2234 {
2235 RssiOffset = 2;
2236 }
2237 else
2238 {
2239 RssiOffset = 5;
2240 }
2241 }
2242 else
2243 {
2244 if (pAd->NicConfig2.field.ExternalLNAForA)
2245 {
2246 RssiOffset = 5;
2247 }
2248 else
2249 {
2250 RssiOffset = 8;
2251 }
2252 }
2253 #ifdef DOT11_N_SUPPORT
2254 /*if (MCS15)*/
2255 if ((pTable == RateSwitchTable11BGN3S) ||
2256 (pTable == RateSwitchTable11N3S) ||
2257 (pTable == RateSwitchTable))
2258 {// N mode with 3 stream // 3*3
2259 if (MCS23 && (Rssi >= -70))
2260 TxRateIdx = MCS15;
2261 else if (MCS22 && (Rssi >= -72))
2262 TxRateIdx = MCS14;
2263 else if (MCS21 && (Rssi >= -76))
2264 TxRateIdx = MCS13;
2265 else if (MCS20 && (Rssi >= -78))
2266 TxRateIdx = MCS12;
2267 else if (MCS4 && (Rssi >= -82))
2268 TxRateIdx = MCS4;
2269 else if (MCS3 && (Rssi >= -84))
2270 TxRateIdx = MCS3;
2271 else if (MCS2 && (Rssi >= -86))
2272 TxRateIdx = MCS2;
2273 else if (MCS1 && (Rssi >= -88))
2274 TxRateIdx = MCS1;
2275 else
2276 TxRateIdx = MCS0;
2277 }
2278 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2279 {// N mode with 2 stream
2280 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2281 TxRateIdx = MCS15;
2282 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2283 TxRateIdx = MCS14;
2284 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2285 TxRateIdx = MCS13;
2286 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2287 TxRateIdx = MCS12;
2288 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2289 TxRateIdx = MCS4;
2290 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2291 TxRateIdx = MCS3;
2292 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2293 TxRateIdx = MCS2;
2294 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2295 TxRateIdx = MCS1;
2296 else
2297 TxRateIdx = MCS0;
2298 }
2299 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2300 {// N mode with 1 stream
2301 if (MCS7 && (Rssi > (-72+RssiOffset)))
2302 TxRateIdx = MCS7;
2303 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2304 TxRateIdx = MCS6;
2305 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2306 TxRateIdx = MCS5;
2307 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2308 TxRateIdx = MCS4;
2309 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2310 TxRateIdx = MCS3;
2311 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2312 TxRateIdx = MCS2;
2313 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2314 TxRateIdx = MCS1;
2315 else
2316 TxRateIdx = MCS0;
2317 }
2318 else
2319 #endif // DOT11_N_SUPPORT //
2320 {// Legacy mode
2321 if (MCS7 && (Rssi > -70))
2322 TxRateIdx = MCS7;
2323 else if (MCS6 && (Rssi > -74))
2324 TxRateIdx = MCS6;
2325 else if (MCS5 && (Rssi > -78))
2326 TxRateIdx = MCS5;
2327 else if (MCS4 && (Rssi > -82))
2328 TxRateIdx = MCS4;
2329 else if (MCS4 == 0) // for B-only mode
2330 TxRateIdx = MCS3;
2331 else if (MCS3 && (Rssi > -85))
2332 TxRateIdx = MCS3;
2333 else if (MCS2 && (Rssi > -87))
2334 TxRateIdx = MCS2;
2335 else if (MCS1 && (Rssi > -90))
2336 TxRateIdx = MCS1;
2337 else
2338 TxRateIdx = MCS0;
2339 }
2340
2341 {
2342 pEntry->CurrTxRateIndex = TxRateIdx;
2343 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2344 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2345 }
2346
2347 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2348 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2349 pEntry->fLastSecAccordingRSSI = TRUE;
2350 // reset all OneSecTx counters
2351 RESET_ONE_SEC_TX_CNT(pEntry);
2352
2353 continue;
2354 }
2355
2356 if (pEntry->fLastSecAccordingRSSI == TRUE)
2357 {
2358 pEntry->fLastSecAccordingRSSI = FALSE;
2359 pEntry->LastSecTxRateChangeAction = 0;
2360 // reset all OneSecTx counters
2361 RESET_ONE_SEC_TX_CNT(pEntry);
2362
2363 continue;
2364 }
2365
2366 do
2367 {
2368 BOOLEAN bTrainUpDown = FALSE;
2369
2370 pEntry->CurrTxRateStableTime ++;
2371
2372 // downgrade TX quality if PER >= Rate-Down threshold
2373 if (TxErrorRatio >= TrainDown)
2374 {
2375 bTrainUpDown = TRUE;
2376 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2377 }
2378 // upgrade TX quality if PER <= Rate-Up threshold
2379 else if (TxErrorRatio <= TrainUp)
2380 {
2381 bTrainUpDown = TRUE;
2382 bUpgradeQuality = TRUE;
2383 if (pEntry->TxQuality[CurrRateIdx])
2384 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2385
2386 if (pEntry->TxRateUpPenalty)
2387 pEntry->TxRateUpPenalty --;
2388 else if (pEntry->TxQuality[UpRateIdx])
2389 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2390 }
2391
2392 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2393
2394 if (bTrainUpDown)
2395 {
2396 // perform DRS - consider TxRate Down first, then rate up.
2397 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2398 {
2399 pEntry->CurrTxRateIndex = DownRateIdx;
2400 }
2401 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2402 {
2403 pEntry->CurrTxRateIndex = UpRateIdx;
2404 }
2405 }
2406 } while (FALSE);
2407
2408 // if rate-up happen, clear all bad history of all TX rates
2409 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2410 {
2411 pEntry->CurrTxRateStableTime = 0;
2412 pEntry->TxRateUpPenalty = 0;
2413 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2414 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2415 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2416
2417 //
2418 // For TxRate fast train up
2419 //
2420 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2421 {
2422 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2423
2424 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2425 }
2426 bTxRateChanged = TRUE;
2427 }
2428 // if rate-down happen, only clear DownRate's bad history
2429 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2430 {
2431 pEntry->CurrTxRateStableTime = 0;
2432 pEntry->TxRateUpPenalty = 0; // no penalty
2433 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2434 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2435 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2436
2437 //
2438 // For TxRate fast train down
2439 //
2440 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2441 {
2442 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2443
2444 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2445 }
2446 bTxRateChanged = TRUE;
2447 }
2448 else
2449 {
2450 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2451 bTxRateChanged = FALSE;
2452 }
2453
2454 pEntry->LastTxOkCount = TxSuccess;
2455
2456 // reset all OneSecTx counters
2457 RESET_ONE_SEC_TX_CNT(pEntry);
2458
2459 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2460 if (bTxRateChanged && pNextTxRate)
2461 {
2462 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2463 }
2464 }
2465 }
2466
2467 /*
2468 ========================================================================
2469 Routine Description:
2470 Station side, Auto TxRate faster train up timer call back function.
2471
2472 Arguments:
2473 SystemSpecific1 - Not used.
2474 FunctionContext - Pointer to our Adapter context.
2475 SystemSpecific2 - Not used.
2476 SystemSpecific3 - Not used.
2477
2478 Return Value:
2479 None
2480
2481 ========================================================================
2482 */
2483 VOID StaQuickResponeForRateUpExec(
2484 IN PVOID SystemSpecific1,
2485 IN PVOID FunctionContext,
2486 IN PVOID SystemSpecific2,
2487 IN PVOID SystemSpecific3)
2488 {
2489 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2490 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2491 ULONG TxTotalCnt;
2492 ULONG TxErrorRatio = 0;
2493 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2494 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2495 PUCHAR pTable;
2496 UCHAR TableSize = 0;
2497 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2498 TX_STA_CNT1_STRUC StaTx1;
2499 TX_STA_CNT0_STRUC TxStaCnt0;
2500 CHAR Rssi, ratio;
2501 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2502 MAC_TABLE_ENTRY *pEntry;
2503 ULONG i;
2504
2505 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2506
2507 //
2508 // walk through MAC table, see if need to change AP's TX rate toward each entry
2509 //
2510 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2511 {
2512 pEntry = &pAd->MacTab.Content[i];
2513
2514 // check if this entry need to switch rate automatically
2515 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2516 continue;
2517
2518 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2519 if (pAd->Antenna.field.TxPath > 1)
2520 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2521 else
2522 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2523
2524 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2525
2526 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2527
2528 // decide the next upgrade rate and downgrade rate, if any
2529 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2530 {
2531 UpRateIdx = CurrRateIdx + 1;
2532 DownRateIdx = CurrRateIdx -1;
2533 }
2534 else if (CurrRateIdx == 0)
2535 {
2536 UpRateIdx = CurrRateIdx + 1;
2537 DownRateIdx = CurrRateIdx;
2538 }
2539 else if (CurrRateIdx == (TableSize - 1))
2540 {
2541 UpRateIdx = CurrRateIdx;
2542 DownRateIdx = CurrRateIdx - 1;
2543 }
2544
2545 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2546
2547 #ifdef DOT11_N_SUPPORT
2548 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2549 {
2550 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2551 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2552 }
2553 else
2554 #endif // DOT11_N_SUPPORT //
2555 {
2556 TrainUp = pCurrTxRate->TrainUp;
2557 TrainDown = pCurrTxRate->TrainDown;
2558 }
2559
2560 if (pAd->MacTab.Size == 1)
2561 {
2562 // Update statistic counter
2563 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2564 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2565
2566 TxRetransmit = StaTx1.field.TxRetransmit;
2567 TxSuccess = StaTx1.field.TxSuccess;
2568 TxFailCount = TxStaCnt0.field.TxFailCount;
2569 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2570
2571 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2572 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2573 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2574 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2575 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2576 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2577
2578 if (TxTotalCnt)
2579 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2580 }
2581 else
2582 {
2583 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2584 pEntry->OneSecTxRetryOkCount +
2585 pEntry->OneSecTxFailCount;
2586
2587 if (TxTotalCnt)
2588 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2589 }
2590
2591
2592 //
2593 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2594 // (criteria copied from RT2500 for Netopia case)
2595 //
2596 if (TxTotalCnt <= 12)
2597 {
2598 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2599 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2600
2601 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2602 {
2603 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2604 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2605 }
2606 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2607 {
2608 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2609 }
2610
2611 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2612 return;
2613 }
2614
2615 do
2616 {
2617 ULONG OneSecTxNoRetryOKRationCount;
2618
2619 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2620 ratio = 5;
2621 else
2622 ratio = 4;
2623
2624 // downgrade TX quality if PER >= Rate-Down threshold
2625 if (TxErrorRatio >= TrainDown)
2626 {
2627 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2628 }
2629
2630 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2631
2632 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2633
2634 // perform DRS - consider TxRate Down first, then rate up.
2635 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2636 {
2637 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2638 {
2639 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2640 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2641
2642 }
2643
2644 }
2645 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2646 {
2647 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2648 {
2649
2650 }
2651 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2652 {
2653 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2654 }
2655 }
2656 }while (FALSE);
2657
2658 // if rate-up happen, clear all bad history of all TX rates
2659 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2660 {
2661 pAd->DrsCounters.TxRateUpPenalty = 0;
2662 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2663 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2664 }
2665 // if rate-down happen, only clear DownRate's bad history
2666 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2667 {
2668 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2669
2670 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2671 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2672 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2673 }
2674 else
2675 {
2676 bTxRateChanged = FALSE;
2677 }
2678
2679 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2680 if (bTxRateChanged && pNextTxRate)
2681 {
2682 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2683 }
2684 }
2685 }
2686
2687 /*
2688 ==========================================================================
2689 Description:
2690 This routine is executed periodically inside MlmePeriodicExec() after
2691 association with an AP.
2692 It checks if StaCfg.Psm is consistent with user policy (recorded in
2693 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2694 there're some conditions to consider:
2695 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2696 the time when Mibss==TRUE
2697 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2698 if outgoing traffic available in TxRing or MgmtRing.
2699 Output:
2700 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2701
2702 IRQL = DISPATCH_LEVEL
2703
2704 ==========================================================================
2705 */
2706 VOID MlmeCheckPsmChange(
2707 IN PRTMP_ADAPTER pAd,
2708 IN ULONG Now32)
2709 {
2710 ULONG PowerMode;
2711
2712 // condition -
2713 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2714 // 2. user wants either MAX_PSP or FAST_PSP
2715 // 3. but current psm is not in PWR_SAVE
2716 // 4. CNTL state machine is not doing SCANning
2717 // 5. no TX SUCCESS event for the past 1-sec period
2718 #ifdef NDIS51_MINIPORT
2719 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2720 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2721 else
2722 #endif
2723 PowerMode = pAd->StaCfg.WindowsPowerMode;
2724
2725 if (INFRA_ON(pAd) &&
2726 (PowerMode != Ndis802_11PowerModeCAM) &&
2727 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2728 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2729 {
2730 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2731 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2732 MlmeSetPsmBit(pAd, PWR_SAVE);
2733 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2734 {
2735 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2736 }
2737 else
2738 {
2739 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2740 }
2741 }
2742 }
2743
2744 // IRQL = PASSIVE_LEVEL
2745 // IRQL = DISPATCH_LEVEL
2746 VOID MlmeSetPsmBit(
2747 IN PRTMP_ADAPTER pAd,
2748 IN USHORT psm)
2749 {
2750 AUTO_RSP_CFG_STRUC csr4;
2751
2752 pAd->StaCfg.Psm = psm;
2753 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2754 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2755 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2756 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2757 }
2758 #endif // CONFIG_STA_SUPPORT //
2759
2760
2761 // IRQL = DISPATCH_LEVEL
2762 VOID MlmeSetTxPreamble(
2763 IN PRTMP_ADAPTER pAd,
2764 IN USHORT TxPreamble)
2765 {
2766 AUTO_RSP_CFG_STRUC csr4;
2767
2768 //
2769 // Always use Long preamble before verifiation short preamble functionality works well.
2770 // Todo: remove the following line if short preamble functionality works
2771 //
2772 //TxPreamble = Rt802_11PreambleLong;
2773
2774 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2775 if (TxPreamble == Rt802_11PreambleLong)
2776 {
2777 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2778 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2779 csr4.field.AutoResponderPreamble = 0;
2780 }
2781 else
2782 {
2783 // NOTE: 1Mbps should always use long preamble
2784 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2785 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2786 csr4.field.AutoResponderPreamble = 1;
2787 }
2788
2789 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2790 }
2791
2792 /*
2793 ==========================================================================
2794 Description:
2795 Update basic rate bitmap
2796 ==========================================================================
2797 */
2798
2799 VOID UpdateBasicRateBitmap(
2800 IN PRTMP_ADAPTER pAdapter)
2801 {
2802 INT i, j;
2803 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2804 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2805 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2806 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2807 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2808
2809
2810 /* if A mode, always use fix BasicRateBitMap */
2811 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2812 if (pAdapter->CommonCfg.Channel > 14)
2813 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2814 /* End of if */
2815
2816 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2817 {
2818 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2819 return;
2820 } /* End of if */
2821
2822 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2823 {
2824 sup_p[i] &= 0x7f;
2825 ext_p[i] &= 0x7f;
2826 } /* End of for */
2827
2828 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2829 {
2830 if (bitmap & (1 << i))
2831 {
2832 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2833 {
2834 if (sup_p[j] == rate[i])
2835 sup_p[j] |= 0x80;
2836 /* End of if */
2837 } /* End of for */
2838
2839 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2840 {
2841 if (ext_p[j] == rate[i])
2842 ext_p[j] |= 0x80;
2843 /* End of if */
2844 } /* End of for */
2845 } /* End of if */
2846 } /* End of for */
2847 } /* End of UpdateBasicRateBitmap */
2848
2849 // IRQL = PASSIVE_LEVEL
2850 // IRQL = DISPATCH_LEVEL
2851 // bLinkUp is to identify the inital link speed.
2852 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2853 VOID MlmeUpdateTxRates(
2854 IN PRTMP_ADAPTER pAd,
2855 IN BOOLEAN bLinkUp,
2856 IN UCHAR apidx)
2857 {
2858 int i, num;
2859 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2860 UCHAR MinSupport = RATE_54;
2861 ULONG BasicRateBitmap = 0;
2862 UCHAR CurrBasicRate = RATE_1;
2863 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2864 PHTTRANSMIT_SETTING pHtPhy = NULL;
2865 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2866 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2867 BOOLEAN *auto_rate_cur_p;
2868 UCHAR HtMcs = MCS_AUTO;
2869
2870 // find max desired rate
2871 UpdateBasicRateBitmap(pAd);
2872
2873 num = 0;
2874 auto_rate_cur_p = NULL;
2875 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2876 {
2877 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2878 {
2879 case 2: Rate = RATE_1; num++; break;
2880 case 4: Rate = RATE_2; num++; break;
2881 case 11: Rate = RATE_5_5; num++; break;
2882 case 22: Rate = RATE_11; num++; break;
2883 case 12: Rate = RATE_6; num++; break;
2884 case 18: Rate = RATE_9; num++; break;
2885 case 24: Rate = RATE_12; num++; break;
2886 case 36: Rate = RATE_18; num++; break;
2887 case 48: Rate = RATE_24; num++; break;
2888 case 72: Rate = RATE_36; num++; break;
2889 case 96: Rate = RATE_48; num++; break;
2890 case 108: Rate = RATE_54; num++; break;
2891 //default: Rate = RATE_1; break;
2892 }
2893 if (MaxDesire < Rate) MaxDesire = Rate;
2894 }
2895
2896 //===========================================================================
2897 //===========================================================================
2898
2899 #ifdef CONFIG_STA_SUPPORT
2900 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2901 {
2902 pHtPhy = &pAd->StaCfg.HTPhyMode;
2903 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2904 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2905
2906 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2907 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2908
2909 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2910 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2911 (MaxDesire > RATE_11))
2912 {
2913 MaxDesire = RATE_11;
2914 }
2915 }
2916 #endif // CONFIG_STA_SUPPORT //
2917
2918 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2919 pMinHtPhy->word = 0;
2920 pMaxHtPhy->word = 0;
2921 pHtPhy->word = 0;
2922
2923 // Auto rate switching is enabled only if more than one DESIRED RATES are
2924 // specified; otherwise disabled
2925 if (num <= 1)
2926 {
2927 *auto_rate_cur_p = FALSE;
2928 }
2929 else
2930 {
2931 *auto_rate_cur_p = TRUE;
2932 }
2933
2934 #if 1
2935 if (HtMcs != MCS_AUTO)
2936 {
2937 *auto_rate_cur_p = FALSE;
2938 }
2939 else
2940 {
2941 *auto_rate_cur_p = TRUE;
2942 }
2943 #endif
2944
2945 #ifdef CONFIG_STA_SUPPORT
2946 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2947 {
2948 pSupRate = &pAd->StaActive.SupRate[0];
2949 pExtRate = &pAd->StaActive.ExtRate[0];
2950 SupRateLen = pAd->StaActive.SupRateLen;
2951 ExtRateLen = pAd->StaActive.ExtRateLen;
2952 }
2953 else
2954 #endif // CONFIG_STA_SUPPORT //
2955 {
2956 pSupRate = &pAd->CommonCfg.SupRate[0];
2957 pExtRate = &pAd->CommonCfg.ExtRate[0];
2958 SupRateLen = pAd->CommonCfg.SupRateLen;
2959 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2960 }
2961
2962 // find max supported rate
2963 for (i=0; i<SupRateLen; i++)
2964 {
2965 switch (pSupRate[i] & 0x7f)
2966 {
2967 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2968 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2969 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2970 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2971 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2972 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2973 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2974 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2975 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2976 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2977 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2978 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2979 default: Rate = RATE_1; break;
2980 }
2981 if (MaxSupport < Rate) MaxSupport = Rate;
2982
2983 if (MinSupport > Rate) MinSupport = Rate;
2984 }
2985
2986 for (i=0; i<ExtRateLen; i++)
2987 {
2988 switch (pExtRate[i] & 0x7f)
2989 {
2990 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2991 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2992 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2993 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2994 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2995 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2996 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2997 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2998 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2999 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3000 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3001 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3002 default: Rate = RATE_1; break;
3003 }
3004 if (MaxSupport < Rate) MaxSupport = Rate;
3005
3006 if (MinSupport > Rate) MinSupport = Rate;
3007 }
3008
3009 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3010
3011 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3012 // the DURATION field of outgoing uniicast DATA/MGMT frame
3013 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3014 {
3015 if (BasicRateBitmap & (0x01 << i))
3016 CurrBasicRate = (UCHAR)i;
3017 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3018 }
3019
3020 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3021 // max tx rate = min {max desire rate, max supported rate}
3022 if (MaxSupport < MaxDesire)
3023 pAd->CommonCfg.MaxTxRate = MaxSupport;
3024 else
3025 pAd->CommonCfg.MaxTxRate = MaxDesire;
3026
3027 pAd->CommonCfg.MinTxRate = MinSupport;
3028 if (*auto_rate_cur_p)
3029 {
3030 short dbm = 0;
3031 #ifdef CONFIG_STA_SUPPORT
3032 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3033 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3034 #endif // CONFIG_STA_SUPPORT //
3035 if (bLinkUp == TRUE)
3036 pAd->CommonCfg.TxRate = RATE_24;
3037 else
3038 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3039
3040 if (dbm < -75)
3041 pAd->CommonCfg.TxRate = RATE_11;
3042 else if (dbm < -70)
3043 pAd->CommonCfg.TxRate = RATE_24;
3044
3045 // should never exceed MaxTxRate (consider 11B-only mode)
3046 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3047 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3048
3049 pAd->CommonCfg.TxRateIndex = 0;
3050 }
3051 else
3052 {
3053 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3054 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3055 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3056
3057 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3058 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3059 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3060 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3061 }
3062
3063 if (pAd->CommonCfg.TxRate <= RATE_11)
3064 {
3065 pMaxHtPhy->field.MODE = MODE_CCK;
3066 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3067 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3068 }
3069 else
3070 {
3071 pMaxHtPhy->field.MODE = MODE_OFDM;
3072 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3073 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3074 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3075 else
3076 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3077 }
3078
3079 pHtPhy->word = (pMaxHtPhy->word);
3080 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3081 {
3082 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3083 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3084 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3085 }
3086 else
3087 {
3088 switch (pAd->CommonCfg.PhyMode)
3089 {
3090 case PHY_11BG_MIXED:
3091 case PHY_11B:
3092 #ifdef DOT11_N_SUPPORT
3093 case PHY_11BGN_MIXED:
3094 #endif // DOT11_N_SUPPORT //
3095 pAd->CommonCfg.MlmeRate = RATE_1;
3096 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3097 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3098 pAd->CommonCfg.RtsRate = RATE_11;
3099 break;
3100 case PHY_11G:
3101 case PHY_11A:
3102 #ifdef DOT11_N_SUPPORT
3103 case PHY_11AGN_MIXED:
3104 case PHY_11GN_MIXED:
3105 case PHY_11N_2_4G:
3106 case PHY_11AN_MIXED:
3107 case PHY_11N_5G:
3108 #endif // DOT11_N_SUPPORT //
3109 pAd->CommonCfg.MlmeRate = RATE_6;
3110 pAd->CommonCfg.RtsRate = RATE_6;
3111 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3112 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3113 break;
3114 case PHY_11ABG_MIXED:
3115 #ifdef DOT11_N_SUPPORT
3116 case PHY_11ABGN_MIXED:
3117 #endif // DOT11_N_SUPPORT //
3118 if (pAd->CommonCfg.Channel <= 14)
3119 {
3120 pAd->CommonCfg.MlmeRate = RATE_1;
3121 pAd->CommonCfg.RtsRate = RATE_1;
3122 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3123 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3124 }
3125 else
3126 {
3127 pAd->CommonCfg.MlmeRate = RATE_6;
3128 pAd->CommonCfg.RtsRate = RATE_6;
3129 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3130 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3131 }
3132 break;
3133 default: // error
3134 pAd->CommonCfg.MlmeRate = RATE_6;
3135 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3136 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3137 pAd->CommonCfg.RtsRate = RATE_1;
3138 break;
3139 }
3140 //
3141 // Keep Basic Mlme Rate.
3142 //
3143 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3144 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3145 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3146 else
3147 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3148 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3149 }
3150
3151 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3152 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3153 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3154 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3155 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3156 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3157 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 ));
3158 }
3159
3160 #ifdef DOT11_N_SUPPORT
3161 /*
3162 ==========================================================================
3163 Description:
3164 This function update HT Rate setting.
3165 Input Wcid value is valid for 2 case :
3166 1. it's used for Station in infra mode that copy AP rate to Mactable.
3167 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3168
3169 IRQL = DISPATCH_LEVEL
3170
3171 ==========================================================================
3172 */
3173 VOID MlmeUpdateHtTxRates(
3174 IN PRTMP_ADAPTER pAd,
3175 IN UCHAR apidx)
3176 {
3177 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3178 CHAR i; // 3*3
3179 RT_HT_CAPABILITY *pRtHtCap = NULL;
3180 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3181 ULONG BasicMCS;
3182 UCHAR j, bitmask;
3183 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3184 PHTTRANSMIT_SETTING pHtPhy = NULL;
3185 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3186 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3187 BOOLEAN *auto_rate_cur_p;
3188
3189 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3190
3191 auto_rate_cur_p = NULL;
3192
3193 #ifdef CONFIG_STA_SUPPORT
3194 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3195 {
3196 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3197 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3198 pHtPhy = &pAd->StaCfg.HTPhyMode;
3199 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3200 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3201
3202 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3203 }
3204 #endif // CONFIG_STA_SUPPORT //
3205
3206 #ifdef CONFIG_STA_SUPPORT
3207 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3208 {
3209 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3210 return;
3211
3212 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3213 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3214 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3215 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3216 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3217 pMaxHtPhy->field.STBC = STBC_USE;
3218 else
3219 pMaxHtPhy->field.STBC = STBC_NONE;
3220 }
3221 else
3222 #endif // CONFIG_STA_SUPPORT //
3223 {
3224 if (pDesireHtPhy->bHtEnable == FALSE)
3225 return;
3226
3227 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3228 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3229 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3230 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3231 pMaxHtPhy->field.STBC = STBC_USE;
3232 else
3233 pMaxHtPhy->field.STBC = STBC_NONE;
3234 }
3235
3236 // Decide MAX ht rate.
3237 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3238 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3239 else
3240 pMaxHtPhy->field.MODE = MODE_HTMIX;
3241
3242 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3243 pMaxHtPhy->field.BW = BW_40;
3244 else
3245 pMaxHtPhy->field.BW = BW_20;
3246
3247 if (pMaxHtPhy->field.BW == BW_20)
3248 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3249 else
3250 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3251
3252 for (i=23; i>=0; i--) // 3*3
3253 {
3254 j = i/8;
3255 bitmask = (1<<(i-(j*8)));
3256
3257 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3258 {
3259 pMaxHtPhy->field.MCS = i;
3260 break;
3261 }
3262
3263 if (i==0)
3264 break;
3265 }
3266
3267 // Copy MIN ht rate. rt2860???
3268 pMinHtPhy->field.BW = BW_20;
3269 pMinHtPhy->field.MCS = 0;
3270 pMinHtPhy->field.STBC = 0;
3271 pMinHtPhy->field.ShortGI = 0;
3272 //If STA assigns fixed rate. update to fixed here.
3273 #ifdef CONFIG_STA_SUPPORT
3274 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3275 {
3276 if (pDesireHtPhy->MCSSet[4] != 0)
3277 {
3278 pMaxHtPhy->field.MCS = 32;
3279 pMinHtPhy->field.MCS = 32;
3280 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3281 }
3282
3283 for (i=23; (CHAR)i >= 0; i--) // 3*3
3284 {
3285 j = i/8;
3286 bitmask = (1<<(i-(j*8)));
3287 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3288 {
3289 pMaxHtPhy->field.MCS = i;
3290 pMinHtPhy->field.MCS = i;
3291 break;
3292 }
3293 if (i==0)
3294 break;
3295 }
3296 }
3297 #endif // CONFIG_STA_SUPPORT //
3298
3299
3300 // Decide ht rate
3301 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3302 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3303 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3304 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3305 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3306
3307 // use default now. rt2860
3308 if (pDesireHtPhy->MCSSet[0] != 0xff)
3309 *auto_rate_cur_p = FALSE;
3310 else
3311 *auto_rate_cur_p = TRUE;
3312
3313 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3314 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3315 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3316 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3317 }
3318 #endif // DOT11_N_SUPPORT //
3319
3320 // IRQL = DISPATCH_LEVEL
3321 VOID MlmeRadioOff(
3322 IN PRTMP_ADAPTER pAd)
3323 {
3324 RT28XX_MLME_RADIO_OFF(pAd);
3325 }
3326
3327 // IRQL = DISPATCH_LEVEL
3328 VOID MlmeRadioOn(
3329 IN PRTMP_ADAPTER pAd)
3330 {
3331 RT28XX_MLME_RADIO_ON(pAd);
3332 }
3333
3334 // ===========================================================================================
3335 // bss_table.c
3336 // ===========================================================================================
3337
3338
3339 /*! \brief initialize BSS table
3340 * \param p_tab pointer to the table
3341 * \return none
3342 * \pre
3343 * \post
3344
3345 IRQL = PASSIVE_LEVEL
3346 IRQL = DISPATCH_LEVEL
3347
3348 */
3349 VOID BssTableInit(
3350 IN BSS_TABLE *Tab)
3351 {
3352 int i;
3353
3354 Tab->BssNr = 0;
3355 Tab->BssOverlapNr = 0;
3356 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3357 {
3358 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3359 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3360 }
3361 }
3362
3363 #ifdef DOT11_N_SUPPORT
3364 VOID BATableInit(
3365 IN PRTMP_ADAPTER pAd,
3366 IN BA_TABLE *Tab)
3367 {
3368 int i;
3369
3370 Tab->numAsOriginator = 0;
3371 Tab->numAsRecipient = 0;
3372 NdisAllocateSpinLock(&pAd->BATabLock);
3373 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3374 {
3375 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3376 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3377 }
3378 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3379 {
3380 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3381 }
3382 }
3383 #endif // DOT11_N_SUPPORT //
3384
3385 /*! \brief search the BSS table by SSID
3386 * \param p_tab pointer to the bss table
3387 * \param ssid SSID string
3388 * \return index of the table, BSS_NOT_FOUND if not in the table
3389 * \pre
3390 * \post
3391 * \note search by sequential search
3392
3393 IRQL = DISPATCH_LEVEL
3394
3395 */
3396 ULONG BssTableSearch(
3397 IN BSS_TABLE *Tab,
3398 IN PUCHAR pBssid,
3399 IN UCHAR Channel)
3400 {
3401 UCHAR i;
3402
3403 for (i = 0; i < Tab->BssNr; i++)
3404 {
3405 //
3406 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3407 // We should distinguish this case.
3408 //
3409 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3410 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3411 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3412 {
3413 return i;
3414 }
3415 }
3416 return (ULONG)BSS_NOT_FOUND;
3417 }
3418
3419 ULONG BssSsidTableSearch(
3420 IN BSS_TABLE *Tab,
3421 IN PUCHAR pBssid,
3422 IN PUCHAR pSsid,
3423 IN UCHAR SsidLen,
3424 IN UCHAR Channel)
3425 {
3426 UCHAR i;
3427
3428 for (i = 0; i < Tab->BssNr; i++)
3429 {
3430 //
3431 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3432 // We should distinguish this case.
3433 //
3434 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3435 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3436 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3437 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3438 {
3439 return i;
3440 }
3441 }
3442 return (ULONG)BSS_NOT_FOUND;
3443 }
3444
3445 ULONG BssTableSearchWithSSID(
3446 IN BSS_TABLE *Tab,
3447 IN PUCHAR Bssid,
3448 IN PUCHAR pSsid,
3449 IN UCHAR SsidLen,
3450 IN UCHAR Channel)
3451 {
3452 UCHAR i;
3453
3454 for (i = 0; i < Tab->BssNr; i++)
3455 {
3456 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3457 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3458 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3459 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3460 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3461 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3462 {
3463 return i;
3464 }
3465 }
3466 return (ULONG)BSS_NOT_FOUND;
3467 }
3468
3469 // IRQL = DISPATCH_LEVEL
3470 VOID BssTableDeleteEntry(
3471 IN OUT BSS_TABLE *Tab,
3472 IN PUCHAR pBssid,
3473 IN UCHAR Channel)
3474 {
3475 UCHAR i, j;
3476
3477 for (i = 0; i < Tab->BssNr; i++)
3478 {
3479 if ((Tab->BssEntry[i].Channel == Channel) &&
3480 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3481 {
3482 for (j = i; j < Tab->BssNr - 1; j++)
3483 {
3484 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3485 }
3486 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3487 Tab->BssNr -= 1;
3488 return;
3489 }
3490 }
3491 }
3492
3493 #ifdef DOT11_N_SUPPORT
3494 /*
3495 ========================================================================
3496 Routine Description:
3497 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3498
3499 Arguments:
3500 // IRQL = DISPATCH_LEVEL
3501 ========================================================================
3502 */
3503 VOID BATableDeleteORIEntry(
3504 IN OUT PRTMP_ADAPTER pAd,
3505 IN BA_ORI_ENTRY *pBAORIEntry)
3506 {
3507
3508 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3509 {
3510 NdisAcquireSpinLock(&pAd->BATabLock);
3511 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3512 {
3513 pAd->BATable.numAsOriginator -= 1;
3514 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3515 // Erase Bitmap flag.
3516 }
3517 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3518 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3519 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3520 pBAORIEntry->Token = 1;
3521 // Not clear Sequence here.
3522 NdisReleaseSpinLock(&pAd->BATabLock);
3523 }
3524 }
3525 #endif // DOT11_N_SUPPORT //
3526
3527 /*! \brief
3528 * \param
3529 * \return
3530 * \pre
3531 * \post
3532
3533 IRQL = DISPATCH_LEVEL
3534
3535 */
3536 VOID BssEntrySet(
3537 IN PRTMP_ADAPTER pAd,
3538 OUT BSS_ENTRY *pBss,
3539 IN PUCHAR pBssid,
3540 IN CHAR Ssid[],
3541 IN UCHAR SsidLen,
3542 IN UCHAR BssType,
3543 IN USHORT BeaconPeriod,
3544 IN PCF_PARM pCfParm,
3545 IN USHORT AtimWin,
3546 IN USHORT CapabilityInfo,
3547 IN UCHAR SupRate[],
3548 IN UCHAR SupRateLen,
3549 IN UCHAR ExtRate[],
3550 IN UCHAR ExtRateLen,
3551 IN HT_CAPABILITY_IE *pHtCapability,
3552 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3553 IN UCHAR HtCapabilityLen,
3554 IN UCHAR AddHtInfoLen,
3555 IN UCHAR NewExtChanOffset,
3556 IN UCHAR Channel,
3557 IN CHAR Rssi,
3558 IN LARGE_INTEGER TimeStamp,
3559 IN UCHAR CkipFlag,
3560 IN PEDCA_PARM pEdcaParm,
3561 IN PQOS_CAPABILITY_PARM pQosCapability,
3562 IN PQBSS_LOAD_PARM pQbssLoad,
3563 IN USHORT LengthVIE,
3564 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3565 {
3566 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3567 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3568 pBss->Hidden = 1;
3569 if (SsidLen > 0)
3570 {
3571 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3572 // Or send beacon /probe response with SSID len matching real SSID length,
3573 // but SSID is all zero. such as "00-00-00-00" with length 4.
3574 // We have to prevent this case overwrite correct table
3575 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3576 {
3577 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3578 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3579 pBss->SsidLen = SsidLen;
3580 pBss->Hidden = 0;
3581 }
3582 }
3583 else
3584 pBss->SsidLen = 0;
3585 pBss->BssType = BssType;
3586 pBss->BeaconPeriod = BeaconPeriod;
3587 if (BssType == BSS_INFRA)
3588 {
3589 if (pCfParm->bValid)
3590 {
3591 pBss->CfpCount = pCfParm->CfpCount;
3592 pBss->CfpPeriod = pCfParm->CfpPeriod;
3593 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3594 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3595 }
3596 }
3597 else
3598 {
3599 pBss->AtimWin = AtimWin;
3600 }
3601
3602 pBss->CapabilityInfo = CapabilityInfo;
3603 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3604 // Combine with AuthMode, they will decide the connection methods.
3605 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3606 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3607 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3608 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3609 else
3610 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3611 pBss->SupRateLen = SupRateLen;
3612 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3613 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3614 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3615 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3616 pBss->NewExtChanOffset = NewExtChanOffset;
3617 pBss->ExtRateLen = ExtRateLen;
3618 pBss->Channel = Channel;
3619 pBss->CentralChannel = Channel;
3620 pBss->Rssi = Rssi;
3621 // Update CkipFlag. if not exists, the value is 0x0
3622 pBss->CkipFlag = CkipFlag;
3623
3624 // New for microsoft Fixed IEs
3625 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3626 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3627 pBss->FixIEs.Capabilities = CapabilityInfo;
3628
3629 // New for microsoft Variable IEs
3630 if (LengthVIE != 0)
3631 {
3632 pBss->VarIELen = LengthVIE;
3633 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3634 }
3635 else
3636 {
3637 pBss->VarIELen = 0;
3638 }
3639
3640 pBss->AddHtInfoLen = 0;
3641 pBss->HtCapabilityLen = 0;
3642 #ifdef DOT11_N_SUPPORT
3643 if (HtCapabilityLen> 0)
3644 {
3645 pBss->HtCapabilityLen = HtCapabilityLen;
3646 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3647 if (AddHtInfoLen > 0)
3648 {
3649 pBss->AddHtInfoLen = AddHtInfoLen;
3650 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3651
3652 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3653 {
3654 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3655 }
3656 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3657 {
3658 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3659 }
3660 }
3661 }
3662 #endif // DOT11_N_SUPPORT //
3663
3664 BssCipherParse(pBss);
3665
3666 // new for QOS
3667 if (pEdcaParm)
3668 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3669 else
3670 pBss->EdcaParm.bValid = FALSE;
3671 if (pQosCapability)
3672 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3673 else
3674 pBss->QosCapability.bValid = FALSE;
3675 if (pQbssLoad)
3676 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3677 else
3678 pBss->QbssLoad.bValid = FALSE;
3679
3680 #ifdef CONFIG_STA_SUPPORT
3681 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3682 {
3683 PEID_STRUCT pEid;
3684 USHORT Length = 0;
3685
3686
3687 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3688 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3689
3690 pEid = (PEID_STRUCT) pVIE;
3691
3692 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3693 {
3694 switch(pEid->Eid)
3695 {
3696 case IE_WPA:
3697 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3698 {
3699 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3700 {
3701 pBss->WpaIE.IELen = 0;
3702 break;
3703 }
3704 pBss->WpaIE.IELen = pEid->Len + 2;
3705 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3706 }
3707 break;
3708 case IE_RSN:
3709 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3710 {
3711 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3712 {
3713 pBss->RsnIE.IELen = 0;
3714 break;
3715 }
3716 pBss->RsnIE.IELen = pEid->Len + 2;
3717 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3718 }
3719 break;
3720 }
3721 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3722 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3723 }
3724 }
3725 #endif // CONFIG_STA_SUPPORT //
3726 }
3727
3728 /*!
3729 * \brief insert an entry into the bss table
3730 * \param p_tab The BSS table
3731 * \param Bssid BSSID
3732 * \param ssid SSID
3733 * \param ssid_len Length of SSID
3734 * \param bss_type
3735 * \param beacon_period
3736 * \param timestamp
3737 * \param p_cf
3738 * \param atim_win
3739 * \param cap
3740 * \param rates
3741 * \param rates_len
3742 * \param channel_idx
3743 * \return none
3744 * \pre
3745 * \post
3746 * \note If SSID is identical, the old entry will be replaced by the new one
3747
3748 IRQL = DISPATCH_LEVEL
3749
3750 */
3751 ULONG BssTableSetEntry(
3752 IN PRTMP_ADAPTER pAd,
3753 OUT BSS_TABLE *Tab,
3754 IN PUCHAR pBssid,
3755 IN CHAR Ssid[],
3756 IN UCHAR SsidLen,
3757 IN UCHAR BssType,
3758 IN USHORT BeaconPeriod,
3759 IN CF_PARM *CfParm,
3760 IN USHORT AtimWin,
3761 IN USHORT CapabilityInfo,
3762 IN UCHAR SupRate[],
3763 IN UCHAR SupRateLen,
3764 IN UCHAR ExtRate[],
3765 IN UCHAR ExtRateLen,
3766 IN HT_CAPABILITY_IE *pHtCapability,
3767 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3768 IN UCHAR HtCapabilityLen,
3769 IN UCHAR AddHtInfoLen,
3770 IN UCHAR NewExtChanOffset,
3771 IN UCHAR ChannelNo,
3772 IN CHAR Rssi,
3773 IN LARGE_INTEGER TimeStamp,
3774 IN UCHAR CkipFlag,
3775 IN PEDCA_PARM pEdcaParm,
3776 IN PQOS_CAPABILITY_PARM pQosCapability,
3777 IN PQBSS_LOAD_PARM pQbssLoad,
3778 IN USHORT LengthVIE,
3779 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3780 {
3781 ULONG Idx;
3782
3783 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3784 if (Idx == BSS_NOT_FOUND)
3785 {
3786 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3787 {
3788 //
3789 // It may happen when BSS Table was full.
3790 // The desired AP will not be added into BSS Table
3791 // In this case, if we found the desired AP then overwrite BSS Table.
3792 //
3793 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3794 {
3795 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3796 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3797 {
3798 Idx = Tab->BssOverlapNr;
3799 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3800 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3801 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3802 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3803 }
3804 return Idx;
3805 }
3806 else
3807 {
3808 return BSS_NOT_FOUND;
3809 }
3810 }
3811 Idx = Tab->BssNr;
3812 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3813 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3814 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3815 Tab->BssNr++;
3816 }
3817 else
3818 {
3819 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3820 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3821 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3822 }
3823
3824 return Idx;
3825 }
3826
3827 #ifdef CONFIG_STA_SUPPORT
3828 // IRQL = DISPATCH_LEVEL
3829 VOID BssTableSsidSort(
3830 IN PRTMP_ADAPTER pAd,
3831 OUT BSS_TABLE *OutTab,
3832 IN CHAR Ssid[],
3833 IN UCHAR SsidLen)
3834 {
3835 INT i;
3836 BssTableInit(OutTab);
3837
3838 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3839 {
3840 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3841 BOOLEAN bIsHiddenApIncluded = FALSE;
3842
3843 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3844 (pAd->MlmeAux.Channel > 14) &&
3845 RadarChannelCheck(pAd, pInBss->Channel))
3846 )
3847 {
3848 if (pInBss->Hidden)
3849 bIsHiddenApIncluded = TRUE;
3850 }
3851
3852 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3853 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3854 {
3855 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3856 #ifdef DOT11_N_SUPPORT
3857 // 2.4G/5G N only mode
3858 if ((pInBss->HtCapabilityLen == 0) &&
3859 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3860 {
3861 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3862 continue;
3863 }
3864 #endif // DOT11_N_SUPPORT //
3865
3866 // New for WPA2
3867 // Check the Authmode first
3868 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3869 {
3870 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3871 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3872 // None matched
3873 continue;
3874
3875 // Check cipher suite, AP must have more secured cipher than station setting
3876 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3877 {
3878 // If it's not mixed mode, we should only let BSS pass with the same encryption
3879 if (pInBss->WPA.bMixMode == FALSE)
3880 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3881 continue;
3882
3883 // check group cipher
3884 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3885 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3886 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3887 continue;
3888
3889 // check pairwise cipher, skip if none matched
3890 // If profile set to AES, let it pass without question.
3891 // If profile set to TKIP, we must find one mateched
3892 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3893 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3894 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3895 continue;
3896 }
3897 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3898 {
3899 // If it's not mixed mode, we should only let BSS pass with the same encryption
3900 if (pInBss->WPA2.bMixMode == FALSE)
3901 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3902 continue;
3903
3904 // check group cipher
3905 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3906 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3907 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3908 continue;
3909
3910 // check pairwise cipher, skip if none matched
3911 // If profile set to AES, let it pass without question.
3912 // If profile set to TKIP, we must find one mateched
3913 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3914 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3915 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3916 continue;
3917 }
3918 }
3919 // Bss Type matched, SSID matched.
3920 // We will check wepstatus for qualification Bss
3921 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3922 {
3923 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3924 //
3925 // For the SESv2 case, we will not qualify WepStatus.
3926 //
3927 if (!pInBss->bSES)
3928 continue;
3929 }
3930
3931 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3932 // It definitely will fail. So, skip it.
3933 // CCX also require not even try to connect it!!
3934 if (SsidLen == 0)
3935 continue;
3936
3937 #ifdef DOT11_N_SUPPORT
3938 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3939 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3940 if ((pInBss->CentralChannel != pInBss->Channel) &&
3941 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3942 {
3943 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3944 {
3945 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3946 SetCommonHT(pAd);
3947 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3948 }
3949 else
3950 {
3951 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3952 {
3953 SetCommonHT(pAd);
3954 }
3955 }
3956 }
3957 #endif // DOT11_N_SUPPORT //
3958
3959 // copy matching BSS from InTab to OutTab
3960 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3961
3962 OutTab->BssNr++;
3963 }
3964 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3965 {
3966 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3967
3968
3969 #ifdef DOT11_N_SUPPORT
3970 // 2.4G/5G N only mode
3971 if ((pInBss->HtCapabilityLen == 0) &&
3972 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3973 {
3974 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3975 continue;
3976 }
3977 #endif // DOT11_N_SUPPORT //
3978
3979 // New for WPA2
3980 // Check the Authmode first
3981 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3982 {
3983 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3984 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3985 // None matched
3986 continue;
3987
3988 // Check cipher suite, AP must have more secured cipher than station setting
3989 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3990 {
3991 // If it's not mixed mode, we should only let BSS pass with the same encryption
3992 if (pInBss->WPA.bMixMode == FALSE)
3993 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3994 continue;
3995
3996 // check group cipher
3997 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3998 continue;
3999
4000 // check pairwise cipher, skip if none matched
4001 // If profile set to AES, let it pass without question.
4002 // If profile set to TKIP, we must find one mateched
4003 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4004 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4005 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4006 continue;
4007 }
4008 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4009 {
4010 // If it's not mixed mode, we should only let BSS pass with the same encryption
4011 if (pInBss->WPA2.bMixMode == FALSE)
4012 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4013 continue;
4014
4015 // check group cipher
4016 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4017 continue;
4018
4019 // check pairwise cipher, skip if none matched
4020 // If profile set to AES, let it pass without question.
4021 // If profile set to TKIP, we must find one mateched
4022 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4023 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4024 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4025 continue;
4026 }
4027 }
4028 // Bss Type matched, SSID matched.
4029 // We will check wepstatus for qualification Bss
4030 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4031 continue;
4032
4033 #ifdef DOT11_N_SUPPORT
4034 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4035 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4036 if ((pInBss->CentralChannel != pInBss->Channel) &&
4037 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4038 {
4039 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4040 {
4041 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4042 SetCommonHT(pAd);
4043 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4044 }
4045 }
4046 #endif // DOT11_N_SUPPORT //
4047
4048 // copy matching BSS from InTab to OutTab
4049 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4050
4051 OutTab->BssNr++;
4052 }
4053
4054 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4055 break;
4056 }
4057
4058 BssTableSortByRssi(OutTab);
4059 }
4060
4061
4062 // IRQL = DISPATCH_LEVEL
4063 VOID BssTableSortByRssi(
4064 IN OUT BSS_TABLE *OutTab)
4065 {
4066 INT i, j;
4067 BSS_ENTRY TmpBss;
4068
4069 for (i = 0; i < OutTab->BssNr - 1; i++)
4070 {
4071 for (j = i+1; j < OutTab->BssNr; j++)
4072 {
4073 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4074 {
4075 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4076 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4077 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4078 }
4079 }
4080 }
4081 }
4082 #endif // CONFIG_STA_SUPPORT //
4083
4084
4085 VOID BssCipherParse(
4086 IN OUT PBSS_ENTRY pBss)
4087 {
4088 PEID_STRUCT pEid;
4089 PUCHAR pTmp;
4090 PRSN_IE_HEADER_STRUCT pRsnHeader;
4091 PCIPHER_SUITE_STRUCT pCipher;
4092 PAKM_SUITE_STRUCT pAKM;
4093 USHORT Count;
4094 INT Length;
4095 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4096
4097 //
4098 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4099 //
4100 if (pBss->Privacy)
4101 {
4102 pBss->WepStatus = Ndis802_11WEPEnabled;
4103 }
4104 else
4105 {
4106 pBss->WepStatus = Ndis802_11WEPDisabled;
4107 }
4108 // Set default to disable & open authentication before parsing variable IE
4109 pBss->AuthMode = Ndis802_11AuthModeOpen;
4110 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4111
4112 // Init WPA setting
4113 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4114 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4115 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4116 pBss->WPA.RsnCapability = 0;
4117 pBss->WPA.bMixMode = FALSE;
4118
4119 // Init WPA2 setting
4120 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4121 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4122 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4123 pBss->WPA2.RsnCapability = 0;
4124 pBss->WPA2.bMixMode = FALSE;
4125
4126
4127 Length = (INT) pBss->VarIELen;
4128
4129 while (Length > 0)
4130 {
4131 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4132 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4133 pEid = (PEID_STRUCT) pTmp;
4134 switch (pEid->Eid)
4135 {
4136 case IE_WPA:
4137 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4138 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4139 {
4140 pTmp += 11;
4141 switch (*pTmp)
4142 {
4143 case 1:
4144 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4145 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4146 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4147 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4148 break;
4149 case 2:
4150 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4151 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4152 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4153 break;
4154 case 4:
4155 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4156 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4157 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4158 break;
4159 default:
4160 break;
4161 }
4162
4163 // if Cisco IE_WPA, break
4164 break;
4165 }
4166 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4167 {
4168 pBss->bSES = TRUE;
4169 break;
4170 }
4171 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4172 {
4173 // if unsupported vendor specific IE
4174 break;
4175 }
4176 // Skip OUI, version, and multicast suite
4177 // This part should be improved in the future when AP supported multiple cipher suite.
4178 // For now, it's OK since almost all APs have fixed cipher suite supported.
4179 // pTmp = (PUCHAR) pEid->Octet;
4180 pTmp += 11;
4181
4182 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4183 // Value Meaning
4184 // 0 None
4185 // 1 WEP-40
4186 // 2 Tkip
4187 // 3 WRAP
4188 // 4 AES
4189 // 5 WEP-104
4190 // Parse group cipher
4191 switch (*pTmp)
4192 {
4193 case 1:
4194 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4195 break;
4196 case 5:
4197 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4198 break;
4199 case 2:
4200 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4201 break;
4202 case 4:
4203 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4204 break;
4205 default:
4206 break;
4207 }
4208 // number of unicast suite
4209 pTmp += 1;
4210
4211 // skip all unicast cipher suites
4212 //Count = *(PUSHORT) pTmp;
4213 Count = (pTmp[1]<<8) + pTmp[0];
4214 pTmp += sizeof(USHORT);
4215
4216 // Parsing all unicast cipher suite
4217 while (Count > 0)
4218 {
4219 // Skip OUI
4220 pTmp += 3;
4221 TmpCipher = Ndis802_11WEPDisabled;
4222 switch (*pTmp)
4223 {
4224 case 1:
4225 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4226 TmpCipher = Ndis802_11Encryption1Enabled;
4227 break;
4228 case 2:
4229 TmpCipher = Ndis802_11Encryption2Enabled;
4230 break;
4231 case 4:
4232 TmpCipher = Ndis802_11Encryption3Enabled;
4233 break;
4234 default:
4235 break;
4236 }
4237 if (TmpCipher > pBss->WPA.PairCipher)
4238 {
4239 // Move the lower cipher suite to PairCipherAux
4240 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4241 pBss->WPA.PairCipher = TmpCipher;
4242 }
4243 else
4244 {
4245 pBss->WPA.PairCipherAux = TmpCipher;
4246 }
4247 pTmp++;
4248 Count--;
4249 }
4250
4251 // 4. get AKM suite counts
4252 //Count = *(PUSHORT) pTmp;
4253 Count = (pTmp[1]<<8) + pTmp[0];
4254 pTmp += sizeof(USHORT);
4255 pTmp += 3;
4256
4257 switch (*pTmp)
4258 {
4259 case 1:
4260 // Set AP support WPA mode
4261 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4262 pBss->AuthMode = Ndis802_11AuthModeWPA;
4263 else
4264 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4265 break;
4266 case 2:
4267 // Set AP support WPA mode
4268 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4269 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4270 else
4271 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4272 break;
4273 default:
4274 break;
4275 }
4276 pTmp += 1;
4277
4278 // Fixed for WPA-None
4279 if (pBss->BssType == BSS_ADHOC)
4280 {
4281 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4282 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4283 pBss->WepStatus = pBss->WPA.GroupCipher;
4284 // Patched bugs for old driver
4285 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4286 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4287 }
4288 else
4289 pBss->WepStatus = pBss->WPA.PairCipher;
4290
4291 // Check the Pair & Group, if different, turn on mixed mode flag
4292 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4293 pBss->WPA.bMixMode = TRUE;
4294
4295 break;
4296
4297 case IE_RSN:
4298 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4299
4300 // 0. Version must be 1
4301 if (le2cpu16(pRsnHeader->Version) != 1)
4302 break;
4303 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4304
4305 // 1. Check group cipher
4306 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4307 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4308 break;
4309
4310 // Parse group cipher
4311 switch (pCipher->Type)
4312 {
4313 case 1:
4314 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4315 break;
4316 case 5:
4317 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4318 break;
4319 case 2:
4320 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4321 break;
4322 case 4:
4323 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4324 break;
4325 default:
4326 break;
4327 }
4328 // set to correct offset for next parsing
4329 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4330
4331 // 2. Get pairwise cipher counts
4332 //Count = *(PUSHORT) pTmp;
4333 Count = (pTmp[1]<<8) + pTmp[0];
4334 pTmp += sizeof(USHORT);
4335
4336 // 3. Get pairwise cipher
4337 // Parsing all unicast cipher suite
4338 while (Count > 0)
4339 {
4340 // Skip OUI
4341 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4342 TmpCipher = Ndis802_11WEPDisabled;
4343 switch (pCipher->Type)
4344 {
4345 case 1:
4346 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4347 TmpCipher = Ndis802_11Encryption1Enabled;
4348 break;
4349 case 2:
4350 TmpCipher = Ndis802_11Encryption2Enabled;
4351 break;
4352 case 4:
4353 TmpCipher = Ndis802_11Encryption3Enabled;
4354 break;
4355 default:
4356 break;
4357 }
4358 if (TmpCipher > pBss->WPA2.PairCipher)
4359 {
4360 // Move the lower cipher suite to PairCipherAux
4361 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4362 pBss->WPA2.PairCipher = TmpCipher;
4363 }
4364 else
4365 {
4366 pBss->WPA2.PairCipherAux = TmpCipher;
4367 }
4368 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4369 Count--;
4370 }
4371
4372 // 4. get AKM suite counts
4373 //Count = *(PUSHORT) pTmp;
4374 Count = (pTmp[1]<<8) + pTmp[0];
4375 pTmp += sizeof(USHORT);
4376
4377 // 5. Get AKM ciphers
4378 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4379 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4380 break;
4381
4382 switch (pAKM->Type)
4383 {
4384 case 1:
4385 // Set AP support WPA mode
4386 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4387 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4388 else
4389 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4390 break;
4391 case 2:
4392 // Set AP support WPA mode
4393 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4394 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4395 else
4396 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4397 break;
4398 default:
4399 break;
4400 }
4401 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4402
4403 // Fixed for WPA-None
4404 if (pBss->BssType == BSS_ADHOC)
4405 {
4406 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4407 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4408 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4409 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4410 pBss->WepStatus = pBss->WPA.GroupCipher;
4411 // Patched bugs for old driver
4412 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4413 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4414 }
4415 pBss->WepStatus = pBss->WPA2.PairCipher;
4416
4417 // 6. Get RSN capability
4418 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4419 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4420 pTmp += sizeof(USHORT);
4421
4422 // Check the Pair & Group, if different, turn on mixed mode flag
4423 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4424 pBss->WPA2.bMixMode = TRUE;
4425
4426 break;
4427 default:
4428 break;
4429 }
4430 Length -= (pEid->Len + 2);
4431 }
4432 }
4433
4434 // ===========================================================================================
4435 // mac_table.c
4436 // ===========================================================================================
4437
4438 /*! \brief generates a random mac address value for IBSS BSSID
4439 * \param Addr the bssid location
4440 * \return none
4441 * \pre
4442 * \post
4443 */
4444 VOID MacAddrRandomBssid(
4445 IN PRTMP_ADAPTER pAd,
4446 OUT PUCHAR pAddr)
4447 {
4448 INT i;
4449
4450 for (i = 0; i < MAC_ADDR_LEN; i++)
4451 {
4452 pAddr[i] = RandomByte(pAd);
4453 }
4454
4455 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4456 }
4457
4458 /*! \brief init the management mac frame header
4459 * \param p_hdr mac header
4460 * \param subtype subtype of the frame
4461 * \param p_ds destination address, don't care if it is a broadcast address
4462 * \return none
4463 * \pre the station has the following information in the pAd->StaCfg
4464 * - bssid
4465 * - station address
4466 * \post
4467 * \note this function initializes the following field
4468
4469 IRQL = PASSIVE_LEVEL
4470 IRQL = DISPATCH_LEVEL
4471
4472 */
4473 VOID MgtMacHeaderInit(
4474 IN PRTMP_ADAPTER pAd,
4475 IN OUT PHEADER_802_11 pHdr80211,
4476 IN UCHAR SubType,
4477 IN UCHAR ToDs,
4478 IN PUCHAR pDA,
4479 IN PUCHAR pBssid)
4480 {
4481 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4482
4483 pHdr80211->FC.Type = BTYPE_MGMT;
4484 pHdr80211->FC.SubType = SubType;
4485 pHdr80211->FC.ToDs = ToDs;
4486 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4487 #ifdef CONFIG_STA_SUPPORT
4488 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4489 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4490 #endif // CONFIG_STA_SUPPORT //
4491 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4492 }
4493
4494 // ===========================================================================================
4495 // mem_mgmt.c
4496 // ===========================================================================================
4497
4498 /*!***************************************************************************
4499 * This routine build an outgoing frame, and fill all information specified
4500 * in argument list to the frame body. The actual frame size is the summation
4501 * of all arguments.
4502 * input params:
4503 * Buffer - pointer to a pre-allocated memory segment
4504 * args - a list of <int arg_size, arg> pairs.
4505 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4506 * function will FAIL!!!
4507 * return:
4508 * Size of the buffer
4509 * usage:
4510 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4511
4512 IRQL = PASSIVE_LEVEL
4513 IRQL = DISPATCH_LEVEL
4514
4515 ****************************************************************************/
4516 ULONG MakeOutgoingFrame(
4517 OUT CHAR *Buffer,
4518 OUT ULONG *FrameLen, ...)
4519 {
4520 CHAR *p;
4521 int leng;
4522 ULONG TotLeng;
4523 va_list Args;
4524
4525 // calculates the total length
4526 TotLeng = 0;
4527 va_start(Args, FrameLen);
4528 do
4529 {
4530 leng = va_arg(Args, int);
4531 if (leng == END_OF_ARGS)
4532 {
4533 break;
4534 }
4535 p = va_arg(Args, PVOID);
4536 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4537 TotLeng = TotLeng + leng;
4538 } while(TRUE);
4539
4540 va_end(Args); /* clean up */
4541 *FrameLen = TotLeng;
4542 return TotLeng;
4543 }
4544
4545 // ===========================================================================================
4546 // mlme_queue.c
4547 // ===========================================================================================
4548
4549 /*! \brief Initialize The MLME Queue, used by MLME Functions
4550 * \param *Queue The MLME Queue
4551 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4552 * \pre
4553 * \post
4554 * \note Because this is done only once (at the init stage), no need to be locked
4555
4556 IRQL = PASSIVE_LEVEL
4557
4558 */
4559 NDIS_STATUS MlmeQueueInit(
4560 IN MLME_QUEUE *Queue)
4561 {
4562 INT i;
4563
4564 NdisAllocateSpinLock(&Queue->Lock);
4565
4566 Queue->Num = 0;
4567 Queue->Head = 0;
4568 Queue->Tail = 0;
4569
4570 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4571 {
4572 Queue->Entry[i].Occupied = FALSE;
4573 Queue->Entry[i].MsgLen = 0;
4574 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4575 }
4576
4577 return NDIS_STATUS_SUCCESS;
4578 }
4579
4580 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4581 * \param *Queue The MLME Queue
4582 * \param Machine The State Machine Id
4583 * \param MsgType The Message Type
4584 * \param MsgLen The Message length
4585 * \param *Msg The message pointer
4586 * \return TRUE if enqueue is successful, FALSE if the queue is full
4587 * \pre
4588 * \post
4589 * \note The message has to be initialized
4590
4591 IRQL = PASSIVE_LEVEL
4592 IRQL = DISPATCH_LEVEL
4593
4594 */
4595 BOOLEAN MlmeEnqueue(
4596 IN PRTMP_ADAPTER pAd,
4597 IN ULONG Machine,
4598 IN ULONG MsgType,
4599 IN ULONG MsgLen,
4600 IN VOID *Msg)
4601 {
4602 INT Tail;
4603 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4604
4605 // Do nothing if the driver is starting halt state.
4606 // This might happen when timer already been fired before cancel timer with mlmehalt
4607 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4608 return FALSE;
4609
4610 // First check the size, it MUST not exceed the mlme queue size
4611 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4612 {
4613 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4614 return FALSE;
4615 }
4616
4617 if (MlmeQueueFull(Queue))
4618 {
4619 return FALSE;
4620 }
4621
4622 NdisAcquireSpinLock(&(Queue->Lock));
4623 Tail = Queue->Tail;
4624 Queue->Tail++;
4625 Queue->Num++;
4626 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4627 {
4628 Queue->Tail = 0;
4629 }
4630
4631 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4632 Queue->Entry[Tail].Occupied = TRUE;
4633 Queue->Entry[Tail].Machine = Machine;
4634 Queue->Entry[Tail].MsgType = MsgType;
4635 Queue->Entry[Tail].MsgLen = MsgLen;
4636
4637 if (Msg != NULL)
4638 {
4639 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4640 }
4641
4642 NdisReleaseSpinLock(&(Queue->Lock));
4643 return TRUE;
4644 }
4645
4646 /*! \brief This function is used when Recv gets a MLME message
4647 * \param *Queue The MLME Queue
4648 * \param TimeStampHigh The upper 32 bit of timestamp
4649 * \param TimeStampLow The lower 32 bit of timestamp
4650 * \param Rssi The receiving RSSI strength
4651 * \param MsgLen The length of the message
4652 * \param *Msg The message pointer
4653 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4654 * \pre
4655 * \post
4656
4657 IRQL = DISPATCH_LEVEL
4658
4659 */
4660 BOOLEAN MlmeEnqueueForRecv(
4661 IN PRTMP_ADAPTER pAd,
4662 IN ULONG Wcid,
4663 IN ULONG TimeStampHigh,
4664 IN ULONG TimeStampLow,
4665 IN UCHAR Rssi0,
4666 IN UCHAR Rssi1,
4667 IN UCHAR Rssi2,
4668 IN ULONG MsgLen,
4669 IN VOID *Msg,
4670 IN UCHAR Signal)
4671 {
4672 INT Tail, Machine;
4673 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4674 INT MsgType;
4675 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4676
4677 // Do nothing if the driver is starting halt state.
4678 // This might happen when timer already been fired before cancel timer with mlmehalt
4679 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4680 {
4681 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4682 return FALSE;
4683 }
4684
4685 // First check the size, it MUST not exceed the mlme queue size
4686 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4687 {
4688 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4689 return FALSE;
4690 }
4691
4692 if (MlmeQueueFull(Queue))
4693 {
4694 return FALSE;
4695 }
4696
4697 #ifdef CONFIG_STA_SUPPORT
4698 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4699 {
4700 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4701 {
4702 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4703 return FALSE;
4704 }
4705 }
4706 #endif // CONFIG_STA_SUPPORT //
4707
4708 // OK, we got all the informations, it is time to put things into queue
4709 NdisAcquireSpinLock(&(Queue->Lock));
4710 Tail = Queue->Tail;
4711 Queue->Tail++;
4712 Queue->Num++;
4713 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4714 {
4715 Queue->Tail = 0;
4716 }
4717 Queue->Entry[Tail].Occupied = TRUE;
4718 Queue->Entry[Tail].Machine = Machine;
4719 Queue->Entry[Tail].MsgType = MsgType;
4720 Queue->Entry[Tail].MsgLen = MsgLen;
4721 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4722 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4723 Queue->Entry[Tail].Rssi0 = Rssi0;
4724 Queue->Entry[Tail].Rssi1 = Rssi1;
4725 Queue->Entry[Tail].Rssi2 = Rssi2;
4726 Queue->Entry[Tail].Signal = Signal;
4727 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4728
4729 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4730
4731 if (Msg != NULL)
4732 {
4733 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4734 }
4735
4736 NdisReleaseSpinLock(&(Queue->Lock));
4737
4738 RT28XX_MLME_HANDLER(pAd);
4739
4740 return TRUE;
4741 }
4742
4743
4744 /*! \brief Dequeue a message from the MLME Queue
4745 * \param *Queue The MLME Queue
4746 * \param *Elem The message dequeued from MLME Queue
4747 * \return TRUE if the Elem contains something, FALSE otherwise
4748 * \pre
4749 * \post
4750
4751 IRQL = DISPATCH_LEVEL
4752
4753 */
4754 BOOLEAN MlmeDequeue(
4755 IN MLME_QUEUE *Queue,
4756 OUT MLME_QUEUE_ELEM **Elem)
4757 {
4758 NdisAcquireSpinLock(&(Queue->Lock));
4759 *Elem = &(Queue->Entry[Queue->Head]);
4760 Queue->Num--;
4761 Queue->Head++;
4762 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4763 {
4764 Queue->Head = 0;
4765 }
4766 NdisReleaseSpinLock(&(Queue->Lock));
4767 return TRUE;
4768 }
4769
4770 // IRQL = DISPATCH_LEVEL
4771 VOID MlmeRestartStateMachine(
4772 IN PRTMP_ADAPTER pAd)
4773 {
4774 MLME_QUEUE_ELEM *Elem = NULL;
4775 #ifdef CONFIG_STA_SUPPORT
4776 BOOLEAN Cancelled;
4777 #endif // CONFIG_STA_SUPPORT //
4778
4779 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4780
4781 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4782 if(pAd->Mlme.bRunning)
4783 {
4784 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4785 return;
4786 }
4787 else
4788 {
4789 pAd->Mlme.bRunning = TRUE;
4790 }
4791 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4792
4793 // Remove all Mlme queues elements
4794 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4795 {
4796 //From message type, determine which state machine I should drive
4797 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4798 {
4799 // free MLME element
4800 Elem->Occupied = FALSE;
4801 Elem->MsgLen = 0;
4802
4803 }
4804 else {
4805 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4806 }
4807 }
4808
4809 #ifdef CONFIG_STA_SUPPORT
4810 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4811 {
4812 // Cancel all timer events
4813 // Be careful to cancel new added timer
4814 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4815 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4816 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4817 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4818 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4819 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4820 }
4821 #endif // CONFIG_STA_SUPPORT //
4822
4823 // Change back to original channel in case of doing scan
4824 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4825 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4826
4827 // Resume MSDU which is turned off durning scan
4828 RTMPResumeMsduTransmission(pAd);
4829
4830 #ifdef CONFIG_STA_SUPPORT
4831 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4832 {
4833 // Set all state machines back IDLE
4834 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4835 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4836 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4837 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4838 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4839 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4840 }
4841 #endif // CONFIG_STA_SUPPORT //
4842
4843 // Remove running state
4844 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4845 pAd->Mlme.bRunning = FALSE;
4846 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4847 }
4848
4849 /*! \brief test if the MLME Queue is empty
4850 * \param *Queue The MLME Queue
4851 * \return TRUE if the Queue is empty, FALSE otherwise
4852 * \pre
4853 * \post
4854
4855 IRQL = DISPATCH_LEVEL
4856
4857 */
4858 BOOLEAN MlmeQueueEmpty(
4859 IN MLME_QUEUE *Queue)
4860 {
4861 BOOLEAN Ans;
4862
4863 NdisAcquireSpinLock(&(Queue->Lock));
4864 Ans = (Queue->Num == 0);
4865 NdisReleaseSpinLock(&(Queue->Lock));
4866
4867 return Ans;
4868 }
4869
4870 /*! \brief test if the MLME Queue is full
4871 * \param *Queue The MLME Queue
4872 * \return TRUE if the Queue is empty, FALSE otherwise
4873 * \pre
4874 * \post
4875
4876 IRQL = PASSIVE_LEVEL
4877 IRQL = DISPATCH_LEVEL
4878
4879 */
4880 BOOLEAN MlmeQueueFull(
4881 IN MLME_QUEUE *Queue)
4882 {
4883 BOOLEAN Ans;
4884
4885 NdisAcquireSpinLock(&(Queue->Lock));
4886 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4887 NdisReleaseSpinLock(&(Queue->Lock));
4888
4889 return Ans;
4890 }
4891
4892 /*! \brief The destructor of MLME Queue
4893 * \param
4894 * \return
4895 * \pre
4896 * \post
4897 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4898
4899 IRQL = PASSIVE_LEVEL
4900
4901 */
4902 VOID MlmeQueueDestroy(
4903 IN MLME_QUEUE *pQueue)
4904 {
4905 NdisAcquireSpinLock(&(pQueue->Lock));
4906 pQueue->Num = 0;
4907 pQueue->Head = 0;
4908 pQueue->Tail = 0;
4909 NdisReleaseSpinLock(&(pQueue->Lock));
4910 NdisFreeSpinLock(&(pQueue->Lock));
4911 }
4912
4913 /*! \brief To substitute the message type if the message is coming from external
4914 * \param pFrame The frame received
4915 * \param *Machine The state machine
4916 * \param *MsgType the message type for the state machine
4917 * \return TRUE if the substitution is successful, FALSE otherwise
4918 * \pre
4919 * \post
4920
4921 IRQL = DISPATCH_LEVEL
4922
4923 */
4924 #ifdef CONFIG_STA_SUPPORT
4925 BOOLEAN MsgTypeSubst(
4926 IN PRTMP_ADAPTER pAd,
4927 IN PFRAME_802_11 pFrame,
4928 OUT INT *Machine,
4929 OUT INT *MsgType)
4930 {
4931 USHORT Seq;
4932 UCHAR EAPType;
4933 PUCHAR pData;
4934
4935 // Pointer to start of data frames including SNAP header
4936 pData = (PUCHAR) pFrame + LENGTH_802_11;
4937
4938 // The only data type will pass to this function is EAPOL frame
4939 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4940 {
4941 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4942 {
4943 // Cisco Aironet SNAP header
4944 *Machine = AIRONET_STATE_MACHINE;
4945 *MsgType = MT2_AIRONET_MSG;
4946 return (TRUE);
4947 }
4948 {
4949 *Machine = WPA_PSK_STATE_MACHINE;
4950 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4951 return(WpaMsgTypeSubst(EAPType, MsgType));
4952 }
4953 }
4954
4955 switch (pFrame->Hdr.FC.SubType)
4956 {
4957 case SUBTYPE_ASSOC_REQ:
4958 *Machine = ASSOC_STATE_MACHINE;
4959 *MsgType = MT2_PEER_ASSOC_REQ;
4960 break;
4961 case SUBTYPE_ASSOC_RSP:
4962 *Machine = ASSOC_STATE_MACHINE;
4963 *MsgType = MT2_PEER_ASSOC_RSP;
4964 break;
4965 case SUBTYPE_REASSOC_REQ:
4966 *Machine = ASSOC_STATE_MACHINE;
4967 *MsgType = MT2_PEER_REASSOC_REQ;
4968 break;
4969 case SUBTYPE_REASSOC_RSP:
4970 *Machine = ASSOC_STATE_MACHINE;
4971 *MsgType = MT2_PEER_REASSOC_RSP;
4972 break;
4973 case SUBTYPE_PROBE_REQ:
4974 *Machine = SYNC_STATE_MACHINE;
4975 *MsgType = MT2_PEER_PROBE_REQ;
4976 break;
4977 case SUBTYPE_PROBE_RSP:
4978 *Machine = SYNC_STATE_MACHINE;
4979 *MsgType = MT2_PEER_PROBE_RSP;
4980 break;
4981 case SUBTYPE_BEACON:
4982 *Machine = SYNC_STATE_MACHINE;
4983 *MsgType = MT2_PEER_BEACON;
4984 break;
4985 case SUBTYPE_ATIM:
4986 *Machine = SYNC_STATE_MACHINE;
4987 *MsgType = MT2_PEER_ATIM;
4988 break;
4989 case SUBTYPE_DISASSOC:
4990 *Machine = ASSOC_STATE_MACHINE;
4991 *MsgType = MT2_PEER_DISASSOC_REQ;
4992 break;
4993 case SUBTYPE_AUTH:
4994 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4995 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4996 if (Seq == 1 || Seq == 3)
4997 {
4998 *Machine = AUTH_RSP_STATE_MACHINE;
4999 *MsgType = MT2_PEER_AUTH_ODD;
5000 }
5001 else if (Seq == 2 || Seq == 4)
5002 {
5003 *Machine = AUTH_STATE_MACHINE;
5004 *MsgType = MT2_PEER_AUTH_EVEN;
5005 }
5006 else
5007 {
5008 return FALSE;
5009 }
5010 break;
5011 case SUBTYPE_DEAUTH:
5012 *Machine = AUTH_RSP_STATE_MACHINE;
5013 *MsgType = MT2_PEER_DEAUTH;
5014 break;
5015 case SUBTYPE_ACTION:
5016 *Machine = ACTION_STATE_MACHINE;
5017 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5018 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5019 {
5020 *MsgType = MT2_ACT_INVALID;
5021 }
5022 else
5023 {
5024 *MsgType = (pFrame->Octet[0]&0x7F);
5025 }
5026 break;
5027 default:
5028 return FALSE;
5029 break;
5030 }
5031
5032 return TRUE;
5033 }
5034 #endif // CONFIG_STA_SUPPORT //
5035
5036 // ===========================================================================================
5037 // state_machine.c
5038 // ===========================================================================================
5039
5040 /*! \brief Initialize the state machine.
5041 * \param *S pointer to the state machine
5042 * \param Trans State machine transition function
5043 * \param StNr number of states
5044 * \param MsgNr number of messages
5045 * \param DefFunc default function, when there is invalid state/message combination
5046 * \param InitState initial state of the state machine
5047 * \param Base StateMachine base, internal use only
5048 * \pre p_sm should be a legal pointer
5049 * \post
5050
5051 IRQL = PASSIVE_LEVEL
5052
5053 */
5054 VOID StateMachineInit(
5055 IN STATE_MACHINE *S,
5056 IN STATE_MACHINE_FUNC Trans[],
5057 IN ULONG StNr,
5058 IN ULONG MsgNr,
5059 IN STATE_MACHINE_FUNC DefFunc,
5060 IN ULONG InitState,
5061 IN ULONG Base)
5062 {
5063 ULONG i, j;
5064
5065 // set number of states and messages
5066 S->NrState = StNr;
5067 S->NrMsg = MsgNr;
5068 S->Base = Base;
5069
5070 S->TransFunc = Trans;
5071
5072 // init all state transition to default function
5073 for (i = 0; i < StNr; i++)
5074 {
5075 for (j = 0; j < MsgNr; j++)
5076 {
5077 S->TransFunc[i * MsgNr + j] = DefFunc;
5078 }
5079 }
5080
5081 // set the starting state
5082 S->CurrState = InitState;
5083 }
5084
5085 /*! \brief This function fills in the function pointer into the cell in the state machine
5086 * \param *S pointer to the state machine
5087 * \param St state
5088 * \param Msg incoming message
5089 * \param f the function to be executed when (state, message) combination occurs at the state machine
5090 * \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
5091 * \post
5092
5093 IRQL = PASSIVE_LEVEL
5094
5095 */
5096 VOID StateMachineSetAction(
5097 IN STATE_MACHINE *S,
5098 IN ULONG St,
5099 IN ULONG Msg,
5100 IN STATE_MACHINE_FUNC Func)
5101 {
5102 ULONG MsgIdx;
5103
5104 MsgIdx = Msg - S->Base;
5105
5106 if (St < S->NrState && MsgIdx < S->NrMsg)
5107 {
5108 // boundary checking before setting the action
5109 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5110 }
5111 }
5112
5113 /*! \brief This function does the state transition
5114 * \param *Adapter the NIC adapter pointer
5115 * \param *S the state machine
5116 * \param *Elem the message to be executed
5117 * \return None
5118
5119 IRQL = DISPATCH_LEVEL
5120
5121 */
5122 VOID StateMachinePerformAction(
5123 IN PRTMP_ADAPTER pAd,
5124 IN STATE_MACHINE *S,
5125 IN MLME_QUEUE_ELEM *Elem)
5126 {
5127 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5128 }
5129
5130 /*
5131 ==========================================================================
5132 Description:
5133 The drop function, when machine executes this, the message is simply
5134 ignored. This function does nothing, the message is freed in
5135 StateMachinePerformAction()
5136 ==========================================================================
5137 */
5138 VOID Drop(
5139 IN PRTMP_ADAPTER pAd,
5140 IN MLME_QUEUE_ELEM *Elem)
5141 {
5142 }
5143
5144 // ===========================================================================================
5145 // lfsr.c
5146 // ===========================================================================================
5147
5148 /*
5149 ==========================================================================
5150 Description:
5151
5152 IRQL = PASSIVE_LEVEL
5153
5154 ==========================================================================
5155 */
5156 VOID LfsrInit(
5157 IN PRTMP_ADAPTER pAd,
5158 IN ULONG Seed)
5159 {
5160 if (Seed == 0)
5161 pAd->Mlme.ShiftReg = 1;
5162 else
5163 pAd->Mlme.ShiftReg = Seed;
5164 }
5165
5166 /*
5167 ==========================================================================
5168 Description:
5169 ==========================================================================
5170 */
5171 UCHAR RandomByte(
5172 IN PRTMP_ADAPTER pAd)
5173 {
5174 ULONG i;
5175 UCHAR R, Result;
5176
5177 R = 0;
5178
5179 if (pAd->Mlme.ShiftReg == 0)
5180 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5181
5182 for (i = 0; i < 8; i++)
5183 {
5184 if (pAd->Mlme.ShiftReg & 0x00000001)
5185 {
5186 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5187 Result = 1;
5188 }
5189 else
5190 {
5191 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5192 Result = 0;
5193 }
5194 R = (R << 1) | Result;
5195 }
5196
5197 return R;
5198 }
5199
5200 VOID AsicUpdateAutoFallBackTable(
5201 IN PRTMP_ADAPTER pAd,
5202 IN PUCHAR pRateTable)
5203 {
5204 UCHAR i;
5205 HT_FBK_CFG0_STRUC HtCfg0;
5206 HT_FBK_CFG1_STRUC HtCfg1;
5207 LG_FBK_CFG0_STRUC LgCfg0;
5208 LG_FBK_CFG1_STRUC LgCfg1;
5209 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5210
5211 // set to initial value
5212 HtCfg0.word = 0x65432100;
5213 HtCfg1.word = 0xedcba988;
5214 LgCfg0.word = 0xedcba988;
5215 LgCfg1.word = 0x00002100;
5216
5217 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5218 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5219 {
5220 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5221 switch (pCurrTxRate->Mode)
5222 {
5223 case 0: //CCK
5224 break;
5225 case 1: //OFDM
5226 {
5227 switch(pCurrTxRate->CurrMCS)
5228 {
5229 case 0:
5230 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5231 break;
5232 case 1:
5233 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5234 break;
5235 case 2:
5236 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5237 break;
5238 case 3:
5239 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5240 break;
5241 case 4:
5242 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5243 break;
5244 case 5:
5245 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5246 break;
5247 case 6:
5248 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5249 break;
5250 case 7:
5251 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5252 break;
5253 }
5254 }
5255 break;
5256 #ifdef DOT11_N_SUPPORT
5257 case 2: //HT-MIX
5258 case 3: //HT-GF
5259 {
5260 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5261 {
5262 switch(pCurrTxRate->CurrMCS)
5263 {
5264 case 0:
5265 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5266 break;
5267 case 1:
5268 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5269 break;
5270 case 2:
5271 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5272 break;
5273 case 3:
5274 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5275 break;
5276 case 4:
5277 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5278 break;
5279 case 5:
5280 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5281 break;
5282 case 6:
5283 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5284 break;
5285 case 7:
5286 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5287 break;
5288 case 8:
5289 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5290 break;
5291 case 9:
5292 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5293 break;
5294 case 10:
5295 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5296 break;
5297 case 11:
5298 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5299 break;
5300 case 12:
5301 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5302 break;
5303 case 13:
5304 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5305 break;
5306 case 14:
5307 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5308 break;
5309 case 15:
5310 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5311 break;
5312 default:
5313 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5314 }
5315 }
5316 }
5317 break;
5318 #endif // DOT11_N_SUPPORT //
5319 }
5320
5321 pNextTxRate = pCurrTxRate;
5322 }
5323
5324 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5325 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5326 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5327 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5328 }
5329
5330 /*
5331 ========================================================================
5332
5333 Routine Description:
5334 Set MAC register value according operation mode.
5335 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5336 If MM or GF mask is not set, those passing argument doesn't not take effect.
5337
5338 Operation mode meaning:
5339 = 0 : Pure HT, no preotection.
5340 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5341 = 0x10: No Transmission in 40M is protected.
5342 = 0x11: Transmission in both 40M and 20M shall be protected
5343 if (bNonGFExist)
5344 we should choose not to use GF. But still set correct ASIC registers.
5345 ========================================================================
5346 */
5347 VOID AsicUpdateProtect(
5348 IN PRTMP_ADAPTER pAd,
5349 IN USHORT OperationMode,
5350 IN UCHAR SetMask,
5351 IN BOOLEAN bDisableBGProtect,
5352 IN BOOLEAN bNonGFExist)
5353 {
5354 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5355 UINT32 Protect[6];
5356 USHORT offset;
5357 UCHAR i;
5358 UINT32 MacReg = 0;
5359
5360 #ifdef DOT11_N_SUPPORT
5361 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5362 {
5363 return;
5364 }
5365
5366 if (pAd->BATable.numAsOriginator)
5367 {
5368 //
5369 // enable the RTS/CTS to avoid channel collision
5370 //
5371 SetMask = ALLN_SETPROTECT;
5372 OperationMode = 8;
5373 }
5374 #endif // DOT11_N_SUPPORT //
5375
5376 // Config ASIC RTS threshold register
5377 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5378 MacReg &= 0xFF0000FF;
5379 #if 0
5380 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5381 #else
5382 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5383 if ((
5384 #ifdef DOT11_N_SUPPORT
5385 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5386 #endif // DOT11_N_SUPPORT //
5387 (pAd->CommonCfg.bAggregationCapable == TRUE))
5388 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5389 {
5390 MacReg |= (0x1000 << 8);
5391 }
5392 else
5393 {
5394 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5395 }
5396 #endif
5397
5398 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5399
5400 // Initial common protection settings
5401 RTMPZeroMemory(Protect, sizeof(Protect));
5402 ProtCfg4.word = 0;
5403 ProtCfg.word = 0;
5404 ProtCfg.field.TxopAllowGF40 = 1;
5405 ProtCfg.field.TxopAllowGF20 = 1;
5406 ProtCfg.field.TxopAllowMM40 = 1;
5407 ProtCfg.field.TxopAllowMM20 = 1;
5408 ProtCfg.field.TxopAllowOfdm = 1;
5409 ProtCfg.field.TxopAllowCck = 1;
5410 ProtCfg.field.RTSThEn = 1;
5411 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5412
5413 // update PHY mode and rate
5414 if (pAd->CommonCfg.Channel > 14)
5415 ProtCfg.field.ProtectRate = 0x4000;
5416 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5417
5418 // Handle legacy(B/G) protection
5419 if (bDisableBGProtect)
5420 {
5421 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5422 ProtCfg.field.ProtectCtrl = 0;
5423 Protect[0] = ProtCfg.word;
5424 Protect[1] = ProtCfg.word;
5425 }
5426 else
5427 {
5428 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5429 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5430 Protect[0] = ProtCfg.word;
5431 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5432 Protect[1] = ProtCfg.word;
5433 }
5434
5435 #ifdef DOT11_N_SUPPORT
5436 // Decide HT frame protection.
5437 if ((SetMask & ALLN_SETPROTECT) != 0)
5438 {
5439 switch(OperationMode)
5440 {
5441 case 0x0:
5442 // NO PROTECT
5443 // 1.All STAs in the BSS are 20/40 MHz HT
5444 // 2. in ai 20/40MHz BSS
5445 // 3. all STAs are 20MHz in a 20MHz BSS
5446 // Pure HT. no protection.
5447
5448 // MM20_PROT_CFG
5449 // Reserved (31:27)
5450 // PROT_TXOP(25:20) -- 010111
5451 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5452 // PROT_CTRL(17:16) -- 00 (None)
5453 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5454 Protect[2] = 0x01744004;
5455
5456 // MM40_PROT_CFG
5457 // Reserved (31:27)
5458 // PROT_TXOP(25:20) -- 111111
5459 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5460 // PROT_CTRL(17:16) -- 00 (None)
5461 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5462 Protect[3] = 0x03f44084;
5463
5464 // CF20_PROT_CFG
5465 // Reserved (31:27)
5466 // PROT_TXOP(25:20) -- 010111
5467 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5468 // PROT_CTRL(17:16) -- 00 (None)
5469 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5470 Protect[4] = 0x01744004;
5471
5472 // CF40_PROT_CFG
5473 // Reserved (31:27)
5474 // PROT_TXOP(25:20) -- 111111
5475 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5476 // PROT_CTRL(17:16) -- 00 (None)
5477 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5478 Protect[5] = 0x03f44084;
5479
5480 if (bNonGFExist)
5481 {
5482 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5483 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5484 Protect[4] = 0x01754004;
5485 Protect[5] = 0x03f54084;
5486 }
5487 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5488 break;
5489
5490 case 1:
5491 // This is "HT non-member protection mode."
5492 // If there may be non-HT STAs my BSS
5493 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5494 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5495 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5496 {
5497 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5498 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5499 }
5500 //Assign Protection method for 20&40 MHz packets
5501 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5502 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5503 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5504 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5505 Protect[2] = ProtCfg.word;
5506 Protect[3] = ProtCfg4.word;
5507 Protect[4] = ProtCfg.word;
5508 Protect[5] = ProtCfg4.word;
5509 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5510 break;
5511
5512 case 2:
5513 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5514 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5515 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5516
5517 //Assign Protection method for 40MHz packets
5518 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5519 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5520 Protect[2] = ProtCfg.word;
5521 Protect[3] = ProtCfg4.word;
5522 if (bNonGFExist)
5523 {
5524 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5525 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5526 }
5527 Protect[4] = ProtCfg.word;
5528 Protect[5] = ProtCfg4.word;
5529
5530 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5531 break;
5532
5533 case 3:
5534 // HT mixed mode. PROTECT ALL!
5535 // Assign Rate
5536 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5537 ProtCfg4.word = 0x03f44084;
5538 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5539 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5540 {
5541 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5542 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5543 }
5544 //Assign Protection method for 20&40 MHz packets
5545 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5546 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5547 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5548 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5549 Protect[2] = ProtCfg.word;
5550 Protect[3] = ProtCfg4.word;
5551 Protect[4] = ProtCfg.word;
5552 Protect[5] = ProtCfg4.word;
5553 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5554 break;
5555
5556 case 8:
5557 // Special on for Atheros problem n chip.
5558 Protect[2] = 0x01754004;
5559 Protect[3] = 0x03f54084;
5560 Protect[4] = 0x01754004;
5561 Protect[5] = 0x03f54084;
5562 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5563 break;
5564 }
5565 }
5566 #endif // DOT11_N_SUPPORT //
5567
5568 offset = CCK_PROT_CFG;
5569 for (i = 0;i < 6;i++)
5570 {
5571 if ((SetMask & (1<< i)))
5572 {
5573 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5574 }
5575 }
5576 }
5577
5578 /*
5579 ==========================================================================
5580 Description:
5581
5582 IRQL = PASSIVE_LEVEL
5583 IRQL = DISPATCH_LEVEL
5584
5585 ==========================================================================
5586 */
5587 VOID AsicSwitchChannel(
5588 IN PRTMP_ADAPTER pAd,
5589 IN UCHAR Channel,
5590 IN BOOLEAN bScan)
5591 {
5592 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5593 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5594 UCHAR index;
5595 UINT32 Value = 0; //BbpReg, Value;
5596 RTMP_RF_REGS *RFRegTable;
5597
5598 // Search Tx power value
5599 for (index = 0; index < pAd->ChannelListNum; index++)
5600 {
5601 if (Channel == pAd->ChannelList[index].Channel)
5602 {
5603 TxPwer = pAd->ChannelList[index].Power;
5604 TxPwer2 = pAd->ChannelList[index].Power2;
5605 break;
5606 }
5607 }
5608
5609 if (index == MAX_NUM_OF_CHANNELS)
5610 {
5611 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5612 }
5613
5614 {
5615 RFRegTable = RF2850RegTable;
5616
5617 switch (pAd->RfIcType)
5618 {
5619 case RFIC_2820:
5620 case RFIC_2850:
5621 case RFIC_2720:
5622 case RFIC_2750:
5623
5624 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5625 {
5626 if (Channel == RFRegTable[index].Channel)
5627 {
5628 R2 = RFRegTable[index].R2;
5629 if (pAd->Antenna.field.TxPath == 1)
5630 {
5631 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5632 }
5633
5634 if (pAd->Antenna.field.RxPath == 2)
5635 {
5636 R2 |= 0x40; // write 1 to off Rxpath.
5637 }
5638 else if (pAd->Antenna.field.RxPath == 1)
5639 {
5640 R2 |= 0x20040; // write 1 to off RxPath
5641 }
5642
5643 if (Channel > 14)
5644 {
5645 // initialize R3, R4
5646 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5647 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5648
5649 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5650 // R3
5651 if ((TxPwer >= -7) && (TxPwer < 0))
5652 {
5653 TxPwer = (7+TxPwer);
5654 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5655 R3 |= (TxPwer << 10);
5656 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5657 }
5658 else
5659 {
5660 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5661 R3 |= (TxPwer << 10) | (1 << 9);
5662 }
5663
5664 // R4
5665 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5666 {
5667 TxPwer2 = (7+TxPwer2);
5668 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5669 R4 |= (TxPwer2 << 7);
5670 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5671 }
5672 else
5673 {
5674 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5675 R4 |= (TxPwer2 << 7) | (1 << 6);
5676 }
5677 }
5678 else
5679 {
5680 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5681 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5682 }
5683
5684 // Based on BBP current mode before changing RF channel.
5685 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5686 {
5687 R4 |=0x200000;
5688 }
5689
5690 // Update variables
5691 pAd->LatchRfRegs.Channel = Channel;
5692 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5693 pAd->LatchRfRegs.R2 = R2;
5694 pAd->LatchRfRegs.R3 = R3;
5695 pAd->LatchRfRegs.R4 = R4;
5696
5697 // Set RF value 1's set R3[bit2] = [0]
5698 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5699 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5700 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5701 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5702
5703 RTMPusecDelay(200);
5704
5705 // Set RF value 2's set R3[bit2] = [1]
5706 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5707 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5708 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5709 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5710
5711 RTMPusecDelay(200);
5712
5713 // Set RF value 3's set R3[bit2] = [0]
5714 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5715 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5716 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5717 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5718
5719 break;
5720 }
5721 }
5722 break;
5723
5724 default:
5725 break;
5726 }
5727 }
5728
5729 // Change BBP setting during siwtch from a->g, g->a
5730 if (Channel <= 14)
5731 {
5732 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5733
5734 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5735 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5736 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5737 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.
5738 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5739
5740 // Rx High power VGA offset for LNA select
5741 if (pAd->NicConfig2.field.ExternalLNAForG)
5742 {
5743 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5744 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5745 }
5746 else
5747 {
5748 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5749 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5750 }
5751
5752 // 5G band selection PIN, bit1 and bit2 are complement
5753 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5754 Value &= (~0x6);
5755 Value |= (0x04);
5756 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5757
5758 // Turn off unused PA or LNA when only 1T or 1R
5759 if (pAd->Antenna.field.TxPath == 1)
5760 {
5761 TxPinCfg &= 0xFFFFFFF3;
5762 }
5763 if (pAd->Antenna.field.RxPath == 1)
5764 {
5765 TxPinCfg &= 0xFFFFF3FF;
5766 }
5767
5768 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5769 }
5770 else
5771 {
5772 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5773
5774 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5775 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5776 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5777 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.
5778 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5779
5780 // Rx High power VGA offset for LNA select
5781 if (pAd->NicConfig2.field.ExternalLNAForA)
5782 {
5783 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5784 }
5785 else
5786 {
5787 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5788 }
5789
5790 // 5G band selection PIN, bit1 and bit2 are complement
5791 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5792 Value &= (~0x6);
5793 Value |= (0x02);
5794 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5795
5796 // Turn off unused PA or LNA when only 1T or 1R
5797 if (pAd->Antenna.field.TxPath == 1)
5798 {
5799 TxPinCfg &= 0xFFFFFFF3;
5800 }
5801 if (pAd->Antenna.field.RxPath == 1)
5802 {
5803 TxPinCfg &= 0xFFFFF3FF;
5804 }
5805
5806 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5807 }
5808
5809 // R66 should be set according to Channel and use 20MHz when scanning
5810 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5811 if (bScan)
5812 RTMPSetAGCInitValue(pAd, BW_20);
5813 else
5814 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5815
5816 //
5817 // On 11A, We should delay and wait RF/BBP to be stable
5818 // and the appropriate time should be 1000 micro seconds
5819 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5820 //
5821 RTMPusecDelay(1000);
5822
5823 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",
5824 Channel,
5825 pAd->RfIcType,
5826 (R3 & 0x00003e00) >> 9,
5827 (R4 & 0x000007c0) >> 6,
5828 pAd->Antenna.field.TxPath,
5829 pAd->LatchRfRegs.R1,
5830 pAd->LatchRfRegs.R2,
5831 pAd->LatchRfRegs.R3,
5832 pAd->LatchRfRegs.R4));
5833 }
5834
5835 /*
5836 ==========================================================================
5837 Description:
5838 This function is required for 2421 only, and should not be used during
5839 site survey. It's only required after NIC decided to stay at a channel
5840 for a longer period.
5841 When this function is called, it's always after AsicSwitchChannel().
5842
5843 IRQL = PASSIVE_LEVEL
5844 IRQL = DISPATCH_LEVEL
5845
5846 ==========================================================================
5847 */
5848 VOID AsicLockChannel(
5849 IN PRTMP_ADAPTER pAd,
5850 IN UCHAR Channel)
5851 {
5852 }
5853
5854 /*
5855 ==========================================================================
5856 Description:
5857
5858 IRQL = PASSIVE_LEVEL
5859 IRQL = DISPATCH_LEVEL
5860
5861 ==========================================================================
5862 */
5863 VOID AsicAntennaSelect(
5864 IN PRTMP_ADAPTER pAd,
5865 IN UCHAR Channel)
5866 {
5867 }
5868
5869 /*
5870 ========================================================================
5871
5872 Routine Description:
5873 Antenna miscellaneous setting.
5874
5875 Arguments:
5876 pAd Pointer to our adapter
5877 BandState Indicate current Band State.
5878
5879 Return Value:
5880 None
5881
5882 IRQL <= DISPATCH_LEVEL
5883
5884 Note:
5885 1.) Frame End type control
5886 only valid for G only (RF_2527 & RF_2529)
5887 0: means DPDT, set BBP R4 bit 5 to 1
5888 1: means SPDT, set BBP R4 bit 5 to 0
5889
5890
5891 ========================================================================
5892 */
5893 VOID AsicAntennaSetting(
5894 IN PRTMP_ADAPTER pAd,
5895 IN ABGBAND_STATE BandState)
5896 {
5897 }
5898
5899 VOID AsicRfTuningExec(
5900 IN PVOID SystemSpecific1,
5901 IN PVOID FunctionContext,
5902 IN PVOID SystemSpecific2,
5903 IN PVOID SystemSpecific3)
5904 {
5905 }
5906
5907 /*
5908 ==========================================================================
5909 Description:
5910 Gives CCK TX rate 2 more dB TX power.
5911 This routine works only in LINK UP in INFRASTRUCTURE mode.
5912
5913 calculate desired Tx power in RF R3.Tx0~5, should consider -
5914 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
5915 1. TxPowerPercentage
5916 2. auto calibration based on TSSI feedback
5917 3. extra 2 db for CCK
5918 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
5919
5920 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
5921 it should be called AFTER MlmeDynamicTxRatSwitching()
5922 ==========================================================================
5923 */
5924 VOID AsicAdjustTxPower(
5925 IN PRTMP_ADAPTER pAd)
5926 {
5927 INT i, j;
5928 CHAR DeltaPwr = 0;
5929 BOOLEAN bAutoTxAgc = FALSE;
5930 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
5931 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
5932 PCHAR pTxAgcCompensate;
5933 ULONG TxPwr[5];
5934 CHAR Value;
5935
5936 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5937 || (pAd->bPCIclkOff == TRUE)
5938 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
5939 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
5940 return;
5941
5942 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
5943 {
5944 if (pAd->CommonCfg.CentralChannel > 14)
5945 {
5946 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
5947 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
5948 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
5949 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
5950 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
5951 }
5952 else
5953 {
5954 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
5955 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
5956 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
5957 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
5958 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
5959 }
5960 }
5961 else
5962 {
5963 if (pAd->CommonCfg.Channel > 14)
5964 {
5965 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
5966 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
5967 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
5968 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
5969 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
5970 }
5971 else
5972 {
5973 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
5974 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
5975 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
5976 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
5977 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
5978 }
5979 }
5980
5981 // TX power compensation for temperature variation based on TSSI. try every 4 second
5982 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
5983 {
5984 if (pAd->CommonCfg.Channel <= 14)
5985 {
5986 /* bg channel */
5987 bAutoTxAgc = pAd->bAutoTxAgcG;
5988 TssiRef = pAd->TssiRefG;
5989 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
5990 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
5991 TxAgcStep = pAd->TxAgcStepG;
5992 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5993 }
5994 else
5995 {
5996 /* a channel */
5997 bAutoTxAgc = pAd->bAutoTxAgcA;
5998 TssiRef = pAd->TssiRefA;
5999 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6000 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6001 TxAgcStep = pAd->TxAgcStepA;
6002 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6003 }
6004
6005 if (bAutoTxAgc)
6006 {
6007 /* BbpR1 is unsigned char */
6008 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6009
6010 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6011 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6012 /* step value is defined in pAd->TxAgcStepG for tx power value */
6013
6014 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6015 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6016 above value are examined in mass factory production */
6017 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6018
6019 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6020 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6021 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6022
6023 if (BbpR49 > pTssiMinusBoundary[1])
6024 {
6025 // Reading is larger than the reference value
6026 // check for how large we need to decrease the Tx power
6027 for (idx = 1; idx < 5; idx++)
6028 {
6029 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6030 break;
6031 }
6032 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6033 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6034
6035 DeltaPwr += (*pTxAgcCompensate);
6036 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6037 BbpR49, TssiRef, TxAgcStep, idx-1));
6038 }
6039 else if (BbpR49 < pTssiPlusBoundary[1])
6040 {
6041 // Reading is smaller than the reference value
6042 // check for how large we need to increase the Tx power
6043 for (idx = 1; idx < 5; idx++)
6044 {
6045 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6046 break;
6047 }
6048 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6049 *pTxAgcCompensate = TxAgcStep * (idx-1);
6050 DeltaPwr += (*pTxAgcCompensate);
6051 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6052 BbpR49, TssiRef, TxAgcStep, idx-1));
6053 }
6054 else
6055 {
6056 *pTxAgcCompensate = 0;
6057 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6058 BbpR49, TssiRef, TxAgcStep, 0));
6059 }
6060 }
6061 }
6062 else
6063 {
6064 if (pAd->CommonCfg.Channel <= 14)
6065 {
6066 bAutoTxAgc = pAd->bAutoTxAgcG;
6067 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6068 }
6069 else
6070 {
6071 bAutoTxAgc = pAd->bAutoTxAgcA;
6072 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6073 }
6074
6075 if (bAutoTxAgc)
6076 DeltaPwr += (*pTxAgcCompensate);
6077 }
6078
6079 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6080 BbpR1 &= 0xFC;
6081
6082 /* calculate delta power based on the percentage specified from UI */
6083 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6084 // We lower TX power here according to the percentage specified from UI
6085 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6086 ;
6087 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6088 ;
6089 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6090 {
6091 DeltaPwr -= 1;
6092 }
6093 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6094 {
6095 DeltaPwr -= 3;
6096 }
6097 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6098 {
6099 BbpR1 |= 0x01;
6100 }
6101 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6102 {
6103 BbpR1 |= 0x01;
6104 DeltaPwr -= 3;
6105 }
6106 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6107 {
6108 BbpR1 |= 0x02;
6109 }
6110
6111 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6112
6113 /* reset different new tx power for different TX rate */
6114 for(i=0; i<5; i++)
6115 {
6116 if (TxPwr[i] != 0xffffffff)
6117 {
6118 for (j=0; j<8; j++)
6119 {
6120 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6121
6122 if ((Value + DeltaPwr) < 0)
6123 {
6124 Value = 0; /* min */
6125 }
6126 else if ((Value + DeltaPwr) > 0xF)
6127 {
6128 Value = 0xF; /* max */
6129 }
6130 else
6131 {
6132 Value += DeltaPwr; /* temperature compensation */
6133 }
6134
6135 /* fill new value to CSR offset */
6136 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6137 }
6138
6139 /* write tx power value to CSR */
6140 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6141 TX power for OFDM 6M/9M
6142 TX power for CCK5.5M/11M
6143 TX power for CCK1M/2M */
6144 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6145 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6146 }
6147 }
6148
6149 }
6150
6151 #ifdef CONFIG_STA_SUPPORT
6152 /*
6153 ==========================================================================
6154 Description:
6155 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6156 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6157 the wakeup timer timeout. Driver has to issue a separate command to wake
6158 PHY up.
6159
6160 IRQL = DISPATCH_LEVEL
6161
6162 ==========================================================================
6163 */
6164 VOID AsicSleepThenAutoWakeup(
6165 IN PRTMP_ADAPTER pAd,
6166 IN USHORT TbttNumToNextWakeUp)
6167 {
6168 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6169 }
6170
6171 /*
6172 ==========================================================================
6173 Description:
6174 AsicForceWakeup() is used whenever manual wakeup is required
6175 AsicForceSleep() should only be used when not in INFRA BSS. When
6176 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6177 ==========================================================================
6178 */
6179 VOID AsicForceSleep(
6180 IN PRTMP_ADAPTER pAd)
6181 {
6182
6183 }
6184
6185 /*
6186 ==========================================================================
6187 Description:
6188 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6189 expired.
6190
6191 IRQL = PASSIVE_LEVEL
6192 IRQL = DISPATCH_LEVEL
6193 ==========================================================================
6194 */
6195 VOID AsicForceWakeup(
6196 IN PRTMP_ADAPTER pAd,
6197 IN UCHAR Level)
6198 {
6199 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6200 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6201 }
6202 #endif // CONFIG_STA_SUPPORT //
6203 /*
6204 ==========================================================================
6205 Description:
6206 Set My BSSID
6207
6208 IRQL = DISPATCH_LEVEL
6209
6210 ==========================================================================
6211 */
6212 VOID AsicSetBssid(
6213 IN PRTMP_ADAPTER pAd,
6214 IN PUCHAR pBssid)
6215 {
6216 ULONG Addr4;
6217 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6218 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6219
6220 Addr4 = (ULONG)(pBssid[0]) |
6221 (ULONG)(pBssid[1] << 8) |
6222 (ULONG)(pBssid[2] << 16) |
6223 (ULONG)(pBssid[3] << 24);
6224 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6225
6226 Addr4 = 0;
6227 // always one BSSID in STA mode
6228 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6229
6230 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6231 }
6232
6233 VOID AsicSetMcastWC(
6234 IN PRTMP_ADAPTER pAd)
6235 {
6236 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6237 USHORT offset;
6238
6239 pEntry->Sst = SST_ASSOC;
6240 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6241 pEntry->PsMode = PWR_ACTIVE;
6242 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6243 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6244 }
6245
6246 /*
6247 ==========================================================================
6248 Description:
6249
6250 IRQL = DISPATCH_LEVEL
6251
6252 ==========================================================================
6253 */
6254 VOID AsicDelWcidTab(
6255 IN PRTMP_ADAPTER pAd,
6256 IN UCHAR Wcid)
6257 {
6258 ULONG Addr0 = 0x0, Addr1 = 0x0;
6259 ULONG offset;
6260
6261 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6262 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6263 RTMP_IO_WRITE32(pAd, offset, Addr0);
6264 offset += 4;
6265 RTMP_IO_WRITE32(pAd, offset, Addr1);
6266 }
6267
6268 /*
6269 ==========================================================================
6270 Description:
6271
6272 IRQL = DISPATCH_LEVEL
6273
6274 ==========================================================================
6275 */
6276 VOID AsicEnableRDG(
6277 IN PRTMP_ADAPTER pAd)
6278 {
6279 TX_LINK_CFG_STRUC TxLinkCfg;
6280 UINT32 Data = 0;
6281
6282 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6283 TxLinkCfg.field.TxRDGEn = 1;
6284 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6285
6286 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6287 Data &= 0xFFFFFF00;
6288 Data |= 0x80;
6289 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6290
6291 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6292 }
6293
6294 /*
6295 ==========================================================================
6296 Description:
6297
6298 IRQL = DISPATCH_LEVEL
6299
6300 ==========================================================================
6301 */
6302 VOID AsicDisableRDG(
6303 IN PRTMP_ADAPTER pAd)
6304 {
6305 TX_LINK_CFG_STRUC TxLinkCfg;
6306 UINT32 Data = 0;
6307
6308
6309 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6310 TxLinkCfg.field.TxRDGEn = 0;
6311 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6312
6313 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6314
6315 Data &= 0xFFFFFF00;
6316 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6317 #ifdef DOT11_N_SUPPORT
6318 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6319 #endif // DOT11_N_SUPPORT //
6320 )
6321 {
6322 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6323 if (pAd->CommonCfg.bEnableTxBurst)
6324 Data |= 0x20;
6325 }
6326 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6327 }
6328
6329 /*
6330 ==========================================================================
6331 Description:
6332
6333 IRQL = PASSIVE_LEVEL
6334 IRQL = DISPATCH_LEVEL
6335
6336 ==========================================================================
6337 */
6338 VOID AsicDisableSync(
6339 IN PRTMP_ADAPTER pAd)
6340 {
6341 BCN_TIME_CFG_STRUC csr;
6342
6343 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6344
6345 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6346 // that NIC will never wakes up because TSF stops and no more
6347 // TBTT interrupts
6348 pAd->TbttTickCount = 0;
6349 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6350 csr.field.bBeaconGen = 0;
6351 csr.field.bTBTTEnable = 0;
6352 csr.field.TsfSyncMode = 0;
6353 csr.field.bTsfTicking = 0;
6354 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6355
6356 }
6357
6358 /*
6359 ==========================================================================
6360 Description:
6361
6362 IRQL = DISPATCH_LEVEL
6363
6364 ==========================================================================
6365 */
6366 VOID AsicEnableBssSync(
6367 IN PRTMP_ADAPTER pAd)
6368 {
6369 BCN_TIME_CFG_STRUC csr;
6370
6371 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6372
6373 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6374 #ifdef CONFIG_STA_SUPPORT
6375 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6376 {
6377 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6378 csr.field.bTsfTicking = 1;
6379 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6380 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6381 csr.field.bTBTTEnable = 1;
6382 }
6383 #endif // CONFIG_STA_SUPPORT //
6384 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6385 }
6386
6387 /*
6388 ==========================================================================
6389 Description:
6390 Note:
6391 BEACON frame in shared memory should be built ok before this routine
6392 can be called. Otherwise, a garbage frame maybe transmitted out every
6393 Beacon period.
6394
6395 IRQL = DISPATCH_LEVEL
6396
6397 ==========================================================================
6398 */
6399 VOID AsicEnableIbssSync(
6400 IN PRTMP_ADAPTER pAd)
6401 {
6402 BCN_TIME_CFG_STRUC csr9;
6403 PUCHAR ptr;
6404 UINT i;
6405
6406 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6407
6408 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6409 csr9.field.bBeaconGen = 0;
6410 csr9.field.bTBTTEnable = 0;
6411 csr9.field.bTsfTicking = 0;
6412 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6413
6414 // move BEACON TXD and frame content to on-chip memory
6415 ptr = (PUCHAR)&pAd->BeaconTxWI;
6416 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6417 {
6418 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6419 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6420 ptr += 4;
6421 }
6422
6423 // start right after the 16-byte TXWI field
6424 ptr = pAd->BeaconBuf;
6425 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6426 {
6427 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6428 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6429 ptr +=4;
6430 }
6431
6432 // start sending BEACON
6433 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6434 csr9.field.bTsfTicking = 1;
6435 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6436 csr9.field.bTBTTEnable = 1;
6437 csr9.field.bBeaconGen = 1;
6438 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6439 }
6440
6441 /*
6442 ==========================================================================
6443 Description:
6444
6445 IRQL = PASSIVE_LEVEL
6446 IRQL = DISPATCH_LEVEL
6447
6448 ==========================================================================
6449 */
6450 VOID AsicSetEdcaParm(
6451 IN PRTMP_ADAPTER pAd,
6452 IN PEDCA_PARM pEdcaParm)
6453 {
6454 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6455 AC_TXOP_CSR0_STRUC csr0;
6456 AC_TXOP_CSR1_STRUC csr1;
6457 AIFSN_CSR_STRUC AifsnCsr;
6458 CWMIN_CSR_STRUC CwminCsr;
6459 CWMAX_CSR_STRUC CwmaxCsr;
6460 int i;
6461
6462 Ac0Cfg.word = 0;
6463 Ac1Cfg.word = 0;
6464 Ac2Cfg.word = 0;
6465 Ac3Cfg.word = 0;
6466 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6467 {
6468 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6469 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6470 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6471 {
6472 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6473 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6474 }
6475
6476 //========================================================
6477 // MAC Register has a copy .
6478 //========================================================
6479 if( pAd->CommonCfg.bEnableTxBurst )
6480 {
6481 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6482 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6483 }
6484 else
6485 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6486 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6487 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6488 Ac0Cfg.field.Aifsn = 2;
6489 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6490
6491 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6492 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6493 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6494 Ac1Cfg.field.Aifsn = 2;
6495 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6496
6497 if (pAd->CommonCfg.PhyMode == PHY_11B)
6498 {
6499 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6500 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6501 }
6502 else
6503 {
6504 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6505 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6506 }
6507 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6508 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6509 Ac2Cfg.field.Aifsn = 2;
6510 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6511 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6512 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6513 Ac3Cfg.field.Aifsn = 2;
6514 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6515
6516 //========================================================
6517 // DMA Register has a copy too.
6518 //========================================================
6519 csr0.field.Ac0Txop = 0; // QID_AC_BE
6520 csr0.field.Ac1Txop = 0; // QID_AC_BK
6521 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6522 if (pAd->CommonCfg.PhyMode == PHY_11B)
6523 {
6524 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6525 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6526 }
6527 else
6528 {
6529 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6530 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6531 }
6532 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6533
6534 CwminCsr.word = 0;
6535 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6536 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6537 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6538 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6539 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6540
6541 CwmaxCsr.word = 0;
6542 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6543 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6544 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6545 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6546 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6547
6548 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6549
6550 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6551 }
6552 else
6553 {
6554 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6555 //========================================================
6556 // MAC Register has a copy.
6557 //========================================================
6558 //
6559 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6560 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6561 //
6562 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6563
6564 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6565 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6566 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6567 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6568
6569 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6570 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6571 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6572 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6573
6574 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6575 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6576 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6577 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6578 #ifdef CONFIG_STA_SUPPORT
6579 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6580 {
6581 // Tuning for Wi-Fi WMM S06
6582 if (pAd->CommonCfg.bWiFiTest &&
6583 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6584 Ac2Cfg.field.Aifsn -= 1;
6585
6586 // Tuning for TGn Wi-Fi 5.2.32
6587 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6588 if (STA_TGN_WIFI_ON(pAd) &&
6589 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6590 {
6591 Ac0Cfg.field.Aifsn = 3;
6592 Ac2Cfg.field.AcTxop = 5;
6593 }
6594 }
6595 #endif // CONFIG_STA_SUPPORT //
6596
6597 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6598 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6599 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6600 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6601
6602 //#ifdef WIFI_TEST
6603 if (pAd->CommonCfg.bWiFiTest)
6604 {
6605 if (Ac3Cfg.field.AcTxop == 102)
6606 {
6607 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6608 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6609 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6610 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6611 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6612 } /* End of if */
6613 }
6614 //#endif // WIFI_TEST //
6615
6616 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6617 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6618 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6619 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6620
6621
6622 //========================================================
6623 // DMA Register has a copy too.
6624 //========================================================
6625 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6626 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6627 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6628
6629 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6630 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6631 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6632
6633 CwminCsr.word = 0;
6634 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6635 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6636 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6637 #ifdef CONFIG_STA_SUPPORT
6638 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6639 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6640 #endif // CONFIG_STA_SUPPORT //
6641 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6642
6643 CwmaxCsr.word = 0;
6644 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6645 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6646 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6647 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6648 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6649
6650 AifsnCsr.word = 0;
6651 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6652 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6653 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6654 #ifdef CONFIG_STA_SUPPORT
6655 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6656 {
6657 // Tuning for Wi-Fi WMM S06
6658 if (pAd->CommonCfg.bWiFiTest &&
6659 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6660 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6661
6662 // Tuning for TGn Wi-Fi 5.2.32
6663 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6664 if (STA_TGN_WIFI_ON(pAd) &&
6665 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6666 {
6667 AifsnCsr.field.Aifsn0 = 3;
6668 AifsnCsr.field.Aifsn2 = 7;
6669 }
6670 }
6671 #endif // CONFIG_STA_SUPPORT //
6672
6673 #ifdef CONFIG_STA_SUPPORT
6674 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6675 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6676 #endif // CONFIG_STA_SUPPORT //
6677 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6678
6679 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6680 if (!ADHOC_ON(pAd))
6681 {
6682 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6683 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6684 pEdcaParm->Aifsn[0],
6685 pEdcaParm->Cwmin[0],
6686 pEdcaParm->Cwmax[0],
6687 pEdcaParm->Txop[0]<<5,
6688 pEdcaParm->bACM[0]));
6689 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6690 pEdcaParm->Aifsn[1],
6691 pEdcaParm->Cwmin[1],
6692 pEdcaParm->Cwmax[1],
6693 pEdcaParm->Txop[1]<<5,
6694 pEdcaParm->bACM[1]));
6695 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6696 pEdcaParm->Aifsn[2],
6697 pEdcaParm->Cwmin[2],
6698 pEdcaParm->Cwmax[2],
6699 pEdcaParm->Txop[2]<<5,
6700 pEdcaParm->bACM[2]));
6701 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6702 pEdcaParm->Aifsn[3],
6703 pEdcaParm->Cwmin[3],
6704 pEdcaParm->Cwmax[3],
6705 pEdcaParm->Txop[3]<<5,
6706 pEdcaParm->bACM[3]));
6707 }
6708 }
6709 }
6710
6711 /*
6712 ==========================================================================
6713 Description:
6714
6715 IRQL = PASSIVE_LEVEL
6716 IRQL = DISPATCH_LEVEL
6717
6718 ==========================================================================
6719 */
6720 VOID AsicSetSlotTime(
6721 IN PRTMP_ADAPTER pAd,
6722 IN BOOLEAN bUseShortSlotTime)
6723 {
6724 ULONG SlotTime;
6725 UINT32 RegValue = 0;
6726
6727 #ifdef CONFIG_STA_SUPPORT
6728 if (pAd->CommonCfg.Channel > 14)
6729 bUseShortSlotTime = TRUE;
6730 #endif // CONFIG_STA_SUPPORT //
6731
6732 if (bUseShortSlotTime)
6733 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6734 else
6735 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6736
6737 SlotTime = (bUseShortSlotTime)? 9 : 20;
6738
6739 #ifdef CONFIG_STA_SUPPORT
6740 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6741 {
6742 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6743 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6744 #ifdef DOT11_N_SUPPORT
6745 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6746 #endif // DOT11_N_SUPPORT //
6747 )
6748 {
6749 // In this case, we will think it is doing Wi-Fi test
6750 // And we will not set to short slot when bEnableTxBurst is TRUE.
6751 }
6752 else if (pAd->CommonCfg.bEnableTxBurst)
6753 SlotTime = 9;
6754 }
6755 #endif // CONFIG_STA_SUPPORT //
6756
6757 //
6758 // For some reasons, always set it to short slot time.
6759 //
6760 // ToDo: Should consider capability with 11B
6761 //
6762 #ifdef CONFIG_STA_SUPPORT
6763 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6764 {
6765 if (pAd->StaCfg.BssType == BSS_ADHOC)
6766 SlotTime = 20;
6767 }
6768 #endif // CONFIG_STA_SUPPORT //
6769
6770 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6771 RegValue = RegValue & 0xFFFFFF00;
6772
6773 RegValue |= SlotTime;
6774
6775 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6776 }
6777
6778 /*
6779 ========================================================================
6780 Description:
6781 Add Shared key information into ASIC.
6782 Update shared key, TxMic and RxMic to Asic Shared key table
6783 Update its cipherAlg to Asic Shared key Mode.
6784
6785 Return:
6786 ========================================================================
6787 */
6788 VOID AsicAddSharedKeyEntry(
6789 IN PRTMP_ADAPTER pAd,
6790 IN UCHAR BssIndex,
6791 IN UCHAR KeyIdx,
6792 IN UCHAR CipherAlg,
6793 IN PUCHAR pKey,
6794 IN PUCHAR pTxMic,
6795 IN PUCHAR pRxMic)
6796 {
6797 ULONG offset; //, csr0;
6798 SHAREDKEY_MODE_STRUC csr1;
6799 INT i;
6800
6801 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6802 //============================================================================================
6803
6804 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6805 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6806 pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
6807 if (pRxMic)
6808 {
6809 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6810 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6811 }
6812 if (pTxMic)
6813 {
6814 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6815 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6816 }
6817 //============================================================================================
6818 //
6819 // fill key material - key + TX MIC + RX MIC
6820 //
6821 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6822 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
6823 {
6824 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6825 }
6826
6827 offset += MAX_LEN_OF_SHARE_KEY;
6828 if (pTxMic)
6829 {
6830 for (i=0; i<8; i++)
6831 {
6832 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6833 }
6834 }
6835
6836 offset += 8;
6837 if (pRxMic)
6838 {
6839 for (i=0; i<8; i++)
6840 {
6841 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6842 }
6843 }
6844
6845
6846 //
6847 // Update cipher algorithm. WSTA always use BSS0
6848 //
6849 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6850 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6851 if ((BssIndex%2) == 0)
6852 {
6853 if (KeyIdx == 0)
6854 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6855 else if (KeyIdx == 1)
6856 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6857 else if (KeyIdx == 2)
6858 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6859 else
6860 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6861 }
6862 else
6863 {
6864 if (KeyIdx == 0)
6865 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6866 else if (KeyIdx == 1)
6867 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6868 else if (KeyIdx == 2)
6869 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6870 else
6871 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6872 }
6873 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6874 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6875
6876 }
6877
6878 // IRQL = DISPATCH_LEVEL
6879 VOID AsicRemoveSharedKeyEntry(
6880 IN PRTMP_ADAPTER pAd,
6881 IN UCHAR BssIndex,
6882 IN UCHAR KeyIdx)
6883 {
6884 //ULONG SecCsr0;
6885 SHAREDKEY_MODE_STRUC csr1;
6886
6887 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
6888
6889 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6890 if ((BssIndex%2) == 0)
6891 {
6892 if (KeyIdx == 0)
6893 csr1.field.Bss0Key0CipherAlg = 0;
6894 else if (KeyIdx == 1)
6895 csr1.field.Bss0Key1CipherAlg = 0;
6896 else if (KeyIdx == 2)
6897 csr1.field.Bss0Key2CipherAlg = 0;
6898 else
6899 csr1.field.Bss0Key3CipherAlg = 0;
6900 }
6901 else
6902 {
6903 if (KeyIdx == 0)
6904 csr1.field.Bss1Key0CipherAlg = 0;
6905 else if (KeyIdx == 1)
6906 csr1.field.Bss1Key1CipherAlg = 0;
6907 else if (KeyIdx == 2)
6908 csr1.field.Bss1Key2CipherAlg = 0;
6909 else
6910 csr1.field.Bss1Key3CipherAlg = 0;
6911 }
6912 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6913 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6914 ASSERT(BssIndex < 4);
6915 ASSERT(KeyIdx < 4);
6916
6917 }
6918
6919
6920 VOID AsicUpdateWCIDAttribute(
6921 IN PRTMP_ADAPTER pAd,
6922 IN USHORT WCID,
6923 IN UCHAR BssIndex,
6924 IN UCHAR CipherAlg,
6925 IN BOOLEAN bUsePairewiseKeyTable)
6926 {
6927 ULONG WCIDAttri = 0, offset;
6928
6929 //
6930 // Update WCID attribute.
6931 // Only TxKey could update WCID attribute.
6932 //
6933 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
6934 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
6935 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
6936 }
6937
6938 VOID AsicUpdateWCIDIVEIV(
6939 IN PRTMP_ADAPTER pAd,
6940 IN USHORT WCID,
6941 IN ULONG uIV,
6942 IN ULONG uEIV)
6943 {
6944 ULONG offset;
6945
6946 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6947
6948 RTMP_IO_WRITE32(pAd, offset, uIV);
6949 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
6950 }
6951
6952 VOID AsicUpdateRxWCIDTable(
6953 IN PRTMP_ADAPTER pAd,
6954 IN USHORT WCID,
6955 IN PUCHAR pAddr)
6956 {
6957 ULONG offset;
6958 ULONG Addr;
6959
6960 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
6961 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
6962 RTMP_IO_WRITE32(pAd, offset, Addr);
6963 Addr = pAddr[4] + (pAddr[5] << 8);
6964 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
6965 }
6966
6967
6968 /*
6969 ========================================================================
6970
6971 Routine Description:
6972 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
6973
6974 Arguments:
6975 pAd Pointer to our adapter
6976 WCID WCID Entry number.
6977 BssIndex BSSID index, station or none multiple BSSID support
6978 this value should be 0.
6979 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
6980 pCipherKey Pointer to Cipher Key.
6981 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
6982 otherwise PairewiseKey table
6983 bTxKey This is the transmit key if enabled.
6984
6985 Return Value:
6986 None
6987
6988 Note:
6989 This routine will set the relative key stuff to Asic including WCID attribute,
6990 Cipher Key, Cipher algorithm and IV/EIV.
6991
6992 IV/EIV will be update if this CipherKey is the transmission key because
6993 ASIC will base on IV's KeyID value to select Cipher Key.
6994
6995 If bTxKey sets to FALSE, this is not the TX key, but it could be
6996 RX key
6997
6998 For AP mode bTxKey must be always set to TRUE.
6999 ========================================================================
7000 */
7001 VOID AsicAddKeyEntry(
7002 IN PRTMP_ADAPTER pAd,
7003 IN USHORT WCID,
7004 IN UCHAR BssIndex,
7005 IN UCHAR KeyIdx,
7006 IN PCIPHER_KEY pCipherKey,
7007 IN BOOLEAN bUsePairewiseKeyTable,
7008 IN BOOLEAN bTxKey)
7009 {
7010 ULONG offset;
7011 UCHAR IV4 = 0;
7012 PUCHAR pKey = pCipherKey->Key;
7013 PUCHAR pTxMic = pCipherKey->TxMic;
7014 PUCHAR pRxMic = pCipherKey->RxMic;
7015 PUCHAR pTxtsc = pCipherKey->TxTsc;
7016 UCHAR CipherAlg = pCipherKey->CipherAlg;
7017 SHAREDKEY_MODE_STRUC csr1;
7018 UCHAR i;
7019
7020 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7021 //
7022 // 1.) decide key table offset
7023 //
7024 if (bUsePairewiseKeyTable)
7025 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7026 else
7027 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7028
7029 //
7030 // 2.) Set Key to Asic
7031 //
7032 //for (i = 0; i < KeyLen; i++)
7033 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7034 {
7035 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7036 }
7037 offset += MAX_LEN_OF_PEER_KEY;
7038
7039 //
7040 // 3.) Set MIC key if available
7041 //
7042 if (pTxMic)
7043 {
7044 for (i = 0; i < 8; i++)
7045 {
7046 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7047 }
7048 }
7049 offset += LEN_TKIP_TXMICK;
7050
7051 if (pRxMic)
7052 {
7053 for (i = 0; i < 8; i++)
7054 {
7055 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7056 }
7057 }
7058
7059
7060 //
7061 // 4.) Modify IV/EIV if needs
7062 // This will force Asic to use this key ID by setting IV.
7063 //
7064 if (bTxKey)
7065 {
7066 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7067 //
7068 // Write IV
7069 //
7070 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7071 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7072 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7073
7074 IV4 = (KeyIdx << 6);
7075 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7076 IV4 |= 0x20; // turn on extension bit means EIV existence
7077
7078 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7079
7080 //
7081 // Write EIV
7082 //
7083 offset += 4;
7084 for (i = 0; i < 4; i++)
7085 {
7086 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7087 }
7088
7089 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7090 }
7091
7092 if (!bUsePairewiseKeyTable)
7093 {
7094 //
7095 // Only update the shared key security mode
7096 //
7097 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7098 if ((BssIndex % 2) == 0)
7099 {
7100 if (KeyIdx == 0)
7101 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7102 else if (KeyIdx == 1)
7103 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7104 else if (KeyIdx == 2)
7105 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7106 else
7107 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7108 }
7109 else
7110 {
7111 if (KeyIdx == 0)
7112 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7113 else if (KeyIdx == 1)
7114 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7115 else if (KeyIdx == 2)
7116 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7117 else
7118 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7119 }
7120 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7121 }
7122
7123 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7124 }
7125
7126
7127 /*
7128 ========================================================================
7129 Description:
7130 Add Pair-wise key material into ASIC.
7131 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7132
7133 Return:
7134 ========================================================================
7135 */
7136 VOID AsicAddPairwiseKeyEntry(
7137 IN PRTMP_ADAPTER pAd,
7138 IN PUCHAR pAddr,
7139 IN UCHAR WCID,
7140 IN CIPHER_KEY *pCipherKey)
7141 {
7142 INT i;
7143 ULONG offset;
7144 PUCHAR pKey = pCipherKey->Key;
7145 PUCHAR pTxMic = pCipherKey->TxMic;
7146 PUCHAR pRxMic = pCipherKey->RxMic;
7147 #ifdef DBG
7148 UCHAR CipherAlg = pCipherKey->CipherAlg;
7149 #endif // DBG //
7150
7151 // EKEY
7152 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7153 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7154 {
7155 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7156 }
7157 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7158 {
7159 UINT32 Value;
7160 RTMP_IO_READ32(pAd, offset + i, &Value);
7161 }
7162
7163 offset += MAX_LEN_OF_PEER_KEY;
7164
7165 // MIC KEY
7166 if (pTxMic)
7167 {
7168 for (i=0; i<8; i++)
7169 {
7170 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7171 }
7172 }
7173 offset += 8;
7174 if (pRxMic)
7175 {
7176 for (i=0; i<8; i++)
7177 {
7178 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7179 }
7180 }
7181
7182 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7183 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7184 pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15]));
7185 if (pRxMic)
7186 {
7187 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7188 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7189 }
7190 if (pTxMic)
7191 {
7192 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7193 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7194 }
7195 }
7196 /*
7197 ========================================================================
7198 Description:
7199 Remove Pair-wise key material from ASIC.
7200
7201 Return:
7202 ========================================================================
7203 */
7204 VOID AsicRemovePairwiseKeyEntry(
7205 IN PRTMP_ADAPTER pAd,
7206 IN UCHAR BssIdx,
7207 IN UCHAR Wcid)
7208 {
7209 ULONG WCIDAttri;
7210 USHORT offset;
7211
7212 // re-set the entry's WCID attribute as OPEN-NONE.
7213 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7214 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7215 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7216 }
7217
7218 BOOLEAN AsicSendCommandToMcu(
7219 IN PRTMP_ADAPTER pAd,
7220 IN UCHAR Command,
7221 IN UCHAR Token,
7222 IN UCHAR Arg0,
7223 IN UCHAR Arg1)
7224 {
7225 HOST_CMD_CSR_STRUC H2MCmd;
7226 H2M_MAILBOX_STRUC H2MMailbox;
7227 ULONG i = 0;
7228
7229 do
7230 {
7231 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7232 if (H2MMailbox.field.Owner == 0)
7233 break;
7234
7235 RTMPusecDelay(2);
7236 } while(i++ < 100);
7237
7238 if (i >= 100)
7239 {
7240 {
7241 UINT32 Data;
7242
7243 // Reset DMA
7244 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7245 Data |= 0x2;
7246 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7247
7248 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7249 // Reset DMA/CPU ring index
7250 RTMPRingCleanUp(pAd, QID_AC_BK);
7251 RTMPRingCleanUp(pAd, QID_AC_BE);
7252 RTMPRingCleanUp(pAd, QID_AC_VI);
7253 RTMPRingCleanUp(pAd, QID_AC_VO);
7254 RTMPRingCleanUp(pAd, QID_HCCA);
7255 RTMPRingCleanUp(pAd, QID_MGMT);
7256 RTMPRingCleanUp(pAd, QID_RX);
7257
7258 // Clear Reset
7259 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7260 Data &= 0xfffffffd;
7261 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7262 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7263 }
7264 //return FALSE;
7265 }
7266
7267 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7268 H2MMailbox.field.CmdToken = Token;
7269 H2MMailbox.field.HighByte = Arg1;
7270 H2MMailbox.field.LowByte = Arg0;
7271 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7272
7273 H2MCmd.word = 0;
7274 H2MCmd.field.HostCommand = Command;
7275 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7276
7277 if (Command != 0x80)
7278 {
7279 }
7280
7281 return TRUE;
7282 }
7283
7284 BOOLEAN AsicCheckCommanOk(
7285 IN PRTMP_ADAPTER pAd,
7286 IN UCHAR Command)
7287 {
7288 UINT32 CmdStatus = 0, CID = 0, i;
7289 UINT32 ThisCIDMask = 0;
7290
7291 i = 0;
7292 do
7293 {
7294 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7295 // Find where the command is. Because this is randomly specified by firmware.
7296 if ((CID & CID0MASK) == Command)
7297 {
7298 ThisCIDMask = CID0MASK;
7299 break;
7300 }
7301 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7302 {
7303 ThisCIDMask = CID1MASK;
7304 break;
7305 }
7306 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7307 {
7308 ThisCIDMask = CID2MASK;
7309 break;
7310 }
7311 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7312 {
7313 ThisCIDMask = CID3MASK;
7314 break;
7315 }
7316
7317 RTMPusecDelay(100);
7318 i++;
7319 }while (i < 200);
7320
7321 // Get CommandStatus Value
7322 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7323
7324 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7325 if (i < 200)
7326 {
7327 // If Status is 1, the comamnd is success.
7328 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7329 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7330 {
7331 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7332 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7333 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7334 return TRUE;
7335 }
7336 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7337 }
7338 else
7339 {
7340 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7341 }
7342 // Clear Command and Status.
7343 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7344 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7345
7346 return FALSE;
7347 }
7348
7349 /*
7350 ========================================================================
7351
7352 Routine Description:
7353 Verify the support rate for different PHY type
7354
7355 Arguments:
7356 pAd Pointer to our adapter
7357
7358 Return Value:
7359 None
7360
7361 IRQL = PASSIVE_LEVEL
7362
7363 ========================================================================
7364 */
7365 VOID RTMPCheckRates(
7366 IN PRTMP_ADAPTER pAd,
7367 IN OUT UCHAR SupRate[],
7368 IN OUT UCHAR *SupRateLen)
7369 {
7370 UCHAR RateIdx, i, j;
7371 UCHAR NewRate[12], NewRateLen;
7372
7373 NewRateLen = 0;
7374
7375 if (pAd->CommonCfg.PhyMode == PHY_11B)
7376 RateIdx = 4;
7377 else
7378 RateIdx = 12;
7379
7380 // Check for support rates exclude basic rate bit
7381 for (i = 0; i < *SupRateLen; i++)
7382 for (j = 0; j < RateIdx; j++)
7383 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7384 NewRate[NewRateLen++] = SupRate[i];
7385
7386 *SupRateLen = NewRateLen;
7387 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7388 }
7389
7390 #ifdef CONFIG_STA_SUPPORT
7391 #ifdef DOT11_N_SUPPORT
7392 BOOLEAN RTMPCheckChannel(
7393 IN PRTMP_ADAPTER pAd,
7394 IN UCHAR CentralChannel,
7395 IN UCHAR Channel)
7396 {
7397 UCHAR k;
7398 UCHAR UpperChannel = 0, LowerChannel = 0;
7399 UCHAR NoEffectChannelinList = 0;
7400
7401 // Find upper and lower channel according to 40MHz current operation.
7402 if (CentralChannel < Channel)
7403 {
7404 UpperChannel = Channel;
7405 if (CentralChannel > 2)
7406 LowerChannel = CentralChannel - 2;
7407 else
7408 return FALSE;
7409 }
7410 else if (CentralChannel > Channel)
7411 {
7412 UpperChannel = CentralChannel + 2;
7413 LowerChannel = Channel;
7414 }
7415
7416 for (k = 0;k < pAd->ChannelListNum;k++)
7417 {
7418 if (pAd->ChannelList[k].Channel == UpperChannel)
7419 {
7420 NoEffectChannelinList ++;
7421 }
7422 if (pAd->ChannelList[k].Channel == LowerChannel)
7423 {
7424 NoEffectChannelinList ++;
7425 }
7426 }
7427
7428 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7429 if (NoEffectChannelinList == 2)
7430 return TRUE;
7431 else
7432 return FALSE;
7433 }
7434
7435 /*
7436 ========================================================================
7437
7438 Routine Description:
7439 Verify the support rate for HT phy type
7440
7441 Arguments:
7442 pAd Pointer to our adapter
7443
7444 Return Value:
7445 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7446
7447 IRQL = PASSIVE_LEVEL
7448
7449 ========================================================================
7450 */
7451 BOOLEAN RTMPCheckHt(
7452 IN PRTMP_ADAPTER pAd,
7453 IN UCHAR Wcid,
7454 IN HT_CAPABILITY_IE *pHtCapability,
7455 IN ADD_HT_INFO_IE *pAddHtInfo)
7456 {
7457 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7458 return FALSE;
7459
7460 // If use AMSDU, set flag.
7461 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7462 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7463 // Save Peer Capability
7464 if (pHtCapability->HtCapInfo.ShortGIfor20)
7465 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7466 if (pHtCapability->HtCapInfo.ShortGIfor40)
7467 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7468 if (pHtCapability->HtCapInfo.TxSTBC)
7469 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7470 if (pHtCapability->HtCapInfo.RxSTBC)
7471 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7472 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7473 {
7474 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7475 }
7476
7477 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7478 {
7479 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7480 }
7481
7482 // Will check ChannelWidth for MCSSet[4] below
7483 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7484 switch (pAd->CommonCfg.RxStream)
7485 {
7486 case 1:
7487 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7488 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7489 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7490 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7491 break;
7492 case 2:
7493 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7494 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7495 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7496 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7497 break;
7498 case 3:
7499 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7500 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7501 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7502 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7503 break;
7504 }
7505
7506 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7507
7508 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7509 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7510 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7511
7512 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7513
7514 // Send Assoc Req with my HT capability.
7515 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7516 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7517 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7518 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7519 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7520 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7521 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7522 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7523 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7524 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7525 if (pAd->CommonCfg.bRdg)
7526 {
7527 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7528 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7529 }
7530
7531 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7532 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7533
7534 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7535 return TRUE;
7536 }
7537 #endif // DOT11_N_SUPPORT //
7538 #endif // CONFIG_STA_SUPPORT //
7539
7540 /*
7541 ========================================================================
7542
7543 Routine Description:
7544 Verify the support rate for different PHY type
7545
7546 Arguments:
7547 pAd Pointer to our adapter
7548
7549 Return Value:
7550 None
7551
7552 IRQL = PASSIVE_LEVEL
7553
7554 ========================================================================
7555 */
7556 VOID RTMPUpdateMlmeRate(
7557 IN PRTMP_ADAPTER pAd)
7558 {
7559 UCHAR MinimumRate;
7560 UCHAR ProperMlmeRate; //= RATE_54;
7561 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7562 BOOLEAN bMatch = FALSE;
7563
7564 switch (pAd->CommonCfg.PhyMode)
7565 {
7566 case PHY_11B:
7567 ProperMlmeRate = RATE_11;
7568 MinimumRate = RATE_1;
7569 break;
7570 case PHY_11BG_MIXED:
7571 #ifdef DOT11_N_SUPPORT
7572 case PHY_11ABGN_MIXED:
7573 case PHY_11BGN_MIXED:
7574 #endif // DOT11_N_SUPPORT //
7575 if ((pAd->MlmeAux.SupRateLen == 4) &&
7576 (pAd->MlmeAux.ExtRateLen == 0))
7577 // B only AP
7578 ProperMlmeRate = RATE_11;
7579 else
7580 ProperMlmeRate = RATE_24;
7581
7582 if (pAd->MlmeAux.Channel <= 14)
7583 MinimumRate = RATE_1;
7584 else
7585 MinimumRate = RATE_6;
7586 break;
7587 case PHY_11A:
7588 #ifdef DOT11_N_SUPPORT
7589 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7590 case PHY_11GN_MIXED:
7591 case PHY_11AGN_MIXED:
7592 case PHY_11AN_MIXED:
7593 case PHY_11N_5G:
7594 #endif // DOT11_N_SUPPORT //
7595 ProperMlmeRate = RATE_24;
7596 MinimumRate = RATE_6;
7597 break;
7598 case PHY_11ABG_MIXED:
7599 ProperMlmeRate = RATE_24;
7600 if (pAd->MlmeAux.Channel <= 14)
7601 MinimumRate = RATE_1;
7602 else
7603 MinimumRate = RATE_6;
7604 break;
7605 default: // error
7606 ProperMlmeRate = RATE_1;
7607 MinimumRate = RATE_1;
7608 break;
7609 }
7610
7611 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7612 {
7613 for (j = 0; j < RateIdx; j++)
7614 {
7615 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7616 {
7617 if (j == ProperMlmeRate)
7618 {
7619 bMatch = TRUE;
7620 break;
7621 }
7622 }
7623 }
7624
7625 if (bMatch)
7626 break;
7627 }
7628
7629 if (bMatch == FALSE)
7630 {
7631 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7632 {
7633 for (j = 0; j < RateIdx; j++)
7634 {
7635 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7636 {
7637 if (j == ProperMlmeRate)
7638 {
7639 bMatch = TRUE;
7640 break;
7641 }
7642 }
7643 }
7644
7645 if (bMatch)
7646 break;
7647 }
7648 }
7649
7650 if (bMatch == FALSE)
7651 {
7652 ProperMlmeRate = MinimumRate;
7653 }
7654
7655 pAd->CommonCfg.MlmeRate = MinimumRate;
7656 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7657 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7658 {
7659 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7660 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7661 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7662 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7663 }
7664 else
7665 {
7666 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7667 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7668 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7669 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7670 }
7671
7672 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7673 }
7674
7675 CHAR RTMPMaxRssi(
7676 IN PRTMP_ADAPTER pAd,
7677 IN CHAR Rssi0,
7678 IN CHAR Rssi1,
7679 IN CHAR Rssi2)
7680 {
7681 CHAR larger = -127;
7682
7683 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7684 {
7685 larger = Rssi0;
7686 }
7687
7688 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7689 {
7690 larger = max(Rssi0, Rssi1);
7691 }
7692
7693 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7694 {
7695 larger = max(larger, Rssi2);
7696 }
7697
7698 if (larger == -127)
7699 larger = 0;
7700
7701 return larger;
7702 }
7703
7704 /*
7705 ========================================================================
7706 Routine Description:
7707 Periodic evaluate antenna link status
7708
7709 Arguments:
7710 pAd - Adapter pointer
7711
7712 Return Value:
7713 None
7714
7715 ========================================================================
7716 */
7717 VOID AsicEvaluateRxAnt(
7718 IN PRTMP_ADAPTER pAd)
7719 {
7720 UCHAR BBPR3 = 0;
7721
7722 #ifdef CONFIG_STA_SUPPORT
7723 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7724 {
7725 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7726 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7727 fRTMP_ADAPTER_RADIO_OFF |
7728 fRTMP_ADAPTER_NIC_NOT_EXIST |
7729 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7730 return;
7731
7732 if (pAd->StaCfg.Psm == PWR_SAVE)
7733 return;
7734 }
7735 #endif // CONFIG_STA_SUPPORT //
7736
7737 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7738 BBPR3 &= (~0x18);
7739 if(pAd->Antenna.field.RxPath == 3)
7740 {
7741 BBPR3 |= (0x10);
7742 }
7743 else if(pAd->Antenna.field.RxPath == 2)
7744 {
7745 BBPR3 |= (0x8);
7746 }
7747 else if(pAd->Antenna.field.RxPath == 1)
7748 {
7749 BBPR3 |= (0x0);
7750 }
7751 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7752 #ifdef CONFIG_STA_SUPPORT
7753 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7754 pAd->StaCfg.BBPR3 = BBPR3;
7755 #endif // CONFIG_STA_SUPPORT //
7756 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7757 )
7758 {
7759 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7760 pAd->RalinkCounters.OneSecTxRetryOkCount +
7761 pAd->RalinkCounters.OneSecTxFailCount;
7762
7763 if (TxTotalCnt > 50)
7764 {
7765 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7766 pAd->Mlme.bLowThroughput = FALSE;
7767 }
7768 else
7769 {
7770 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7771 pAd->Mlme.bLowThroughput = TRUE;
7772 }
7773 }
7774 }
7775
7776 /*
7777 ========================================================================
7778 Routine Description:
7779 After evaluation, check antenna link status
7780
7781 Arguments:
7782 pAd - Adapter pointer
7783
7784 Return Value:
7785 None
7786
7787 ========================================================================
7788 */
7789 VOID AsicRxAntEvalTimeout(
7790 IN PVOID SystemSpecific1,
7791 IN PVOID FunctionContext,
7792 IN PVOID SystemSpecific2,
7793 IN PVOID SystemSpecific3)
7794 {
7795 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7796 #ifdef CONFIG_STA_SUPPORT
7797 UCHAR BBPR3 = 0;
7798 CHAR larger = -127, rssi0, rssi1, rssi2;
7799 #endif // CONFIG_STA_SUPPORT //
7800
7801 #ifdef CONFIG_STA_SUPPORT
7802 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7803 {
7804 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7805 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7806 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7807 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7808 return;
7809
7810 if (pAd->StaCfg.Psm == PWR_SAVE)
7811 return;
7812
7813
7814 // if the traffic is low, use average rssi as the criteria
7815 if (pAd->Mlme.bLowThroughput == TRUE)
7816 {
7817 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7818 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7819 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7820 }
7821 else
7822 {
7823 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7824 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7825 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7826 }
7827
7828 if(pAd->Antenna.field.RxPath == 3)
7829 {
7830 larger = max(rssi0, rssi1);
7831
7832 if (larger > (rssi2 + 20))
7833 pAd->Mlme.RealRxPath = 2;
7834 else
7835 pAd->Mlme.RealRxPath = 3;
7836 }
7837 else if(pAd->Antenna.field.RxPath == 2)
7838 {
7839 if (rssi0 > (rssi1 + 20))
7840 pAd->Mlme.RealRxPath = 1;
7841 else
7842 pAd->Mlme.RealRxPath = 2;
7843 }
7844
7845 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7846 BBPR3 &= (~0x18);
7847 if(pAd->Mlme.RealRxPath == 3)
7848 {
7849 BBPR3 |= (0x10);
7850 }
7851 else if(pAd->Mlme.RealRxPath == 2)
7852 {
7853 BBPR3 |= (0x8);
7854 }
7855 else if(pAd->Mlme.RealRxPath == 1)
7856 {
7857 BBPR3 |= (0x0);
7858 }
7859 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7860 pAd->StaCfg.BBPR3 = BBPR3;
7861 }
7862
7863 #endif // CONFIG_STA_SUPPORT //
7864
7865 }
7866
7867
7868
7869 VOID APSDPeriodicExec(
7870 IN PVOID SystemSpecific1,
7871 IN PVOID FunctionContext,
7872 IN PVOID SystemSpecific2,
7873 IN PVOID SystemSpecific3)
7874 {
7875 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7876
7877 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7878 return;
7879
7880 pAd->CommonCfg.TriggerTimerCount++;
7881
7882 }
7883
7884 /*
7885 ========================================================================
7886 Routine Description:
7887 Set/reset MAC registers according to bPiggyBack parameter
7888
7889 Arguments:
7890 pAd - Adapter pointer
7891 bPiggyBack - Enable / Disable Piggy-Back
7892
7893 Return Value:
7894 None
7895
7896 ========================================================================
7897 */
7898 VOID RTMPSetPiggyBack(
7899 IN PRTMP_ADAPTER pAd,
7900 IN BOOLEAN bPiggyBack)
7901 {
7902 TX_LINK_CFG_STRUC TxLinkCfg;
7903
7904 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
7905
7906 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
7907 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
7908 }
7909
7910 /*
7911 ========================================================================
7912 Routine Description:
7913 check if this entry need to switch rate automatically
7914
7915 Arguments:
7916 pAd
7917 pEntry
7918
7919 Return Value:
7920 TURE
7921 FALSE
7922
7923 ========================================================================
7924 */
7925 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
7926 IN PRTMP_ADAPTER pAd,
7927 IN PMAC_TABLE_ENTRY pEntry)
7928 {
7929 BOOLEAN result = TRUE;
7930
7931
7932 #ifdef CONFIG_STA_SUPPORT
7933 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7934 {
7935 // only associated STA counts
7936 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
7937 {
7938 result = pAd->StaCfg.bAutoTxRateSwitch;
7939 }
7940 else
7941 result = FALSE;
7942 }
7943 #endif // CONFIG_STA_SUPPORT //
7944
7945
7946
7947 return result;
7948 }
7949
7950
7951 BOOLEAN RTMPAutoRateSwitchCheck(
7952 IN PRTMP_ADAPTER pAd)
7953 {
7954
7955 #ifdef CONFIG_STA_SUPPORT
7956 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7957 {
7958 if (pAd->StaCfg.bAutoTxRateSwitch)
7959 return TRUE;
7960 }
7961 #endif // CONFIG_STA_SUPPORT //
7962 return FALSE;
7963 }
7964
7965
7966 /*
7967 ========================================================================
7968 Routine Description:
7969 check if this entry need to fix tx legacy rate
7970
7971 Arguments:
7972 pAd
7973 pEntry
7974
7975 Return Value:
7976 TURE
7977 FALSE
7978
7979 ========================================================================
7980 */
7981 UCHAR RTMPStaFixedTxMode(
7982 IN PRTMP_ADAPTER pAd,
7983 IN PMAC_TABLE_ENTRY pEntry)
7984 {
7985 UCHAR tx_mode = FIXED_TXMODE_HT;
7986
7987
7988 #ifdef CONFIG_STA_SUPPORT
7989 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7990 {
7991 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
7992 }
7993 #endif // CONFIG_STA_SUPPORT //
7994
7995 return tx_mode;
7996 }
7997
7998 /*
7999 ========================================================================
8000 Routine Description:
8001 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8002
8003 Arguments:
8004 pAd
8005 pEntry
8006
8007 Return Value:
8008 TURE
8009 FALSE
8010
8011 ========================================================================
8012 */
8013 VOID RTMPUpdateLegacyTxSetting(
8014 UCHAR fixed_tx_mode,
8015 PMAC_TABLE_ENTRY pEntry)
8016 {
8017 HTTRANSMIT_SETTING TransmitSetting;
8018
8019 if (fixed_tx_mode == FIXED_TXMODE_HT)
8020 return;
8021
8022 TransmitSetting.word = 0;
8023
8024 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8025 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8026
8027 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8028 {
8029 TransmitSetting.field.MODE = MODE_CCK;
8030 // CCK mode allow MCS 0~3
8031 if (TransmitSetting.field.MCS > MCS_3)
8032 TransmitSetting.field.MCS = MCS_3;
8033 }
8034 else
8035 {
8036 TransmitSetting.field.MODE = MODE_OFDM;
8037 // OFDM mode allow MCS 0~7
8038 if (TransmitSetting.field.MCS > MCS_7)
8039 TransmitSetting.field.MCS = MCS_7;
8040 }
8041
8042 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8043 {
8044 pEntry->HTPhyMode.word = TransmitSetting.word;
8045 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8046 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8047 }
8048 }
8049
8050 #ifdef CONFIG_STA_SUPPORT
8051 /*
8052 ==========================================================================
8053 Description:
8054 dynamic tune BBP R66 to find a balance between sensibility and
8055 noise isolation
8056
8057 IRQL = DISPATCH_LEVEL
8058
8059 ==========================================================================
8060 */
8061 VOID AsicStaBbpTuning(
8062 IN PRTMP_ADAPTER pAd)
8063 {
8064 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8065 CHAR Rssi;
8066
8067 // 2860C did not support Fase CCA, therefore can't tune
8068 if (pAd->MACVersion == 0x28600100)
8069 return;
8070
8071 //
8072 // work as a STA
8073 //
8074 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8075 return;
8076
8077 if ((pAd->OpMode == OPMODE_STA)
8078 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8079 )
8080 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8081 && (pAd->bPCIclkOff == FALSE))
8082 {
8083 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8084 R66 = OrigR66Value;
8085
8086 if (pAd->Antenna.field.RxPath > 1)
8087 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8088 else
8089 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8090
8091 if (pAd->LatchRfRegs.Channel <= 14)
8092 { //BG band
8093 {
8094 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8095 {
8096 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8097 if (OrigR66Value != R66)
8098 {
8099 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8100 }
8101 }
8102 else
8103 {
8104 R66 = 0x2E + GET_LNA_GAIN(pAd);
8105 if (OrigR66Value != R66)
8106 {
8107 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8108 }
8109 }
8110 }
8111 }
8112 else
8113 { //A band
8114 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8115 {
8116 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8117 {
8118 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8119 if (OrigR66Value != R66)
8120 {
8121 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8122 }
8123 }
8124 else
8125 {
8126 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8127 if (OrigR66Value != R66)
8128 {
8129 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8130 }
8131 }
8132 }
8133 else
8134 {
8135 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8136 {
8137 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8138 if (OrigR66Value != R66)
8139 {
8140 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8141 }
8142 }
8143 else
8144 {
8145 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8146 if (OrigR66Value != R66)
8147 {
8148 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8149 }
8150 }
8151 }
8152 }
8153
8154
8155 }
8156 }
8157
8158 VOID AsicResetFromDMABusy(
8159 IN PRTMP_ADAPTER pAd)
8160 {
8161 UINT32 Data;
8162 BOOLEAN bCtrl = FALSE;
8163
8164 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8165
8166 // Be sure restore link control value so we can write register.
8167 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8168 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8169 {
8170 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8171 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8172 RTMPusecDelay(6000);
8173 pAd->bPCIclkOff = FALSE;
8174 bCtrl = TRUE;
8175 }
8176 // Reset DMA
8177 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8178 Data |= 0x2;
8179 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8180
8181 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8182 // Reset DMA/CPU ring index
8183 RTMPRingCleanUp(pAd, QID_AC_BK);
8184 RTMPRingCleanUp(pAd, QID_AC_BE);
8185 RTMPRingCleanUp(pAd, QID_AC_VI);
8186 RTMPRingCleanUp(pAd, QID_AC_VO);
8187 RTMPRingCleanUp(pAd, QID_HCCA);
8188 RTMPRingCleanUp(pAd, QID_MGMT);
8189 RTMPRingCleanUp(pAd, QID_RX);
8190
8191 // Clear Reset
8192 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8193 Data &= 0xfffffffd;
8194 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8195
8196 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8197 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8198 RTMPPCIeLinkCtrlSetting(pAd, 3);
8199
8200 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8201 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8202 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8203 }
8204
8205 VOID AsicResetBBP(
8206 IN PRTMP_ADAPTER pAd)
8207 {
8208 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8209
8210 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8211 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8212 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8213
8214 // After hard-reset BBP, initialize all BBP values.
8215 NICRestoreBBPValue(pAd);
8216 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8217 }
8218
8219 VOID AsicResetMAC(
8220 IN PRTMP_ADAPTER pAd)
8221 {
8222 ULONG Data;
8223
8224 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8225 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8226 Data |= 0x4;
8227 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8228 Data &= 0xfffffffb;
8229 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8230
8231 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8232 }
8233
8234 VOID AsicResetPBF(
8235 IN PRTMP_ADAPTER pAd)
8236 {
8237 ULONG Value1, Value2;
8238 ULONG Data;
8239
8240 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8241 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8242
8243 Value2 &= 0xff;
8244 // sum should be equals to 0xff, which is the total buffer size.
8245 if ((Value1 + Value2) < 0xff)
8246 {
8247 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8248 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8249 Data |= 0x8;
8250 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8251 Data &= 0xfffffff7;
8252 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8253
8254 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8255 }
8256 }
8257 #endif // CONFIG_STA_SUPPORT //
8258
8259 VOID RTMPSetAGCInitValue(
8260 IN PRTMP_ADAPTER pAd,
8261 IN UCHAR BandWidth)
8262 {
8263 UCHAR R66 = 0x30;
8264
8265 if (pAd->LatchRfRegs.Channel <= 14)
8266 { // BG band
8267 R66 = 0x2E + GET_LNA_GAIN(pAd);
8268 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8269 }
8270 else
8271 { //A band
8272 if (BandWidth == BW_20)
8273 {
8274 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8275 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8276 }
8277 #ifdef DOT11_N_SUPPORT
8278 else
8279 {
8280 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8281 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8282 }
8283 #endif // DOT11_N_SUPPORT //
8284 }
8285
8286 }
8287
8288 VOID AsicTurnOffRFClk(
8289 IN PRTMP_ADAPTER pAd,
8290 IN UCHAR Channel)
8291 {
8292
8293 // RF R2 bit 18 = 0
8294 UINT32 R1 = 0, R2 = 0, R3 = 0;
8295 UCHAR index;
8296 RTMP_RF_REGS *RFRegTable;
8297
8298 RFRegTable = RF2850RegTable;
8299
8300 switch (pAd->RfIcType)
8301 {
8302 case RFIC_2820:
8303 case RFIC_2850:
8304 case RFIC_2720:
8305 case RFIC_2750:
8306
8307 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8308 {
8309 if (Channel == RFRegTable[index].Channel)
8310 {
8311 R1 = RFRegTable[index].R1 & 0xffffdfff;
8312 R2 = RFRegTable[index].R2 & 0xfffbffff;
8313 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8314
8315 RTMP_RF_IO_WRITE32(pAd, R1);
8316 RTMP_RF_IO_WRITE32(pAd, R2);
8317
8318 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8319 // Set RF R2 bit18=0, R3 bit[18:19]=0
8320 //if (pAd->StaCfg.bRadio == FALSE)
8321 if (1)
8322 {
8323 RTMP_RF_IO_WRITE32(pAd, R3);
8324
8325 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8326 Channel, pAd->RfIcType, R2, R3));
8327 }
8328 else
8329 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8330 Channel, pAd->RfIcType, R2));
8331 break;
8332 }
8333 }
8334 break;
8335
8336 default:
8337 break;
8338 }
8339 }
8340
8341
8342 VOID AsicTurnOnRFClk(
8343 IN PRTMP_ADAPTER pAd,
8344 IN UCHAR Channel)
8345 {
8346
8347 // RF R2 bit 18 = 0
8348 UINT32 R1 = 0, R2 = 0, R3 = 0;
8349 UCHAR index;
8350 RTMP_RF_REGS *RFRegTable;
8351
8352 RFRegTable = RF2850RegTable;
8353
8354 switch (pAd->RfIcType)
8355 {
8356 case RFIC_2820:
8357 case RFIC_2850:
8358 case RFIC_2720:
8359 case RFIC_2750:
8360
8361 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8362 {
8363 if (Channel == RFRegTable[index].Channel)
8364 {
8365 R3 = pAd->LatchRfRegs.R3;
8366 R3 &= 0xfff3ffff;
8367 R3 |= 0x00080000;
8368 RTMP_RF_IO_WRITE32(pAd, R3);
8369
8370 R1 = RFRegTable[index].R1;
8371 RTMP_RF_IO_WRITE32(pAd, R1);
8372
8373 R2 = RFRegTable[index].R2;
8374 if (pAd->Antenna.field.TxPath == 1)
8375 {
8376 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8377 }
8378
8379 if (pAd->Antenna.field.RxPath == 2)
8380 {
8381 R2 |= 0x40; // write 1 to off Rxpath.
8382 }
8383 else if (pAd->Antenna.field.RxPath == 1)
8384 {
8385 R2 |= 0x20040; // write 1 to off RxPath
8386 }
8387 RTMP_RF_IO_WRITE32(pAd, R2);
8388
8389 break;
8390 }
8391 }
8392 break;
8393
8394 default:
8395 break;
8396 }
8397
8398 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
8399 Channel,
8400 pAd->RfIcType,
8401 R2));
8402 }
8403