Staging: rt2870: remove dead DOT11N_DRAFT3 code
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / rt2870 / common / mlme.c
blob54ae2a3adc5d94ef69aca8c71349cf853c8700b5
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
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 *************************************************************************
27 Module Name:
28 mlme.c
30 Abstract:
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
39 #include "../rt_config.h"
40 #include <stdarg.h>
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
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 //
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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 #if 1
252 0x05, 0x20, 20, 15, 30,
253 0x06, 0x20, 21, 8, 20,
254 0x07, 0x20, 22, 8, 20,
255 0x08, 0x20, 23, 8, 25,
256 0x09, 0x22, 23, 8, 25,
257 #else // for RT2860 2*3 test
258 0x05, 0x20, 12, 15, 30,
259 0x06, 0x20, 13, 8, 20,
260 0x07, 0x20, 14, 8, 20,
261 0x08, 0x20, 15, 8, 25,
262 0x09, 0x22, 15, 8, 25,
263 #endif
266 UCHAR RateSwitchTable11BGN2SForABand[] = {
267 // 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)
268 0x0b, 0x09, 0, 0, 0, // Initial used item after association
269 0x00, 0x21, 0, 30,101, //50
270 0x01, 0x21, 1, 20, 50,
271 0x02, 0x21, 2, 20, 50,
272 0x03, 0x21, 3, 15, 50,
273 0x04, 0x21, 4, 15, 30,
274 0x05, 0x21, 5, 15, 30,
275 0x06, 0x20, 12, 15, 30,
276 0x07, 0x20, 13, 8, 20,
277 0x08, 0x20, 14, 8, 20,
278 0x09, 0x20, 15, 8, 25,
279 0x0a, 0x22, 15, 8, 25,
282 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
283 // 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)
284 0x0c, 0x09, 0, 0, 0, // Initial used item after association
285 0x00, 0x21, 0, 30,101, //50
286 0x01, 0x21, 1, 20, 50,
287 0x02, 0x21, 2, 20, 50,
288 0x03, 0x21, 3, 15, 50,
289 0x04, 0x21, 4, 15, 30,
290 0x05, 0x21, 5, 15, 30,
291 0x06, 0x21, 12, 15, 30,
292 0x07, 0x20, 20, 15, 30,
293 0x08, 0x20, 21, 8, 20,
294 0x09, 0x20, 22, 8, 20,
295 0x0a, 0x20, 23, 8, 25,
296 0x0b, 0x22, 23, 8, 25,
298 #endif // DOT11_N_SUPPORT //
300 PUCHAR ReasonString[] = {
301 /* 0 */ "Reserved",
302 /* 1 */ "Unspecified Reason",
303 /* 2 */ "Previous Auth no longer valid",
304 /* 3 */ "STA is leaving / has left",
305 /* 4 */ "DIS-ASSOC due to inactivity",
306 /* 5 */ "AP unable to hanle all associations",
307 /* 6 */ "class 2 error",
308 /* 7 */ "class 3 error",
309 /* 8 */ "STA is leaving / has left",
310 /* 9 */ "require auth before assoc/re-assoc",
311 /* 10 */ "Reserved",
312 /* 11 */ "Reserved",
313 /* 12 */ "Reserved",
314 /* 13 */ "invalid IE",
315 /* 14 */ "MIC error",
316 /* 15 */ "4-way handshake timeout",
317 /* 16 */ "2-way (group key) handshake timeout",
318 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
319 /* 18 */
322 extern UCHAR OfdmRateToRxwiMCS[];
323 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
324 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
325 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
326 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
327 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
329 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
330 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
331 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
333 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
334 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
335 // clean environment.
336 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
337 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
339 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
340 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
342 UCHAR SsidIe = IE_SSID;
343 UCHAR SupRateIe = IE_SUPP_RATES;
344 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
345 #ifdef DOT11_N_SUPPORT
346 UCHAR HtCapIe = IE_HT_CAP;
347 UCHAR AddHtInfoIe = IE_ADD_HT;
348 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
349 #endif // DOT11_N_SUPPORT //
350 UCHAR ErpIe = IE_ERP;
351 UCHAR DsIe = IE_DS_PARM;
352 UCHAR TimIe = IE_TIM;
353 UCHAR WpaIe = IE_WPA;
354 UCHAR Wpa2Ie = IE_WPA2;
355 UCHAR IbssIe = IE_IBSS_PARM;
356 UCHAR Ccx2Ie = IE_CCX_V2;
357 UCHAR WapiIe = IE_WAPI;
359 extern UCHAR WPA_OUI[];
361 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
363 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
364 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
366 // Reset the RFIC setting to new series
367 RTMP_RF_REGS RF2850RegTable[] = {
368 // ch R1 R2 R3(TX0~4=0) R4
369 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
370 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
371 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
372 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
373 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
374 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
375 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
376 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
377 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
378 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
379 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
380 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
381 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
382 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
384 // 802.11 UNI / HyperLan 2
385 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
386 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
387 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
388 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
389 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
390 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
391 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
392 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
393 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
394 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
395 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
396 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
398 // 802.11 HyperLan 2
399 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
401 // 2008.04.30 modified
402 // The system team has AN to improve the EVM value
403 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
404 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
405 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
406 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
408 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
409 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
410 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
411 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
412 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
413 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
414 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
415 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
416 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
417 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
418 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
419 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
421 // 802.11 UNII
422 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
423 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
424 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
425 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
426 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
427 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
428 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
430 // Japan
431 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
432 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
433 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
434 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
435 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
436 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
437 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
439 // still lack of MMAC(Japan) ch 34,38,42,46
441 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
443 FREQUENCY_ITEM FreqItems3020[] =
445 /**************************************************/
446 // ISM : 2.4 to 2.483 GHz //
447 /**************************************************/
448 // 11g
449 /**************************************************/
450 //-CH---N-------R---K-----------
451 {1, 241, 2, 2},
452 {2, 241, 2, 7},
453 {3, 242, 2, 2},
454 {4, 242, 2, 7},
455 {5, 243, 2, 2},
456 {6, 243, 2, 7},
457 {7, 244, 2, 2},
458 {8, 244, 2, 7},
459 {9, 245, 2, 2},
460 {10, 245, 2, 7},
461 {11, 246, 2, 2},
462 {12, 246, 2, 7},
463 {13, 247, 2, 2},
464 {14, 248, 2, 4},
466 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
469 ==========================================================================
470 Description:
471 initialize the MLME task and its data structure (queue, spinlock,
472 timer, state machines).
474 IRQL = PASSIVE_LEVEL
476 Return:
477 always return NDIS_STATUS_SUCCESS
479 ==========================================================================
481 NDIS_STATUS MlmeInit(
482 IN PRTMP_ADAPTER pAd)
484 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
486 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
490 Status = MlmeQueueInit(&pAd->Mlme.Queue);
491 if(Status != NDIS_STATUS_SUCCESS)
492 break;
494 pAd->Mlme.bRunning = FALSE;
495 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
497 #ifdef CONFIG_STA_SUPPORT
498 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
500 BssTableInit(&pAd->ScanTab);
502 // init STA state machines
503 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
504 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
505 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
506 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
507 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
508 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
510 // Since we are using switch/case to implement it, the init is different from the above
511 // state machine init
512 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
514 #endif // CONFIG_STA_SUPPORT //
518 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
520 // Init mlme periodic timer
521 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
523 // Set mlme periodic timer
524 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
526 // software-based RX Antenna diversity
527 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
529 } while (FALSE);
531 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
533 return Status;
537 ==========================================================================
538 Description:
539 main loop of the MLME
540 Pre:
541 Mlme has to be initialized, and there are something inside the queue
542 Note:
543 This function is invoked from MPSetInformation and MPReceive;
544 This task guarantee only one MlmeHandler will run.
546 IRQL = DISPATCH_LEVEL
548 ==========================================================================
550 VOID MlmeHandler(
551 IN PRTMP_ADAPTER pAd)
553 MLME_QUEUE_ELEM *Elem = NULL;
555 // Only accept MLME and Frame from peer side, no other (control/data) frame should
556 // get into this state machine
558 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
559 if(pAd->Mlme.bRunning)
561 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
562 return;
564 else
566 pAd->Mlme.bRunning = TRUE;
568 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
570 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
572 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
573 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
574 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
576 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
577 break;
580 //From message type, determine which state machine I should drive
581 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
583 #ifdef RT2870
584 if (Elem->MsgType == MT2_RESET_CONF)
586 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
587 MlmeRestartStateMachine(pAd);
588 Elem->Occupied = FALSE;
589 Elem->MsgLen = 0;
590 continue;
592 #endif // RT2870 //
594 // if dequeue success
595 switch (Elem->Machine)
597 // STA state machines
598 #ifdef CONFIG_STA_SUPPORT
599 case ASSOC_STATE_MACHINE:
600 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
601 break;
602 case AUTH_STATE_MACHINE:
603 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
604 break;
605 case AUTH_RSP_STATE_MACHINE:
606 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
607 break;
608 case SYNC_STATE_MACHINE:
609 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
610 break;
611 case MLME_CNTL_STATE_MACHINE:
612 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
613 break;
614 case WPA_PSK_STATE_MACHINE:
615 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
616 break;
617 case AIRONET_STATE_MACHINE:
618 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
619 break;
620 #endif // CONFIG_STA_SUPPORT //
622 case ACTION_STATE_MACHINE:
623 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
624 break;
629 default:
630 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
631 break;
632 } // end of switch
634 // free MLME element
635 Elem->Occupied = FALSE;
636 Elem->MsgLen = 0;
639 else {
640 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
644 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
645 pAd->Mlme.bRunning = FALSE;
646 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
650 ==========================================================================
651 Description:
652 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
653 Parameters:
654 Adapter - NIC Adapter pointer
655 Post:
656 The MLME task will no longer work properly
658 IRQL = PASSIVE_LEVEL
660 ==========================================================================
662 VOID MlmeHalt(
663 IN PRTMP_ADAPTER pAd)
665 BOOLEAN Cancelled;
667 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
669 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
671 // disable BEACON generation and other BEACON related hardware timers
672 AsicDisableSync(pAd);
675 #ifdef CONFIG_STA_SUPPORT
676 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
678 // Cancel pending timers
679 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
680 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
681 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
682 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
683 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
684 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
686 #endif // CONFIG_STA_SUPPORT //
688 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
689 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
693 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
695 // Set LED
696 RTMPSetLED(pAd, LED_HALT);
697 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
698 #ifdef RT2870
700 LED_CFG_STRUC LedCfg;
701 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
702 LedCfg.field.LedPolar = 0;
703 LedCfg.field.RLedMode = 0;
704 LedCfg.field.GLedMode = 0;
705 LedCfg.field.YLedMode = 0;
706 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
708 #endif // RT2870 //
711 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
713 MlmeQueueDestroy(&pAd->Mlme.Queue);
714 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
716 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
719 VOID MlmeResetRalinkCounters(
720 IN PRTMP_ADAPTER pAd)
722 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
723 // clear all OneSecxxx counters.
724 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
725 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
726 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
727 pAd->RalinkCounters.OneSecRxOkCnt = 0;
728 pAd->RalinkCounters.OneSecTxFailCount = 0;
729 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
730 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
731 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
733 // TODO: for debug only. to be removed
734 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
735 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
736 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
737 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
738 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
739 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
740 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
741 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
742 pAd->RalinkCounters.OneSecTxDoneCount = 0;
743 pAd->RalinkCounters.OneSecRxCount = 0;
744 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
745 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
747 return;
750 unsigned long rx_AMSDU;
751 unsigned long rx_Total;
754 ==========================================================================
755 Description:
756 This routine is executed periodically to -
757 1. Decide if it's a right time to turn on PwrMgmt bit of all
758 outgoiing frames
759 2. Calculate ChannelQuality based on statistics of the last
760 period, so that TX rate won't toggling very frequently between a
761 successful TX and a failed TX.
762 3. If the calculated ChannelQuality indicated current connection not
763 healthy, then a ROAMing attempt is tried here.
765 IRQL = DISPATCH_LEVEL
767 ==========================================================================
769 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
770 VOID MlmePeriodicExec(
771 IN PVOID SystemSpecific1,
772 IN PVOID FunctionContext,
773 IN PVOID SystemSpecific2,
774 IN PVOID SystemSpecific3)
776 ULONG TxTotalCnt;
777 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
779 // Do nothing if the driver is starting halt state.
780 // This might happen when timer already been fired before cancel timer with mlmehalt
781 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
782 fRTMP_ADAPTER_RADIO_OFF |
783 fRTMP_ADAPTER_RADIO_MEASUREMENT |
784 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
785 return;
787 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
789 #ifdef CONFIG_STA_SUPPORT
790 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
792 // Do nothing if monitor mode is on
793 if (MONITOR_ON(pAd))
794 return;
796 if (pAd->Mlme.PeriodicRound & 0x1)
798 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
799 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
800 (STA_TGN_WIFI_ON(pAd)) &&
801 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
804 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
805 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
807 else if ((STA_TGN_WIFI_ON(pAd)) &&
808 ((pAd->MACVersion & 0xffff) == 0x0101))
810 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
811 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
815 #endif // CONFIG_STA_SUPPORT //
817 pAd->bUpdateBcnCntDone = FALSE;
819 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
820 pAd->Mlme.PeriodicRound ++;
822 // execute every 500ms
823 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
825 #ifdef CONFIG_STA_SUPPORT
826 // perform dynamic tx rate switching based on past TX history
827 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
829 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
831 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
832 MlmeDynamicTxRateSwitching(pAd);
834 #endif // CONFIG_STA_SUPPORT //
837 // Normal 1 second Mlme PeriodicExec.
838 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
840 pAd->Mlme.OneSecPeriodicRound ++;
842 if (rx_Total)
845 // reset counters
846 rx_AMSDU = 0;
847 rx_Total = 0;
850 //ORIBATimerTimeout(pAd);
852 // Media status changed, report to NDIS
853 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
855 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
856 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
858 pAd->IndicateMediaState = NdisMediaStateConnected;
859 RTMP_IndicateMediaState(pAd);
862 else
864 pAd->IndicateMediaState = NdisMediaStateDisconnected;
865 RTMP_IndicateMediaState(pAd);
869 NdisGetSystemUpTime(&pAd->Mlme.Now32);
871 // add the most up-to-date h/w raw counters into software variable, so that
872 // the dynamic tuning mechanism below are based on most up-to-date information
873 NICUpdateRawCounters(pAd);
875 #ifdef RT2870
876 RT2870_WatchDog(pAd);
877 #endif // RT2870 //
879 #ifdef DOT11_N_SUPPORT
880 // Need statistics after read counter. So put after NICUpdateRawCounters
881 ORIBATimerTimeout(pAd);
882 #endif // DOT11_N_SUPPORT //
884 // if MGMT RING is full more than twice within 1 second, we consider there's
885 // a hardware problem stucking the TX path. In this case, try a hardware reset
886 // to recover the system
887 // if (pAd->RalinkCounters.MgmtRingFullCount >= 2)
888 // RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR);
889 // else
890 // pAd->RalinkCounters.MgmtRingFullCount = 0;
892 // The time period for checking antenna is according to traffic
893 if (pAd->Mlme.bEnableAutoAntennaCheck)
895 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
896 pAd->RalinkCounters.OneSecTxRetryOkCount +
897 pAd->RalinkCounters.OneSecTxFailCount;
899 if (TxTotalCnt > 50)
901 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
903 AsicEvaluateRxAnt(pAd);
906 else
908 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
910 AsicEvaluateRxAnt(pAd);
915 #ifdef CONFIG_STA_SUPPORT
916 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
917 STAMlmePeriodicExec(pAd);
918 #endif // CONFIG_STA_SUPPORT //
920 MlmeResetRalinkCounters(pAd);
922 #ifdef CONFIG_STA_SUPPORT
923 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
926 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
927 // and sending CTS-to-self over and over.
928 // Software Patch Solution:
929 // 1. Polling debug state register 0x10F4 every one second.
930 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
931 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
933 UINT32 MacReg = 0;
935 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
936 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
938 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
939 RTMPusecDelay(1);
940 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
942 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
946 #endif // CONFIG_STA_SUPPORT //
948 RT28XX_MLME_HANDLER(pAd);
952 pAd->bUpdateBcnCntDone = FALSE;
955 #ifdef CONFIG_STA_SUPPORT
956 VOID STAMlmePeriodicExec(
957 PRTMP_ADAPTER pAd)
959 ULONG TxTotalCnt;
960 int i;
962 #ifdef WPA_SUPPLICANT_SUPPORT
963 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
964 #endif // WPA_SUPPLICANT_SUPPORT //
966 // WPA MIC error should block association attempt for 60 seconds
967 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
968 pAd->StaCfg.bBlockAssoc = FALSE;
971 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
973 if (pAd->IndicateMediaState == NdisMediaStateConnected)
975 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
977 pAd->PreMediaState = pAd->IndicateMediaState;
983 AsicStaBbpTuning(pAd);
985 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
986 pAd->RalinkCounters.OneSecTxRetryOkCount +
987 pAd->RalinkCounters.OneSecTxFailCount;
989 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
991 // update channel quality for Roaming and UI LinkQuality display
992 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
995 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
996 // Radio is currently in noisy environment
997 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
998 AsicAdjustTxPower(pAd);
1000 if (INFRA_ON(pAd))
1002 // Is PSM bit consistent with user power management policy?
1003 // This is the only place that will set PSM bit ON.
1004 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1005 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1007 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1009 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1010 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1011 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1013 RTMPSetAGCInitValue(pAd, BW_20);
1014 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1017 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1018 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1020 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1022 // When APSD is enabled, the period changes as 20 sec
1023 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1024 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1026 else
1028 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1029 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1031 if (pAd->CommonCfg.bWmmCapable)
1032 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1033 else
1034 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1039 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1041 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1042 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1043 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1045 // Lost AP, send disconnect & link down event
1046 LinkDown(pAd, FALSE);
1048 #ifdef WPA_SUPPLICANT_SUPPORT
1049 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1050 if (pAd->StaCfg.WpaSupplicantUP)
1052 union iwreq_data wrqu;
1053 //send disassociate event to wpa_supplicant
1054 memset(&wrqu, 0, sizeof(wrqu));
1055 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1056 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1058 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1059 #endif // WPA_SUPPLICANT_SUPPORT //
1061 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1063 union iwreq_data wrqu;
1064 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1065 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1067 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1069 // RTMPPatchMacBbpBug(pAd);
1070 MlmeAutoReconnectLastSSID(pAd);
1072 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1074 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1075 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1076 MlmeAutoReconnectLastSSID(pAd);
1079 // Add auto seamless roaming
1080 if (pAd->StaCfg.bFastRoaming)
1082 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1084 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));
1086 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1088 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1092 else if (ADHOC_ON(pAd))
1094 //radar detect
1095 if ((pAd->CommonCfg.Channel > 14)
1096 && (pAd->CommonCfg.bIEEE80211H == 1)
1097 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1099 RadarDetectPeriodic(pAd);
1102 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1103 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1104 // join later.
1105 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1106 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1108 MLME_START_REQ_STRUCT StartReq;
1110 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1111 LinkDown(pAd, FALSE);
1113 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1114 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1115 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1118 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1120 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1122 if (pEntry->ValidAsCLI == FALSE)
1123 continue;
1125 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1126 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1129 else // no INFRA nor ADHOC connection
1132 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1133 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1134 goto SKIP_AUTO_SCAN_CONN;
1135 else
1136 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1138 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1139 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1140 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1142 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1144 MLME_SCAN_REQ_STRUCT ScanReq;
1146 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1148 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1149 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1150 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1151 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1152 // Reset Missed scan number
1153 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1155 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1156 MlmeAutoReconnectLastSSID(pAd);
1158 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1160 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1162 MlmeAutoScan(pAd);
1163 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1165 else
1167 MlmeAutoReconnectLastSSID(pAd);
1173 SKIP_AUTO_SCAN_CONN:
1175 #ifdef DOT11_N_SUPPORT
1176 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1178 pAd->MacTab.fAnyBASession = TRUE;
1179 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1181 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1183 pAd->MacTab.fAnyBASession = FALSE;
1184 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1186 #endif // DOT11_N_SUPPORT //
1188 return;
1191 // Link down report
1192 VOID LinkDownExec(
1193 IN PVOID SystemSpecific1,
1194 IN PVOID FunctionContext,
1195 IN PVOID SystemSpecific2,
1196 IN PVOID SystemSpecific3)
1199 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1201 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1202 RTMP_IndicateMediaState(pAd);
1203 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1206 // IRQL = DISPATCH_LEVEL
1207 VOID MlmeAutoScan(
1208 IN PRTMP_ADAPTER pAd)
1210 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1211 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1213 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1214 MlmeEnqueue(pAd,
1215 MLME_CNTL_STATE_MACHINE,
1216 OID_802_11_BSSID_LIST_SCAN,
1218 NULL);
1219 RT28XX_MLME_HANDLER(pAd);
1223 // IRQL = DISPATCH_LEVEL
1224 VOID MlmeAutoReconnectLastSSID(
1225 IN PRTMP_ADAPTER pAd)
1229 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1230 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1231 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1233 NDIS_802_11_SSID OidSsid;
1234 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1235 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1237 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1238 MlmeEnqueue(pAd,
1239 MLME_CNTL_STATE_MACHINE,
1240 OID_802_11_SSID,
1241 sizeof(NDIS_802_11_SSID),
1242 &OidSsid);
1243 RT28XX_MLME_HANDLER(pAd);
1246 #endif // CONFIG_STA_SUPPORT //
1249 ==========================================================================
1250 Validate SSID for connection try and rescan purpose
1251 Valid SSID will have visible chars only.
1252 The valid length is from 0 to 32.
1253 IRQL = DISPATCH_LEVEL
1254 ==========================================================================
1256 BOOLEAN MlmeValidateSSID(
1257 IN PUCHAR pSsid,
1258 IN UCHAR SsidLen)
1260 int index;
1262 if (SsidLen > MAX_LEN_OF_SSID)
1263 return (FALSE);
1265 // Check each character value
1266 for (index = 0; index < SsidLen; index++)
1268 if (pSsid[index] < 0x20)
1269 return (FALSE);
1272 // All checked
1273 return (TRUE);
1276 VOID MlmeSelectTxRateTable(
1277 IN PRTMP_ADAPTER pAd,
1278 IN PMAC_TABLE_ENTRY pEntry,
1279 IN PUCHAR *ppTable,
1280 IN PUCHAR pTableSize,
1281 IN PUCHAR pInitTxRateIdx)
1285 // decide the rate table for tuning
1286 if (pAd->CommonCfg.TxRateTableSize > 0)
1288 *ppTable = RateSwitchTable;
1289 *pTableSize = RateSwitchTable[0];
1290 *pInitTxRateIdx = RateSwitchTable[1];
1292 break;
1295 #ifdef CONFIG_STA_SUPPORT
1296 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1298 #ifdef DOT11_N_SUPPORT
1299 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1300 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1301 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1302 {// 11N 1S Adhoc
1303 *ppTable = RateSwitchTable11N1S;
1304 *pTableSize = RateSwitchTable11N1S[0];
1305 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1308 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1309 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1310 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1311 (pAd->Antenna.field.TxPath == 2))
1312 {// 11N 2S Adhoc
1313 if (pAd->LatchRfRegs.Channel <= 14)
1315 *ppTable = RateSwitchTable11N2S;
1316 *pTableSize = RateSwitchTable11N2S[0];
1317 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1319 else
1321 *ppTable = RateSwitchTable11N2SForABand;
1322 *pTableSize = RateSwitchTable11N2SForABand[0];
1323 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1327 else
1328 #endif // DOT11_N_SUPPORT //
1329 if ((pEntry->RateLen == 4)
1330 #ifdef DOT11_N_SUPPORT
1331 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1332 #endif // DOT11_N_SUPPORT //
1335 *ppTable = RateSwitchTable11B;
1336 *pTableSize = RateSwitchTable11B[0];
1337 *pInitTxRateIdx = RateSwitchTable11B[1];
1340 else if (pAd->LatchRfRegs.Channel <= 14)
1342 *ppTable = RateSwitchTable11BG;
1343 *pTableSize = RateSwitchTable11BG[0];
1344 *pInitTxRateIdx = RateSwitchTable11BG[1];
1347 else
1349 *ppTable = RateSwitchTable11G;
1350 *pTableSize = RateSwitchTable11G[0];
1351 *pInitTxRateIdx = RateSwitchTable11G[1];
1354 break;
1356 #endif // CONFIG_STA_SUPPORT //
1358 #ifdef DOT11_N_SUPPORT
1359 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1360 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1361 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1362 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1363 {// 11BGN 1S AP
1364 *ppTable = RateSwitchTable11BGN1S;
1365 *pTableSize = RateSwitchTable11BGN1S[0];
1366 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1368 break;
1371 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1372 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1373 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1374 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1375 {// 11BGN 2S AP
1376 if (pAd->LatchRfRegs.Channel <= 14)
1378 *ppTable = RateSwitchTable11BGN2S;
1379 *pTableSize = RateSwitchTable11BGN2S[0];
1380 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1383 else
1385 *ppTable = RateSwitchTable11BGN2SForABand;
1386 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1387 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1390 break;
1393 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1394 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1395 {// 11N 1S AP
1396 *ppTable = RateSwitchTable11N1S;
1397 *pTableSize = RateSwitchTable11N1S[0];
1398 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1400 break;
1403 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1404 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1405 {// 11N 2S AP
1406 if (pAd->LatchRfRegs.Channel <= 14)
1408 *ppTable = RateSwitchTable11N2S;
1409 *pTableSize = RateSwitchTable11N2S[0];
1410 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1412 else
1414 *ppTable = RateSwitchTable11N2SForABand;
1415 *pTableSize = RateSwitchTable11N2SForABand[0];
1416 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1419 break;
1421 #endif // DOT11_N_SUPPORT //
1422 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1423 if ((pEntry->RateLen == 4)
1424 #ifdef DOT11_N_SUPPORT
1425 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1426 #endif // DOT11_N_SUPPORT //
1428 {// B only AP
1429 *ppTable = RateSwitchTable11B;
1430 *pTableSize = RateSwitchTable11B[0];
1431 *pInitTxRateIdx = RateSwitchTable11B[1];
1433 break;
1436 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1437 if ((pEntry->RateLen > 8)
1438 #ifdef DOT11_N_SUPPORT
1439 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1440 #endif // DOT11_N_SUPPORT //
1442 {// B/G mixed AP
1443 *ppTable = RateSwitchTable11BG;
1444 *pTableSize = RateSwitchTable11BG[0];
1445 *pInitTxRateIdx = RateSwitchTable11BG[1];
1447 break;
1450 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1451 if ((pEntry->RateLen == 8)
1452 #ifdef DOT11_N_SUPPORT
1453 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1454 #endif // DOT11_N_SUPPORT //
1456 {// G only AP
1457 *ppTable = RateSwitchTable11G;
1458 *pTableSize = RateSwitchTable11G[0];
1459 *pInitTxRateIdx = RateSwitchTable11G[1];
1461 break;
1463 #ifdef DOT11_N_SUPPORT
1464 #endif // DOT11_N_SUPPORT //
1466 #ifdef CONFIG_STA_SUPPORT
1467 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1469 #ifdef DOT11_N_SUPPORT
1470 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1471 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1472 #endif // DOT11_N_SUPPORT //
1473 { // Legacy mode
1474 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1476 *ppTable = RateSwitchTable11B;
1477 *pTableSize = RateSwitchTable11B[0];
1478 *pInitTxRateIdx = RateSwitchTable11B[1];
1480 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1482 *ppTable = RateSwitchTable11G;
1483 *pTableSize = RateSwitchTable11G[0];
1484 *pInitTxRateIdx = RateSwitchTable11G[1];
1487 else
1489 *ppTable = RateSwitchTable11BG;
1490 *pTableSize = RateSwitchTable11BG[0];
1491 *pInitTxRateIdx = RateSwitchTable11BG[1];
1493 break;
1495 #ifdef DOT11_N_SUPPORT
1496 if (pAd->LatchRfRegs.Channel <= 14)
1498 if (pAd->CommonCfg.TxStream == 1)
1500 *ppTable = RateSwitchTable11N1S;
1501 *pTableSize = RateSwitchTable11N1S[0];
1502 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1503 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1505 else
1507 *ppTable = RateSwitchTable11N2S;
1508 *pTableSize = RateSwitchTable11N2S[0];
1509 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1510 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1513 else
1515 if (pAd->CommonCfg.TxStream == 1)
1517 *ppTable = RateSwitchTable11N1S;
1518 *pTableSize = RateSwitchTable11N1S[0];
1519 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1520 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1522 else
1524 *ppTable = RateSwitchTable11N2SForABand;
1525 *pTableSize = RateSwitchTable11N2SForABand[0];
1526 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1527 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1530 #endif // DOT11_N_SUPPORT //
1531 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1532 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1534 #endif // CONFIG_STA_SUPPORT //
1535 } while(FALSE);
1538 #ifdef CONFIG_STA_SUPPORT
1540 ==========================================================================
1541 Description:
1542 This routine checks if there're other APs out there capable for
1543 roaming. Caller should call this routine only when Link up in INFRA mode
1544 and channel quality is below CQI_GOOD_THRESHOLD.
1546 IRQL = DISPATCH_LEVEL
1548 Output:
1549 ==========================================================================
1551 VOID MlmeCheckForRoaming(
1552 IN PRTMP_ADAPTER pAd,
1553 IN ULONG Now32)
1555 USHORT i;
1556 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1557 BSS_ENTRY *pBss;
1559 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1560 // put all roaming candidates into RoamTab, and sort in RSSI order
1561 BssTableInit(pRoamTab);
1562 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1564 pBss = &pAd->ScanTab.BssEntry[i];
1566 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1567 continue; // AP disappear
1568 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1569 continue; // RSSI too weak. forget it.
1570 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1571 continue; // skip current AP
1572 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1573 continue; // only AP with stronger RSSI is eligible for roaming
1575 // AP passing all above rules is put into roaming candidate table
1576 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1577 pRoamTab->BssNr += 1;
1580 if (pRoamTab->BssNr > 0)
1582 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1583 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1585 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1586 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1587 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1588 RT28XX_MLME_HANDLER(pAd);
1591 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1595 ==========================================================================
1596 Description:
1597 This routine checks if there're other APs out there capable for
1598 roaming. Caller should call this routine only when link up in INFRA mode
1599 and channel quality is below CQI_GOOD_THRESHOLD.
1601 IRQL = DISPATCH_LEVEL
1603 Output:
1604 ==========================================================================
1606 VOID MlmeCheckForFastRoaming(
1607 IN PRTMP_ADAPTER pAd,
1608 IN ULONG Now)
1610 USHORT i;
1611 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1612 BSS_ENTRY *pBss;
1614 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1615 // put all roaming candidates into RoamTab, and sort in RSSI order
1616 BssTableInit(pRoamTab);
1617 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1619 pBss = &pAd->ScanTab.BssEntry[i];
1621 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1622 continue; // RSSI too weak. forget it.
1623 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1624 continue; // skip current AP
1625 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1626 continue; // skip different SSID
1627 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1628 continue; // skip AP without better RSSI
1630 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));
1631 // AP passing all above rules is put into roaming candidate table
1632 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1633 pRoamTab->BssNr += 1;
1636 if (pRoamTab->BssNr > 0)
1638 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1639 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1641 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1642 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1643 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1644 RT28XX_MLME_HANDLER(pAd);
1647 // Maybe site survey required
1648 else
1650 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1652 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1653 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1654 pAd->StaCfg.ScanCnt = 2;
1655 pAd->StaCfg.LastScanTime = Now;
1656 MlmeAutoScan(pAd);
1660 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1664 ==========================================================================
1665 Description:
1666 This routine calculates TxPER, RxPER of the past N-sec period. And
1667 according to the calculation result, ChannelQuality is calculated here
1668 to decide if current AP is still doing the job.
1670 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1671 Output:
1672 StaCfg.ChannelQuality - 0..100
1674 IRQL = DISPATCH_LEVEL
1676 NOTE: This routine decide channle quality based on RX CRC error ratio.
1677 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1678 is performed right before this routine, so that this routine can decide
1679 channel quality based on the most up-to-date information
1680 ==========================================================================
1682 VOID MlmeCalculateChannelQuality(
1683 IN PRTMP_ADAPTER pAd,
1684 IN ULONG Now32)
1686 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1687 ULONG RxCnt, RxPER;
1688 UCHAR NorRssi;
1689 CHAR MaxRssi;
1690 ULONG BeaconLostTime = BEACON_LOST_TIME;
1692 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1695 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1697 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1698 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1699 if (TxCnt < 5)
1701 TxPER = 0;
1702 TxPRR = 0;
1704 else
1706 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1707 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1711 // calculate RX PER - don't take RxPER into consideration if too few sample
1713 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1714 if (RxCnt < 5)
1715 RxPER = 0;
1716 else
1717 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1720 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1722 if (INFRA_ON(pAd) &&
1723 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1724 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1726 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1727 pAd->Mlme.ChannelQuality = 0;
1729 else
1731 // Normalize Rssi
1732 if (MaxRssi > -40)
1733 NorRssi = 100;
1734 else if (MaxRssi < -90)
1735 NorRssi = 0;
1736 else
1737 NorRssi = (MaxRssi + 90) * 2;
1739 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1740 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1741 TX_WEIGHTING * (100 - TxPRR) +
1742 RX_WEIGHTING* (100 - RxPER)) / 100;
1743 if (pAd->Mlme.ChannelQuality >= 100)
1744 pAd->Mlme.ChannelQuality = 100;
1749 VOID MlmeSetTxRate(
1750 IN PRTMP_ADAPTER pAd,
1751 IN PMAC_TABLE_ENTRY pEntry,
1752 IN PRTMP_TX_RATE_SWITCH pTxRate)
1754 UCHAR MaxMode = MODE_OFDM;
1756 #ifdef DOT11_N_SUPPORT
1757 MaxMode = MODE_HTGREENFIELD;
1759 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1760 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1761 else
1762 #endif // DOT11_N_SUPPORT //
1763 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1765 if (pTxRate->CurrMCS < MCS_AUTO)
1766 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1768 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1769 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1771 if (ADHOC_ON(pAd))
1773 // If peer adhoc is b-only mode, we can't send 11g rate.
1774 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1775 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1778 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1780 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1781 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1782 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1784 // Patch speed error in status page
1785 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1787 else
1789 if (pTxRate->Mode <= MaxMode)
1790 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1792 #ifdef DOT11_N_SUPPORT
1793 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1794 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1795 else
1796 #endif // DOT11_N_SUPPORT //
1797 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1799 #ifdef DOT11_N_SUPPORT
1800 // Reexam each bandwidth's SGI support.
1801 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1803 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1804 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1805 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1806 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1809 // Turn RTS/CTS rate to 6Mbps.
1810 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1812 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1813 if (pAd->MacTab.fAnyBASession)
1815 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1817 else
1819 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1822 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1824 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1825 if (pAd->MacTab.fAnyBASession)
1827 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1829 else
1831 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1834 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1836 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1839 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1841 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1843 #endif // DOT11_N_SUPPORT //
1845 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1846 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1847 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1848 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1849 #ifdef DOT11_N_SUPPORT
1850 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1851 pAd->WIFItestbed.bGreenField)
1852 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1853 #endif // DOT11_N_SUPPORT //
1856 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1860 ==========================================================================
1861 Description:
1862 This routine calculates the acumulated TxPER of eaxh TxRate. And
1863 according to the calculation result, change CommonCfg.TxRate which
1864 is the stable TX Rate we expect the Radio situation could sustained.
1866 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1867 Output:
1868 CommonCfg.TxRate -
1870 IRQL = DISPATCH_LEVEL
1872 NOTE:
1873 call this routine every second
1874 ==========================================================================
1876 VOID MlmeDynamicTxRateSwitching(
1877 IN PRTMP_ADAPTER pAd)
1879 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1880 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1881 ULONG TxErrorRatio = 0;
1882 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1883 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1884 PUCHAR pTable;
1885 UCHAR TableSize = 0;
1886 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1887 CHAR Rssi, RssiOffset = 0;
1888 TX_STA_CNT1_STRUC StaTx1;
1889 TX_STA_CNT0_STRUC TxStaCnt0;
1890 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1891 MAC_TABLE_ENTRY *pEntry;
1894 // walk through MAC table, see if need to change AP's TX rate toward each entry
1896 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1898 pEntry = &pAd->MacTab.Content[i];
1900 // check if this entry need to switch rate automatically
1901 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1902 continue;
1904 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1906 Rssi = RTMPMaxRssi(pAd,
1907 pAd->StaCfg.RssiSample.AvgRssi0,
1908 pAd->StaCfg.RssiSample.AvgRssi1,
1909 pAd->StaCfg.RssiSample.AvgRssi2);
1911 // Update statistic counter
1912 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1913 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1914 pAd->bUpdateBcnCntDone = TRUE;
1915 TxRetransmit = StaTx1.field.TxRetransmit;
1916 TxSuccess = StaTx1.field.TxSuccess;
1917 TxFailCount = TxStaCnt0.field.TxFailCount;
1918 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1920 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1921 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1922 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1923 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1924 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1925 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1927 // if no traffic in the past 1-sec period, don't change TX rate,
1928 // but clear all bad history. because the bad history may affect the next
1929 // Chariot throughput test
1930 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1931 pAd->RalinkCounters.OneSecTxRetryOkCount +
1932 pAd->RalinkCounters.OneSecTxFailCount;
1934 if (TxTotalCnt)
1935 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1937 else
1939 if (INFRA_ON(pAd) && (i == 1))
1940 Rssi = RTMPMaxRssi(pAd,
1941 pAd->StaCfg.RssiSample.AvgRssi0,
1942 pAd->StaCfg.RssiSample.AvgRssi1,
1943 pAd->StaCfg.RssiSample.AvgRssi2);
1944 else
1945 Rssi = RTMPMaxRssi(pAd,
1946 pEntry->RssiSample.AvgRssi0,
1947 pEntry->RssiSample.AvgRssi1,
1948 pEntry->RssiSample.AvgRssi2);
1950 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1951 pEntry->OneSecTxRetryOkCount +
1952 pEntry->OneSecTxFailCount;
1954 if (TxTotalCnt)
1955 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1958 CurrRateIdx = pEntry->CurrTxRateIndex;
1960 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1962 if (CurrRateIdx >= TableSize)
1964 CurrRateIdx = TableSize - 1;
1967 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
1968 // So need to sync here.
1969 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1970 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1971 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1975 // Need to sync Real Tx rate and our record.
1976 // Then return for next DRS.
1977 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
1978 pEntry->CurrTxRateIndex = InitTxRateIdx;
1979 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1981 // reset all OneSecTx counters
1982 RESET_ONE_SEC_TX_CNT(pEntry);
1983 continue;
1986 // decide the next upgrade rate and downgrade rate, if any
1987 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
1989 UpRateIdx = CurrRateIdx + 1;
1990 DownRateIdx = CurrRateIdx -1;
1992 else if (CurrRateIdx == 0)
1994 UpRateIdx = CurrRateIdx + 1;
1995 DownRateIdx = CurrRateIdx;
1997 else if (CurrRateIdx == (TableSize - 1))
1999 UpRateIdx = CurrRateIdx;
2000 DownRateIdx = CurrRateIdx - 1;
2003 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2005 #ifdef DOT11_N_SUPPORT
2006 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2008 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2009 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2011 else
2012 #endif // DOT11_N_SUPPORT //
2014 TrainUp = pCurrTxRate->TrainUp;
2015 TrainDown = pCurrTxRate->TrainDown;
2018 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2021 // Keep the last time TxRateChangeAction status.
2023 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2028 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2029 // (criteria copied from RT2500 for Netopia case)
2031 if (TxTotalCnt <= 15)
2033 CHAR idx = 0;
2034 UCHAR TxRateIdx;
2035 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2036 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2037 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2038 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2040 // check the existence and index of each needed MCS
2041 while (idx < pTable[0])
2043 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2045 if (pCurrTxRate->CurrMCS == MCS_0)
2047 MCS0 = idx;
2049 else if (pCurrTxRate->CurrMCS == MCS_1)
2051 MCS1 = idx;
2053 else if (pCurrTxRate->CurrMCS == MCS_2)
2055 MCS2 = idx;
2057 else if (pCurrTxRate->CurrMCS == MCS_3)
2059 MCS3 = idx;
2061 else if (pCurrTxRate->CurrMCS == MCS_4)
2063 MCS4 = idx;
2065 else if (pCurrTxRate->CurrMCS == MCS_5)
2067 MCS5 = idx;
2069 else if (pCurrTxRate->CurrMCS == MCS_6)
2071 MCS6 = idx;
2073 //else if (pCurrTxRate->CurrMCS == MCS_7)
2074 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2076 MCS7 = idx;
2078 else if (pCurrTxRate->CurrMCS == MCS_12)
2080 MCS12 = idx;
2082 else if (pCurrTxRate->CurrMCS == MCS_13)
2084 MCS13 = idx;
2086 else if (pCurrTxRate->CurrMCS == MCS_14)
2088 MCS14 = idx;
2090 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2091 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
2093 MCS15 = idx;
2095 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2097 MCS20 = idx;
2099 else if (pCurrTxRate->CurrMCS == MCS_21)
2101 MCS21 = idx;
2103 else if (pCurrTxRate->CurrMCS == MCS_22)
2105 MCS22 = idx;
2107 else if (pCurrTxRate->CurrMCS == MCS_23)
2109 MCS23 = idx;
2111 idx ++;
2114 if (pAd->LatchRfRegs.Channel <= 14)
2116 if (pAd->NicConfig2.field.ExternalLNAForG)
2118 RssiOffset = 2;
2120 else
2122 RssiOffset = 5;
2125 else
2127 if (pAd->NicConfig2.field.ExternalLNAForA)
2129 RssiOffset = 5;
2131 else
2133 RssiOffset = 8;
2136 #ifdef DOT11_N_SUPPORT
2137 /*if (MCS15)*/
2138 if ((pTable == RateSwitchTable11BGN3S) ||
2139 (pTable == RateSwitchTable11N3S) ||
2140 (pTable == RateSwitchTable))
2141 {// N mode with 3 stream // 3*3
2142 if (MCS23 && (Rssi >= -70))
2143 TxRateIdx = MCS15;
2144 else if (MCS22 && (Rssi >= -72))
2145 TxRateIdx = MCS14;
2146 else if (MCS21 && (Rssi >= -76))
2147 TxRateIdx = MCS13;
2148 else if (MCS20 && (Rssi >= -78))
2149 TxRateIdx = MCS12;
2150 else if (MCS4 && (Rssi >= -82))
2151 TxRateIdx = MCS4;
2152 else if (MCS3 && (Rssi >= -84))
2153 TxRateIdx = MCS3;
2154 else if (MCS2 && (Rssi >= -86))
2155 TxRateIdx = MCS2;
2156 else if (MCS1 && (Rssi >= -88))
2157 TxRateIdx = MCS1;
2158 else
2159 TxRateIdx = MCS0;
2161 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2162 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2163 {// N mode with 2 stream
2164 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2165 TxRateIdx = MCS15;
2166 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2167 TxRateIdx = MCS14;
2168 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2169 TxRateIdx = MCS13;
2170 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2171 TxRateIdx = MCS12;
2172 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2173 TxRateIdx = MCS4;
2174 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2175 TxRateIdx = MCS3;
2176 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2177 TxRateIdx = MCS2;
2178 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2179 TxRateIdx = MCS1;
2180 else
2181 TxRateIdx = MCS0;
2183 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2184 {// N mode with 1 stream
2185 if (MCS7 && (Rssi > (-72+RssiOffset)))
2186 TxRateIdx = MCS7;
2187 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2188 TxRateIdx = MCS6;
2189 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2190 TxRateIdx = MCS5;
2191 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2192 TxRateIdx = MCS4;
2193 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2194 TxRateIdx = MCS3;
2195 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2196 TxRateIdx = MCS2;
2197 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2198 TxRateIdx = MCS1;
2199 else
2200 TxRateIdx = MCS0;
2202 else
2203 #endif // DOT11_N_SUPPORT //
2204 {// Legacy mode
2205 if (MCS7 && (Rssi > -70))
2206 TxRateIdx = MCS7;
2207 else if (MCS6 && (Rssi > -74))
2208 TxRateIdx = MCS6;
2209 else if (MCS5 && (Rssi > -78))
2210 TxRateIdx = MCS5;
2211 else if (MCS4 && (Rssi > -82))
2212 TxRateIdx = MCS4;
2213 else if (MCS4 == 0) // for B-only mode
2214 TxRateIdx = MCS3;
2215 else if (MCS3 && (Rssi > -85))
2216 TxRateIdx = MCS3;
2217 else if (MCS2 && (Rssi > -87))
2218 TxRateIdx = MCS2;
2219 else if (MCS1 && (Rssi > -90))
2220 TxRateIdx = MCS1;
2221 else
2222 TxRateIdx = MCS0;
2225 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2227 pEntry->CurrTxRateIndex = TxRateIdx;
2228 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2229 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2232 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2233 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2234 pEntry->fLastSecAccordingRSSI = TRUE;
2235 // reset all OneSecTx counters
2236 RESET_ONE_SEC_TX_CNT(pEntry);
2238 continue;
2241 if (pEntry->fLastSecAccordingRSSI == TRUE)
2243 pEntry->fLastSecAccordingRSSI = FALSE;
2244 pEntry->LastSecTxRateChangeAction = 0;
2245 // reset all OneSecTx counters
2246 RESET_ONE_SEC_TX_CNT(pEntry);
2248 continue;
2253 BOOLEAN bTrainUpDown = FALSE;
2255 pEntry->CurrTxRateStableTime ++;
2257 // downgrade TX quality if PER >= Rate-Down threshold
2258 if (TxErrorRatio >= TrainDown)
2260 bTrainUpDown = TRUE;
2261 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2263 // upgrade TX quality if PER <= Rate-Up threshold
2264 else if (TxErrorRatio <= TrainUp)
2266 bTrainUpDown = TRUE;
2267 bUpgradeQuality = TRUE;
2268 if (pEntry->TxQuality[CurrRateIdx])
2269 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2271 if (pEntry->TxRateUpPenalty)
2272 pEntry->TxRateUpPenalty --;
2273 else if (pEntry->TxQuality[UpRateIdx])
2274 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2277 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2279 if (bTrainUpDown)
2281 // perform DRS - consider TxRate Down first, then rate up.
2282 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2284 pEntry->CurrTxRateIndex = DownRateIdx;
2286 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2288 pEntry->CurrTxRateIndex = UpRateIdx;
2291 } while (FALSE);
2293 // if rate-up happen, clear all bad history of all TX rates
2294 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2296 pEntry->CurrTxRateStableTime = 0;
2297 pEntry->TxRateUpPenalty = 0;
2298 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2299 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2300 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2303 // For TxRate fast train up
2305 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2307 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2309 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2311 bTxRateChanged = TRUE;
2313 // if rate-down happen, only clear DownRate's bad history
2314 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2316 pEntry->CurrTxRateStableTime = 0;
2317 pEntry->TxRateUpPenalty = 0; // no penalty
2318 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2319 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2320 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2323 // For TxRate fast train down
2325 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2327 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2329 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2331 bTxRateChanged = TRUE;
2333 else
2335 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2336 bTxRateChanged = FALSE;
2339 pEntry->LastTxOkCount = TxSuccess;
2341 // reset all OneSecTx counters
2342 RESET_ONE_SEC_TX_CNT(pEntry);
2344 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2345 if (bTxRateChanged && pNextTxRate)
2347 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2353 ========================================================================
2354 Routine Description:
2355 Station side, Auto TxRate faster train up timer call back function.
2357 Arguments:
2358 SystemSpecific1 - Not used.
2359 FunctionContext - Pointer to our Adapter context.
2360 SystemSpecific2 - Not used.
2361 SystemSpecific3 - Not used.
2363 Return Value:
2364 None
2366 ========================================================================
2368 VOID StaQuickResponeForRateUpExec(
2369 IN PVOID SystemSpecific1,
2370 IN PVOID FunctionContext,
2371 IN PVOID SystemSpecific2,
2372 IN PVOID SystemSpecific3)
2374 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2375 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2376 ULONG TxTotalCnt;
2377 ULONG TxErrorRatio = 0;
2378 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2379 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2380 PUCHAR pTable;
2381 UCHAR TableSize = 0;
2382 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2383 TX_STA_CNT1_STRUC StaTx1;
2384 TX_STA_CNT0_STRUC TxStaCnt0;
2385 CHAR Rssi, ratio;
2386 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2387 MAC_TABLE_ENTRY *pEntry;
2388 ULONG i;
2390 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2393 // walk through MAC table, see if need to change AP's TX rate toward each entry
2395 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2397 pEntry = &pAd->MacTab.Content[i];
2399 // check if this entry need to switch rate automatically
2400 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2401 continue;
2403 if (INFRA_ON(pAd) && (i == 1))
2404 Rssi = RTMPMaxRssi(pAd,
2405 pAd->StaCfg.RssiSample.AvgRssi0,
2406 pAd->StaCfg.RssiSample.AvgRssi1,
2407 pAd->StaCfg.RssiSample.AvgRssi2);
2408 else
2409 Rssi = RTMPMaxRssi(pAd,
2410 pEntry->RssiSample.AvgRssi0,
2411 pEntry->RssiSample.AvgRssi1,
2412 pEntry->RssiSample.AvgRssi2);
2414 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2416 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2418 // decide the next upgrade rate and downgrade rate, if any
2419 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2421 UpRateIdx = CurrRateIdx + 1;
2422 DownRateIdx = CurrRateIdx -1;
2424 else if (CurrRateIdx == 0)
2426 UpRateIdx = CurrRateIdx + 1;
2427 DownRateIdx = CurrRateIdx;
2429 else if (CurrRateIdx == (TableSize - 1))
2431 UpRateIdx = CurrRateIdx;
2432 DownRateIdx = CurrRateIdx - 1;
2435 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2437 #ifdef DOT11_N_SUPPORT
2438 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2440 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2441 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2443 else
2444 #endif // DOT11_N_SUPPORT //
2446 TrainUp = pCurrTxRate->TrainUp;
2447 TrainDown = pCurrTxRate->TrainDown;
2450 if (pAd->MacTab.Size == 1)
2452 // Update statistic counter
2453 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2454 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2456 TxRetransmit = StaTx1.field.TxRetransmit;
2457 TxSuccess = StaTx1.field.TxSuccess;
2458 TxFailCount = TxStaCnt0.field.TxFailCount;
2459 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2461 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2462 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2463 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2464 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2465 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2466 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2468 #if 0 // test by Gary.
2469 // if no traffic in the past 1-sec period, don't change TX rate,
2470 // but clear all bad history. because the bad history may affect the next
2471 // Chariot throughput test
2472 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2473 pAd->RalinkCounters.OneSecTxRetryOkCount +
2474 pAd->RalinkCounters.OneSecTxFailCount;
2475 #endif
2476 if (TxTotalCnt)
2477 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2479 else
2481 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2482 pEntry->OneSecTxRetryOkCount +
2483 pEntry->OneSecTxFailCount;
2485 if (TxTotalCnt)
2486 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2491 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2492 // (criteria copied from RT2500 for Netopia case)
2494 if (TxTotalCnt <= 12)
2496 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2497 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2499 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2501 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2502 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2504 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2506 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2509 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2510 return;
2515 ULONG OneSecTxNoRetryOKRationCount;
2517 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2518 ratio = 5;
2519 else
2520 ratio = 4;
2522 // downgrade TX quality if PER >= Rate-Down threshold
2523 if (TxErrorRatio >= TrainDown)
2525 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2528 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2530 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2532 // perform DRS - consider TxRate Down first, then rate up.
2533 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2535 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2537 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2538 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2543 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2545 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2549 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2551 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2554 }while (FALSE);
2556 // if rate-up happen, clear all bad history of all TX rates
2557 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2559 pAd->DrsCounters.TxRateUpPenalty = 0;
2560 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2561 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2562 bTxRateChanged = TRUE;
2564 // if rate-down happen, only clear DownRate's bad history
2565 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2567 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2569 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2570 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2571 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2572 bTxRateChanged = TRUE;
2574 else
2576 bTxRateChanged = FALSE;
2579 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2580 if (bTxRateChanged && pNextTxRate)
2582 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2588 ==========================================================================
2589 Description:
2590 This routine is executed periodically inside MlmePeriodicExec() after
2591 association with an AP.
2592 It checks if StaCfg.Psm is consistent with user policy (recorded in
2593 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2594 there're some conditions to consider:
2595 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2596 the time when Mibss==TRUE
2597 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2598 if outgoing traffic available in TxRing or MgmtRing.
2599 Output:
2600 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2602 IRQL = DISPATCH_LEVEL
2604 ==========================================================================
2606 VOID MlmeCheckPsmChange(
2607 IN PRTMP_ADAPTER pAd,
2608 IN ULONG Now32)
2610 ULONG PowerMode;
2612 // condition -
2613 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2614 // 2. user wants either MAX_PSP or FAST_PSP
2615 // 3. but current psm is not in PWR_SAVE
2616 // 4. CNTL state machine is not doing SCANning
2617 // 5. no TX SUCCESS event for the past 1-sec period
2618 #ifdef NDIS51_MINIPORT
2619 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2620 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2621 else
2622 #endif
2623 PowerMode = pAd->StaCfg.WindowsPowerMode;
2625 if (INFRA_ON(pAd) &&
2626 (PowerMode != Ndis802_11PowerModeCAM) &&
2627 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2628 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2629 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2630 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2631 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2633 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2634 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2635 MlmeSetPsmBit(pAd, PWR_SAVE);
2636 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2638 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2640 else
2642 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2647 // IRQL = PASSIVE_LEVEL
2648 // IRQL = DISPATCH_LEVEL
2649 VOID MlmeSetPsmBit(
2650 IN PRTMP_ADAPTER pAd,
2651 IN USHORT psm)
2653 AUTO_RSP_CFG_STRUC csr4;
2655 pAd->StaCfg.Psm = psm;
2656 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2657 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2658 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2659 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2661 #endif // CONFIG_STA_SUPPORT //
2664 // IRQL = DISPATCH_LEVEL
2665 VOID MlmeSetTxPreamble(
2666 IN PRTMP_ADAPTER pAd,
2667 IN USHORT TxPreamble)
2669 AUTO_RSP_CFG_STRUC csr4;
2672 // Always use Long preamble before verifiation short preamble functionality works well.
2673 // Todo: remove the following line if short preamble functionality works
2675 //TxPreamble = Rt802_11PreambleLong;
2677 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2678 if (TxPreamble == Rt802_11PreambleLong)
2680 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2681 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2682 csr4.field.AutoResponderPreamble = 0;
2684 else
2686 // NOTE: 1Mbps should always use long preamble
2687 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2688 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2689 csr4.field.AutoResponderPreamble = 1;
2692 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2696 ==========================================================================
2697 Description:
2698 Update basic rate bitmap
2699 ==========================================================================
2702 VOID UpdateBasicRateBitmap(
2703 IN PRTMP_ADAPTER pAdapter)
2705 INT i, j;
2706 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2707 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2708 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2709 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2710 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2713 /* if A mode, always use fix BasicRateBitMap */
2714 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2715 if (pAdapter->CommonCfg.Channel > 14)
2716 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2717 /* End of if */
2719 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2721 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2722 return;
2723 } /* End of if */
2725 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2727 sup_p[i] &= 0x7f;
2728 ext_p[i] &= 0x7f;
2729 } /* End of for */
2731 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2733 if (bitmap & (1 << i))
2735 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2737 if (sup_p[j] == rate[i])
2738 sup_p[j] |= 0x80;
2739 /* End of if */
2740 } /* End of for */
2742 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2744 if (ext_p[j] == rate[i])
2745 ext_p[j] |= 0x80;
2746 /* End of if */
2747 } /* End of for */
2748 } /* End of if */
2749 } /* End of for */
2750 } /* End of UpdateBasicRateBitmap */
2752 // IRQL = PASSIVE_LEVEL
2753 // IRQL = DISPATCH_LEVEL
2754 // bLinkUp is to identify the inital link speed.
2755 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2756 VOID MlmeUpdateTxRates(
2757 IN PRTMP_ADAPTER pAd,
2758 IN BOOLEAN bLinkUp,
2759 IN UCHAR apidx)
2761 int i, num;
2762 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2763 UCHAR MinSupport = RATE_54;
2764 ULONG BasicRateBitmap = 0;
2765 UCHAR CurrBasicRate = RATE_1;
2766 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2767 PHTTRANSMIT_SETTING pHtPhy = NULL;
2768 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2769 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2770 BOOLEAN *auto_rate_cur_p;
2771 UCHAR HtMcs = MCS_AUTO;
2773 // find max desired rate
2774 UpdateBasicRateBitmap(pAd);
2776 num = 0;
2777 auto_rate_cur_p = NULL;
2778 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2780 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2782 case 2: Rate = RATE_1; num++; break;
2783 case 4: Rate = RATE_2; num++; break;
2784 case 11: Rate = RATE_5_5; num++; break;
2785 case 22: Rate = RATE_11; num++; break;
2786 case 12: Rate = RATE_6; num++; break;
2787 case 18: Rate = RATE_9; num++; break;
2788 case 24: Rate = RATE_12; num++; break;
2789 case 36: Rate = RATE_18; num++; break;
2790 case 48: Rate = RATE_24; num++; break;
2791 case 72: Rate = RATE_36; num++; break;
2792 case 96: Rate = RATE_48; num++; break;
2793 case 108: Rate = RATE_54; num++; break;
2794 //default: Rate = RATE_1; break;
2796 if (MaxDesire < Rate) MaxDesire = Rate;
2799 //===========================================================================
2800 //===========================================================================
2802 #ifdef CONFIG_STA_SUPPORT
2803 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2805 pHtPhy = &pAd->StaCfg.HTPhyMode;
2806 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2807 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2809 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2810 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2812 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2813 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2814 (MaxDesire > RATE_11))
2816 MaxDesire = RATE_11;
2819 #endif // CONFIG_STA_SUPPORT //
2821 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2822 pMinHtPhy->word = 0;
2823 pMaxHtPhy->word = 0;
2824 pHtPhy->word = 0;
2826 // Auto rate switching is enabled only if more than one DESIRED RATES are
2827 // specified; otherwise disabled
2828 if (num <= 1)
2830 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2831 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2832 *auto_rate_cur_p = FALSE;
2834 else
2836 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2837 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2838 *auto_rate_cur_p = TRUE;
2841 #if 1
2842 if (HtMcs != MCS_AUTO)
2844 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2845 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2846 *auto_rate_cur_p = FALSE;
2848 else
2850 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2851 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2852 *auto_rate_cur_p = TRUE;
2854 #endif
2856 #ifdef CONFIG_STA_SUPPORT
2857 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2859 pSupRate = &pAd->StaActive.SupRate[0];
2860 pExtRate = &pAd->StaActive.ExtRate[0];
2861 SupRateLen = pAd->StaActive.SupRateLen;
2862 ExtRateLen = pAd->StaActive.ExtRateLen;
2864 else
2865 #endif // CONFIG_STA_SUPPORT //
2867 pSupRate = &pAd->CommonCfg.SupRate[0];
2868 pExtRate = &pAd->CommonCfg.ExtRate[0];
2869 SupRateLen = pAd->CommonCfg.SupRateLen;
2870 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2873 // find max supported rate
2874 for (i=0; i<SupRateLen; i++)
2876 switch (pSupRate[i] & 0x7f)
2878 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2879 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2880 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2881 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2882 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2883 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2884 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2885 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2886 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2887 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2888 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2889 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2890 default: Rate = RATE_1; break;
2892 if (MaxSupport < Rate) MaxSupport = Rate;
2894 if (MinSupport > Rate) MinSupport = Rate;
2897 for (i=0; i<ExtRateLen; i++)
2899 switch (pExtRate[i] & 0x7f)
2901 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2902 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2903 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2904 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2905 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2906 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2907 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2908 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2909 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2910 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2911 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2912 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2913 default: Rate = RATE_1; break;
2915 if (MaxSupport < Rate) MaxSupport = Rate;
2917 if (MinSupport > Rate) MinSupport = Rate;
2920 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2922 // bug fix
2923 // pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap;
2925 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2926 // the DURATION field of outgoing uniicast DATA/MGMT frame
2927 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2929 if (BasicRateBitmap & (0x01 << i))
2930 CurrBasicRate = (UCHAR)i;
2931 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2934 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2935 // max tx rate = min {max desire rate, max supported rate}
2936 if (MaxSupport < MaxDesire)
2937 pAd->CommonCfg.MaxTxRate = MaxSupport;
2938 else
2939 pAd->CommonCfg.MaxTxRate = MaxDesire;
2941 pAd->CommonCfg.MinTxRate = MinSupport;
2942 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
2943 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
2944 // on average RSSI
2945 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
2946 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
2947 // 3. -75 > RSSI, start at 11 Mbps (long distance)
2948 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
2949 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
2950 if (*auto_rate_cur_p)
2952 short dbm = 0;
2953 #ifdef CONFIG_STA_SUPPORT
2954 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2955 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2956 #endif // CONFIG_STA_SUPPORT //
2957 if (bLinkUp == TRUE)
2958 pAd->CommonCfg.TxRate = RATE_24;
2959 else
2960 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2962 if (dbm < -75)
2963 pAd->CommonCfg.TxRate = RATE_11;
2964 else if (dbm < -70)
2965 pAd->CommonCfg.TxRate = RATE_24;
2967 // should never exceed MaxTxRate (consider 11B-only mode)
2968 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2969 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2971 pAd->CommonCfg.TxRateIndex = 0;
2973 else
2975 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2976 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
2977 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
2979 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
2980 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
2981 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
2982 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
2985 if (pAd->CommonCfg.TxRate <= RATE_11)
2987 pMaxHtPhy->field.MODE = MODE_CCK;
2988 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
2989 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
2991 else
2993 pMaxHtPhy->field.MODE = MODE_OFDM;
2994 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
2995 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
2996 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
2997 else
2998 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3001 pHtPhy->word = (pMaxHtPhy->word);
3002 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3004 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3005 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3006 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3008 else
3010 switch (pAd->CommonCfg.PhyMode)
3012 case PHY_11BG_MIXED:
3013 case PHY_11B:
3014 #ifdef DOT11_N_SUPPORT
3015 case PHY_11BGN_MIXED:
3016 #endif // DOT11_N_SUPPORT //
3017 pAd->CommonCfg.MlmeRate = RATE_1;
3018 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3019 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3021 //#ifdef WIFI_TEST
3022 pAd->CommonCfg.RtsRate = RATE_11;
3023 //#else
3024 // pAd->CommonCfg.RtsRate = RATE_1;
3025 //#endif
3026 break;
3027 case PHY_11G:
3028 case PHY_11A:
3029 #ifdef DOT11_N_SUPPORT
3030 case PHY_11AGN_MIXED:
3031 case PHY_11GN_MIXED:
3032 case PHY_11N_2_4G:
3033 case PHY_11AN_MIXED:
3034 case PHY_11N_5G:
3035 #endif // DOT11_N_SUPPORT //
3036 pAd->CommonCfg.MlmeRate = RATE_6;
3037 pAd->CommonCfg.RtsRate = RATE_6;
3038 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3039 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3040 break;
3041 case PHY_11ABG_MIXED:
3042 #ifdef DOT11_N_SUPPORT
3043 case PHY_11ABGN_MIXED:
3044 #endif // DOT11_N_SUPPORT //
3045 if (pAd->CommonCfg.Channel <= 14)
3047 pAd->CommonCfg.MlmeRate = RATE_1;
3048 pAd->CommonCfg.RtsRate = RATE_1;
3049 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3050 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3052 else
3054 pAd->CommonCfg.MlmeRate = RATE_6;
3055 pAd->CommonCfg.RtsRate = RATE_6;
3056 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3057 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3059 break;
3060 default: // error
3061 pAd->CommonCfg.MlmeRate = RATE_6;
3062 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3063 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3064 pAd->CommonCfg.RtsRate = RATE_1;
3065 break;
3068 // Keep Basic Mlme Rate.
3070 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3071 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3072 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3073 else
3074 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3075 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3078 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3079 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3080 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3081 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3082 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3083 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3084 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 ));
3087 #ifdef DOT11_N_SUPPORT
3089 ==========================================================================
3090 Description:
3091 This function update HT Rate setting.
3092 Input Wcid value is valid for 2 case :
3093 1. it's used for Station in infra mode that copy AP rate to Mactable.
3094 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3096 IRQL = DISPATCH_LEVEL
3098 ==========================================================================
3100 VOID MlmeUpdateHtTxRates(
3101 IN PRTMP_ADAPTER pAd,
3102 IN UCHAR apidx)
3104 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3105 CHAR i; // 3*3
3106 RT_HT_CAPABILITY *pRtHtCap = NULL;
3107 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3108 ULONG BasicMCS;
3109 UCHAR j, bitmask;
3110 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3111 PHTTRANSMIT_SETTING pHtPhy = NULL;
3112 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3113 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3114 BOOLEAN *auto_rate_cur_p;
3116 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3118 auto_rate_cur_p = NULL;
3120 #ifdef CONFIG_STA_SUPPORT
3121 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3123 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3124 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3125 pHtPhy = &pAd->StaCfg.HTPhyMode;
3126 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3127 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3129 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3131 #endif // CONFIG_STA_SUPPORT //
3133 #ifdef CONFIG_STA_SUPPORT
3134 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3136 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3137 return;
3139 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3140 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3141 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3142 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3143 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3144 pMaxHtPhy->field.STBC = STBC_USE;
3145 else
3146 pMaxHtPhy->field.STBC = STBC_NONE;
3148 else
3149 #endif // CONFIG_STA_SUPPORT //
3151 if (pDesireHtPhy->bHtEnable == FALSE)
3152 return;
3154 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3155 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3156 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3157 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3158 pMaxHtPhy->field.STBC = STBC_USE;
3159 else
3160 pMaxHtPhy->field.STBC = STBC_NONE;
3163 // Decide MAX ht rate.
3164 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3165 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3166 else
3167 pMaxHtPhy->field.MODE = MODE_HTMIX;
3169 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3170 pMaxHtPhy->field.BW = BW_40;
3171 else
3172 pMaxHtPhy->field.BW = BW_20;
3174 if (pMaxHtPhy->field.BW == BW_20)
3175 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3176 else
3177 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3179 for (i=23; i>=0; i--) // 3*3
3181 j = i/8;
3182 bitmask = (1<<(i-(j*8)));
3184 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3186 pMaxHtPhy->field.MCS = i;
3187 break;
3190 if (i==0)
3191 break;
3194 // Copy MIN ht rate. rt2860???
3195 pMinHtPhy->field.BW = BW_20;
3196 pMinHtPhy->field.MCS = 0;
3197 pMinHtPhy->field.STBC = 0;
3198 pMinHtPhy->field.ShortGI = 0;
3199 //If STA assigns fixed rate. update to fixed here.
3200 #ifdef CONFIG_STA_SUPPORT
3201 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3203 if (pDesireHtPhy->MCSSet[4] != 0)
3205 pMaxHtPhy->field.MCS = 32;
3206 pMinHtPhy->field.MCS = 32;
3207 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3210 for (i=23; (CHAR)i >= 0; i--) // 3*3
3212 j = i/8;
3213 bitmask = (1<<(i-(j*8)));
3214 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3216 pMaxHtPhy->field.MCS = i;
3217 pMinHtPhy->field.MCS = i;
3218 break;
3220 if (i==0)
3221 break;
3224 #endif // CONFIG_STA_SUPPORT //
3227 // Decide ht rate
3228 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3229 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3230 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3231 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3232 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3234 // use default now. rt2860
3235 if (pDesireHtPhy->MCSSet[0] != 0xff)
3236 *auto_rate_cur_p = FALSE;
3237 else
3238 *auto_rate_cur_p = TRUE;
3240 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3241 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3242 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3243 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3245 #endif // DOT11_N_SUPPORT //
3247 // IRQL = DISPATCH_LEVEL
3248 VOID MlmeRadioOff(
3249 IN PRTMP_ADAPTER pAd)
3251 RT28XX_MLME_RADIO_OFF(pAd);
3254 // IRQL = DISPATCH_LEVEL
3255 VOID MlmeRadioOn(
3256 IN PRTMP_ADAPTER pAd)
3258 RT28XX_MLME_RADIO_ON(pAd);
3261 // ===========================================================================================
3262 // bss_table.c
3263 // ===========================================================================================
3266 /*! \brief initialize BSS table
3267 * \param p_tab pointer to the table
3268 * \return none
3269 * \pre
3270 * \post
3272 IRQL = PASSIVE_LEVEL
3273 IRQL = DISPATCH_LEVEL
3276 VOID BssTableInit(
3277 IN BSS_TABLE *Tab)
3279 int i;
3281 Tab->BssNr = 0;
3282 Tab->BssOverlapNr = 0;
3283 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3285 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3286 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3290 #ifdef DOT11_N_SUPPORT
3291 VOID BATableInit(
3292 IN PRTMP_ADAPTER pAd,
3293 IN BA_TABLE *Tab)
3295 int i;
3297 Tab->numAsOriginator = 0;
3298 Tab->numAsRecipient = 0;
3299 NdisAllocateSpinLock(&pAd->BATabLock);
3300 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3302 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3303 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3305 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3307 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3310 #endif // DOT11_N_SUPPORT //
3312 /*! \brief search the BSS table by SSID
3313 * \param p_tab pointer to the bss table
3314 * \param ssid SSID string
3315 * \return index of the table, BSS_NOT_FOUND if not in the table
3316 * \pre
3317 * \post
3318 * \note search by sequential search
3320 IRQL = DISPATCH_LEVEL
3323 ULONG BssTableSearch(
3324 IN BSS_TABLE *Tab,
3325 IN PUCHAR pBssid,
3326 IN UCHAR Channel)
3328 UCHAR i;
3330 for (i = 0; i < Tab->BssNr; i++)
3333 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3334 // We should distinguish this case.
3336 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3337 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3338 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3340 return i;
3343 return (ULONG)BSS_NOT_FOUND;
3346 ULONG BssSsidTableSearch(
3347 IN BSS_TABLE *Tab,
3348 IN PUCHAR pBssid,
3349 IN PUCHAR pSsid,
3350 IN UCHAR SsidLen,
3351 IN UCHAR Channel)
3353 UCHAR i;
3355 for (i = 0; i < Tab->BssNr; i++)
3358 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3359 // We should distinguish this case.
3361 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3362 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3363 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3364 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3366 return i;
3369 return (ULONG)BSS_NOT_FOUND;
3372 ULONG BssTableSearchWithSSID(
3373 IN BSS_TABLE *Tab,
3374 IN PUCHAR Bssid,
3375 IN PUCHAR pSsid,
3376 IN UCHAR SsidLen,
3377 IN UCHAR Channel)
3379 UCHAR i;
3381 for (i = 0; i < Tab->BssNr; i++)
3383 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3384 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3385 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3386 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3387 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3388 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3390 return i;
3393 return (ULONG)BSS_NOT_FOUND;
3396 // IRQL = DISPATCH_LEVEL
3397 VOID BssTableDeleteEntry(
3398 IN OUT BSS_TABLE *Tab,
3399 IN PUCHAR pBssid,
3400 IN UCHAR Channel)
3402 UCHAR i, j;
3404 for (i = 0; i < Tab->BssNr; i++)
3406 if ((Tab->BssEntry[i].Channel == Channel) &&
3407 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3409 for (j = i; j < Tab->BssNr - 1; j++)
3411 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3413 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3414 Tab->BssNr -= 1;
3415 return;
3420 #ifdef DOT11_N_SUPPORT
3422 ========================================================================
3423 Routine Description:
3424 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3426 Arguments:
3427 // IRQL = DISPATCH_LEVEL
3428 ========================================================================
3430 VOID BATableDeleteORIEntry(
3431 IN OUT PRTMP_ADAPTER pAd,
3432 IN BA_ORI_ENTRY *pBAORIEntry)
3435 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3437 NdisAcquireSpinLock(&pAd->BATabLock);
3438 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3440 pAd->BATable.numAsOriginator -= 1;
3441 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3442 // Erase Bitmap flag.
3444 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3445 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3446 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3447 pBAORIEntry->Token = 1;
3448 // Not clear Sequence here.
3449 NdisReleaseSpinLock(&pAd->BATabLock);
3452 #endif // DOT11_N_SUPPORT //
3454 /*! \brief
3455 * \param
3456 * \return
3457 * \pre
3458 * \post
3460 IRQL = DISPATCH_LEVEL
3463 VOID BssEntrySet(
3464 IN PRTMP_ADAPTER pAd,
3465 OUT BSS_ENTRY *pBss,
3466 IN PUCHAR pBssid,
3467 IN CHAR Ssid[],
3468 IN UCHAR SsidLen,
3469 IN UCHAR BssType,
3470 IN USHORT BeaconPeriod,
3471 IN PCF_PARM pCfParm,
3472 IN USHORT AtimWin,
3473 IN USHORT CapabilityInfo,
3474 IN UCHAR SupRate[],
3475 IN UCHAR SupRateLen,
3476 IN UCHAR ExtRate[],
3477 IN UCHAR ExtRateLen,
3478 IN HT_CAPABILITY_IE *pHtCapability,
3479 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3480 IN UCHAR HtCapabilityLen,
3481 IN UCHAR AddHtInfoLen,
3482 IN UCHAR NewExtChanOffset,
3483 IN UCHAR Channel,
3484 IN CHAR Rssi,
3485 IN LARGE_INTEGER TimeStamp,
3486 IN UCHAR CkipFlag,
3487 IN PEDCA_PARM pEdcaParm,
3488 IN PQOS_CAPABILITY_PARM pQosCapability,
3489 IN PQBSS_LOAD_PARM pQbssLoad,
3490 IN USHORT LengthVIE,
3491 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3493 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3494 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3495 pBss->Hidden = 1;
3496 if (SsidLen > 0)
3498 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3499 // Or send beacon /probe response with SSID len matching real SSID length,
3500 // but SSID is all zero. such as "00-00-00-00" with length 4.
3501 // We have to prevent this case overwrite correct table
3502 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3504 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3505 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3506 pBss->SsidLen = SsidLen;
3507 pBss->Hidden = 0;
3510 else
3511 pBss->SsidLen = 0;
3512 pBss->BssType = BssType;
3513 pBss->BeaconPeriod = BeaconPeriod;
3514 if (BssType == BSS_INFRA)
3516 if (pCfParm->bValid)
3518 pBss->CfpCount = pCfParm->CfpCount;
3519 pBss->CfpPeriod = pCfParm->CfpPeriod;
3520 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3521 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3524 else
3526 pBss->AtimWin = AtimWin;
3529 pBss->CapabilityInfo = CapabilityInfo;
3530 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3531 // Combine with AuthMode, they will decide the connection methods.
3532 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3533 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3534 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3535 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3536 else
3537 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3538 pBss->SupRateLen = SupRateLen;
3539 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3540 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3541 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3542 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3543 pBss->NewExtChanOffset = NewExtChanOffset;
3544 pBss->ExtRateLen = ExtRateLen;
3545 pBss->Channel = Channel;
3546 pBss->CentralChannel = Channel;
3547 pBss->Rssi = Rssi;
3548 // Update CkipFlag. if not exists, the value is 0x0
3549 pBss->CkipFlag = CkipFlag;
3551 // New for microsoft Fixed IEs
3552 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3553 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3554 pBss->FixIEs.Capabilities = CapabilityInfo;
3556 // New for microsoft Variable IEs
3557 if (LengthVIE != 0)
3559 pBss->VarIELen = LengthVIE;
3560 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3562 else
3564 pBss->VarIELen = 0;
3567 pBss->AddHtInfoLen = 0;
3568 pBss->HtCapabilityLen = 0;
3569 #ifdef DOT11_N_SUPPORT
3570 if (HtCapabilityLen> 0)
3572 pBss->HtCapabilityLen = HtCapabilityLen;
3573 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3574 if (AddHtInfoLen > 0)
3576 pBss->AddHtInfoLen = AddHtInfoLen;
3577 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3579 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3581 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3583 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3585 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3589 #endif // DOT11_N_SUPPORT //
3591 BssCipherParse(pBss);
3593 // new for QOS
3594 if (pEdcaParm)
3595 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3596 else
3597 pBss->EdcaParm.bValid = FALSE;
3598 if (pQosCapability)
3599 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3600 else
3601 pBss->QosCapability.bValid = FALSE;
3602 if (pQbssLoad)
3603 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3604 else
3605 pBss->QbssLoad.bValid = FALSE;
3607 #ifdef CONFIG_STA_SUPPORT
3608 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3610 PEID_STRUCT pEid;
3611 USHORT Length = 0;
3614 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3615 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3617 pEid = (PEID_STRUCT) pVIE;
3619 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3621 switch(pEid->Eid)
3623 case IE_WPA:
3624 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3626 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3628 pBss->WpaIE.IELen = 0;
3629 break;
3631 pBss->WpaIE.IELen = pEid->Len + 2;
3632 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3634 break;
3635 case IE_RSN:
3636 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3638 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3640 pBss->RsnIE.IELen = 0;
3641 break;
3643 pBss->RsnIE.IELen = pEid->Len + 2;
3644 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3646 break;
3648 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3649 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3652 #endif // CONFIG_STA_SUPPORT //
3656 * \brief insert an entry into the bss table
3657 * \param p_tab The BSS table
3658 * \param Bssid BSSID
3659 * \param ssid SSID
3660 * \param ssid_len Length of SSID
3661 * \param bss_type
3662 * \param beacon_period
3663 * \param timestamp
3664 * \param p_cf
3665 * \param atim_win
3666 * \param cap
3667 * \param rates
3668 * \param rates_len
3669 * \param channel_idx
3670 * \return none
3671 * \pre
3672 * \post
3673 * \note If SSID is identical, the old entry will be replaced by the new one
3675 IRQL = DISPATCH_LEVEL
3678 ULONG BssTableSetEntry(
3679 IN PRTMP_ADAPTER pAd,
3680 OUT BSS_TABLE *Tab,
3681 IN PUCHAR pBssid,
3682 IN CHAR Ssid[],
3683 IN UCHAR SsidLen,
3684 IN UCHAR BssType,
3685 IN USHORT BeaconPeriod,
3686 IN CF_PARM *CfParm,
3687 IN USHORT AtimWin,
3688 IN USHORT CapabilityInfo,
3689 IN UCHAR SupRate[],
3690 IN UCHAR SupRateLen,
3691 IN UCHAR ExtRate[],
3692 IN UCHAR ExtRateLen,
3693 IN HT_CAPABILITY_IE *pHtCapability,
3694 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3695 IN UCHAR HtCapabilityLen,
3696 IN UCHAR AddHtInfoLen,
3697 IN UCHAR NewExtChanOffset,
3698 IN UCHAR ChannelNo,
3699 IN CHAR Rssi,
3700 IN LARGE_INTEGER TimeStamp,
3701 IN UCHAR CkipFlag,
3702 IN PEDCA_PARM pEdcaParm,
3703 IN PQOS_CAPABILITY_PARM pQosCapability,
3704 IN PQBSS_LOAD_PARM pQbssLoad,
3705 IN USHORT LengthVIE,
3706 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3708 ULONG Idx;
3710 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3711 if (Idx == BSS_NOT_FOUND)
3713 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3716 // It may happen when BSS Table was full.
3717 // The desired AP will not be added into BSS Table
3718 // In this case, if we found the desired AP then overwrite BSS Table.
3720 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3722 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3723 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3725 Idx = Tab->BssOverlapNr;
3726 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3727 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3728 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3729 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3731 return Idx;
3733 else
3735 return BSS_NOT_FOUND;
3738 Idx = Tab->BssNr;
3739 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3740 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3741 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3742 Tab->BssNr++;
3744 else
3746 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3747 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3748 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3751 return Idx;
3754 #ifdef CONFIG_STA_SUPPORT
3755 // IRQL = DISPATCH_LEVEL
3756 VOID BssTableSsidSort(
3757 IN PRTMP_ADAPTER pAd,
3758 OUT BSS_TABLE *OutTab,
3759 IN CHAR Ssid[],
3760 IN UCHAR SsidLen)
3762 INT i;
3763 BssTableInit(OutTab);
3765 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3767 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3768 BOOLEAN bIsHiddenApIncluded = FALSE;
3770 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3771 (pAd->MlmeAux.Channel > 14) &&
3772 RadarChannelCheck(pAd, pInBss->Channel))
3775 if (pInBss->Hidden)
3776 bIsHiddenApIncluded = TRUE;
3779 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3780 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3782 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3783 #ifdef DOT11_N_SUPPORT
3784 // 2.4G/5G N only mode
3785 if ((pInBss->HtCapabilityLen == 0) &&
3786 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3788 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3789 continue;
3791 #endif // DOT11_N_SUPPORT //
3793 // New for WPA2
3794 // Check the Authmode first
3795 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3797 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3798 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3799 // None matched
3800 continue;
3802 // Check cipher suite, AP must have more secured cipher than station setting
3803 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3805 // If it's not mixed mode, we should only let BSS pass with the same encryption
3806 if (pInBss->WPA.bMixMode == FALSE)
3807 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3808 continue;
3810 // check group cipher
3811 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3812 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3813 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3814 continue;
3816 // check pairwise cipher, skip if none matched
3817 // If profile set to AES, let it pass without question.
3818 // If profile set to TKIP, we must find one mateched
3819 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3820 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3821 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3822 continue;
3824 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3826 // If it's not mixed mode, we should only let BSS pass with the same encryption
3827 if (pInBss->WPA2.bMixMode == FALSE)
3828 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3829 continue;
3831 // check group cipher
3832 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3833 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3834 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3835 continue;
3837 // check pairwise cipher, skip if none matched
3838 // If profile set to AES, let it pass without question.
3839 // If profile set to TKIP, we must find one mateched
3840 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3841 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3842 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3843 continue;
3846 // Bss Type matched, SSID matched.
3847 // We will check wepstatus for qualification Bss
3848 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3850 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3852 // For the SESv2 case, we will not qualify WepStatus.
3854 if (!pInBss->bSES)
3855 continue;
3858 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3859 // It definitely will fail. So, skip it.
3860 // CCX also require not even try to connect it!!
3861 if (SsidLen == 0)
3862 continue;
3864 #ifdef DOT11_N_SUPPORT
3865 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3866 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3867 if ((pInBss->CentralChannel != pInBss->Channel) &&
3868 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3870 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3872 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3873 SetCommonHT(pAd);
3874 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3876 else
3878 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3880 SetCommonHT(pAd);
3884 #endif // DOT11_N_SUPPORT //
3886 // copy matching BSS from InTab to OutTab
3887 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3889 OutTab->BssNr++;
3891 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3893 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3896 #ifdef DOT11_N_SUPPORT
3897 // 2.4G/5G N only mode
3898 if ((pInBss->HtCapabilityLen == 0) &&
3899 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3901 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3902 continue;
3904 #endif // DOT11_N_SUPPORT //
3906 // New for WPA2
3907 // Check the Authmode first
3908 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3910 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3911 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3912 // None matched
3913 continue;
3915 // Check cipher suite, AP must have more secured cipher than station setting
3916 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3918 // If it's not mixed mode, we should only let BSS pass with the same encryption
3919 if (pInBss->WPA.bMixMode == FALSE)
3920 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3921 continue;
3923 // check group cipher
3924 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3925 continue;
3927 // check pairwise cipher, skip if none matched
3928 // If profile set to AES, let it pass without question.
3929 // If profile set to TKIP, we must find one mateched
3930 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3931 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3932 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3933 continue;
3935 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3937 // If it's not mixed mode, we should only let BSS pass with the same encryption
3938 if (pInBss->WPA2.bMixMode == FALSE)
3939 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3940 continue;
3942 // check group cipher
3943 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3944 continue;
3946 // check pairwise cipher, skip if none matched
3947 // If profile set to AES, let it pass without question.
3948 // If profile set to TKIP, we must find one mateched
3949 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3950 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3951 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3952 continue;
3955 // Bss Type matched, SSID matched.
3956 // We will check wepstatus for qualification Bss
3957 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3958 continue;
3960 #ifdef DOT11_N_SUPPORT
3961 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3962 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3963 if ((pInBss->CentralChannel != pInBss->Channel) &&
3964 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3966 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3968 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3969 SetCommonHT(pAd);
3970 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3973 #endif // DOT11_N_SUPPORT //
3975 // copy matching BSS from InTab to OutTab
3976 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3978 OutTab->BssNr++;
3981 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3982 break;
3985 BssTableSortByRssi(OutTab);
3989 // IRQL = DISPATCH_LEVEL
3990 VOID BssTableSortByRssi(
3991 IN OUT BSS_TABLE *OutTab)
3993 INT i, j;
3994 BSS_ENTRY TmpBss;
3996 for (i = 0; i < OutTab->BssNr - 1; i++)
3998 for (j = i+1; j < OutTab->BssNr; j++)
4000 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4002 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4003 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4004 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4009 #endif // CONFIG_STA_SUPPORT //
4012 VOID BssCipherParse(
4013 IN OUT PBSS_ENTRY pBss)
4015 PEID_STRUCT pEid;
4016 PUCHAR pTmp;
4017 PRSN_IE_HEADER_STRUCT pRsnHeader;
4018 PCIPHER_SUITE_STRUCT pCipher;
4019 PAKM_SUITE_STRUCT pAKM;
4020 USHORT Count;
4021 INT Length;
4022 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4025 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4027 if (pBss->Privacy)
4029 pBss->WepStatus = Ndis802_11WEPEnabled;
4031 else
4033 pBss->WepStatus = Ndis802_11WEPDisabled;
4035 // Set default to disable & open authentication before parsing variable IE
4036 pBss->AuthMode = Ndis802_11AuthModeOpen;
4037 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4039 // Init WPA setting
4040 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4041 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4042 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4043 pBss->WPA.RsnCapability = 0;
4044 pBss->WPA.bMixMode = FALSE;
4046 // Init WPA2 setting
4047 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4048 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4049 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4050 pBss->WPA2.RsnCapability = 0;
4051 pBss->WPA2.bMixMode = FALSE;
4054 Length = (INT) pBss->VarIELen;
4056 while (Length > 0)
4058 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4059 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4060 pEid = (PEID_STRUCT) pTmp;
4061 switch (pEid->Eid)
4063 case IE_WPA:
4064 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4065 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4067 pTmp += 11;
4068 switch (*pTmp)
4070 case 1:
4071 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4072 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4073 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4074 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4075 break;
4076 case 2:
4077 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4078 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4079 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4080 break;
4081 case 4:
4082 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4083 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4084 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4085 break;
4086 default:
4087 break;
4090 // if Cisco IE_WPA, break
4091 break;
4093 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4095 pBss->bSES = TRUE;
4096 break;
4098 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4100 // if unsupported vendor specific IE
4101 break;
4103 // Skip OUI, version, and multicast suite
4104 // This part should be improved in the future when AP supported multiple cipher suite.
4105 // For now, it's OK since almost all APs have fixed cipher suite supported.
4106 // pTmp = (PUCHAR) pEid->Octet;
4107 pTmp += 11;
4109 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4110 // Value Meaning
4111 // 0 None
4112 // 1 WEP-40
4113 // 2 Tkip
4114 // 3 WRAP
4115 // 4 AES
4116 // 5 WEP-104
4117 // Parse group cipher
4118 switch (*pTmp)
4120 case 1:
4121 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4122 break;
4123 case 5:
4124 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4125 break;
4126 case 2:
4127 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4128 break;
4129 case 4:
4130 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4131 break;
4132 default:
4133 break;
4135 // number of unicast suite
4136 pTmp += 1;
4138 // skip all unicast cipher suites
4139 //Count = *(PUSHORT) pTmp;
4140 Count = (pTmp[1]<<8) + pTmp[0];
4141 pTmp += sizeof(USHORT);
4143 // Parsing all unicast cipher suite
4144 while (Count > 0)
4146 // Skip OUI
4147 pTmp += 3;
4148 TmpCipher = Ndis802_11WEPDisabled;
4149 switch (*pTmp)
4151 case 1:
4152 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4153 TmpCipher = Ndis802_11Encryption1Enabled;
4154 break;
4155 case 2:
4156 TmpCipher = Ndis802_11Encryption2Enabled;
4157 break;
4158 case 4:
4159 TmpCipher = Ndis802_11Encryption3Enabled;
4160 break;
4161 default:
4162 break;
4164 if (TmpCipher > pBss->WPA.PairCipher)
4166 // Move the lower cipher suite to PairCipherAux
4167 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4168 pBss->WPA.PairCipher = TmpCipher;
4170 else
4172 pBss->WPA.PairCipherAux = TmpCipher;
4174 pTmp++;
4175 Count--;
4178 // 4. get AKM suite counts
4179 //Count = *(PUSHORT) pTmp;
4180 Count = (pTmp[1]<<8) + pTmp[0];
4181 pTmp += sizeof(USHORT);
4182 pTmp += 3;
4184 switch (*pTmp)
4186 case 1:
4187 // Set AP support WPA mode
4188 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4189 pBss->AuthMode = Ndis802_11AuthModeWPA;
4190 else
4191 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4192 break;
4193 case 2:
4194 // Set AP support WPA mode
4195 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4196 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4197 else
4198 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4199 break;
4200 default:
4201 break;
4203 pTmp += 1;
4205 // Fixed for WPA-None
4206 if (pBss->BssType == BSS_ADHOC)
4208 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4209 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4210 pBss->WepStatus = pBss->WPA.GroupCipher;
4211 // Patched bugs for old driver
4212 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4213 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4215 else
4216 pBss->WepStatus = pBss->WPA.PairCipher;
4218 // Check the Pair & Group, if different, turn on mixed mode flag
4219 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4220 pBss->WPA.bMixMode = TRUE;
4222 break;
4224 case IE_RSN:
4225 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4227 // 0. Version must be 1
4228 if (le2cpu16(pRsnHeader->Version) != 1)
4229 break;
4230 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4232 // 1. Check group cipher
4233 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4234 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4235 break;
4237 // Parse group cipher
4238 switch (pCipher->Type)
4240 case 1:
4241 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4242 break;
4243 case 5:
4244 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4245 break;
4246 case 2:
4247 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4248 break;
4249 case 4:
4250 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4251 break;
4252 default:
4253 break;
4255 // set to correct offset for next parsing
4256 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4258 // 2. Get pairwise cipher counts
4259 //Count = *(PUSHORT) pTmp;
4260 Count = (pTmp[1]<<8) + pTmp[0];
4261 pTmp += sizeof(USHORT);
4263 // 3. Get pairwise cipher
4264 // Parsing all unicast cipher suite
4265 while (Count > 0)
4267 // Skip OUI
4268 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4269 TmpCipher = Ndis802_11WEPDisabled;
4270 switch (pCipher->Type)
4272 case 1:
4273 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4274 TmpCipher = Ndis802_11Encryption1Enabled;
4275 break;
4276 case 2:
4277 TmpCipher = Ndis802_11Encryption2Enabled;
4278 break;
4279 case 4:
4280 TmpCipher = Ndis802_11Encryption3Enabled;
4281 break;
4282 default:
4283 break;
4285 if (TmpCipher > pBss->WPA2.PairCipher)
4287 // Move the lower cipher suite to PairCipherAux
4288 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4289 pBss->WPA2.PairCipher = TmpCipher;
4291 else
4293 pBss->WPA2.PairCipherAux = TmpCipher;
4295 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4296 Count--;
4299 // 4. get AKM suite counts
4300 //Count = *(PUSHORT) pTmp;
4301 Count = (pTmp[1]<<8) + pTmp[0];
4302 pTmp += sizeof(USHORT);
4304 // 5. Get AKM ciphers
4305 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4306 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4307 break;
4309 switch (pAKM->Type)
4311 case 1:
4312 // Set AP support WPA mode
4313 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4314 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4315 else
4316 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4317 break;
4318 case 2:
4319 // Set AP support WPA mode
4320 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4321 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4322 else
4323 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4324 break;
4325 default:
4326 break;
4328 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4330 // Fixed for WPA-None
4331 if (pBss->BssType == BSS_ADHOC)
4333 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4334 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4335 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4336 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4337 pBss->WepStatus = pBss->WPA.GroupCipher;
4338 // Patched bugs for old driver
4339 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4340 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4342 pBss->WepStatus = pBss->WPA2.PairCipher;
4344 // 6. Get RSN capability
4345 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4346 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4347 pTmp += sizeof(USHORT);
4349 // Check the Pair & Group, if different, turn on mixed mode flag
4350 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4351 pBss->WPA2.bMixMode = TRUE;
4353 break;
4354 default:
4355 break;
4357 Length -= (pEid->Len + 2);
4361 // ===========================================================================================
4362 // mac_table.c
4363 // ===========================================================================================
4365 /*! \brief generates a random mac address value for IBSS BSSID
4366 * \param Addr the bssid location
4367 * \return none
4368 * \pre
4369 * \post
4371 VOID MacAddrRandomBssid(
4372 IN PRTMP_ADAPTER pAd,
4373 OUT PUCHAR pAddr)
4375 INT i;
4377 for (i = 0; i < MAC_ADDR_LEN; i++)
4379 pAddr[i] = RandomByte(pAd);
4382 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4385 /*! \brief init the management mac frame header
4386 * \param p_hdr mac header
4387 * \param subtype subtype of the frame
4388 * \param p_ds destination address, don't care if it is a broadcast address
4389 * \return none
4390 * \pre the station has the following information in the pAd->StaCfg
4391 * - bssid
4392 * - station address
4393 * \post
4394 * \note this function initializes the following field
4396 IRQL = PASSIVE_LEVEL
4397 IRQL = DISPATCH_LEVEL
4400 VOID MgtMacHeaderInit(
4401 IN PRTMP_ADAPTER pAd,
4402 IN OUT PHEADER_802_11 pHdr80211,
4403 IN UCHAR SubType,
4404 IN UCHAR ToDs,
4405 IN PUCHAR pDA,
4406 IN PUCHAR pBssid)
4408 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4410 pHdr80211->FC.Type = BTYPE_MGMT;
4411 pHdr80211->FC.SubType = SubType;
4412 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4413 // pHdr80211->FC.Type = BTYPE_CNTL;
4414 pHdr80211->FC.ToDs = ToDs;
4415 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4416 #ifdef CONFIG_STA_SUPPORT
4417 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4418 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4419 #endif // CONFIG_STA_SUPPORT //
4420 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4423 // ===========================================================================================
4424 // mem_mgmt.c
4425 // ===========================================================================================
4427 /*!***************************************************************************
4428 * This routine build an outgoing frame, and fill all information specified
4429 * in argument list to the frame body. The actual frame size is the summation
4430 * of all arguments.
4431 * input params:
4432 * Buffer - pointer to a pre-allocated memory segment
4433 * args - a list of <int arg_size, arg> pairs.
4434 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4435 * function will FAIL!!!
4436 * return:
4437 * Size of the buffer
4438 * usage:
4439 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4441 IRQL = PASSIVE_LEVEL
4442 IRQL = DISPATCH_LEVEL
4444 ****************************************************************************/
4445 ULONG MakeOutgoingFrame(
4446 OUT CHAR *Buffer,
4447 OUT ULONG *FrameLen, ...)
4449 CHAR *p;
4450 int leng;
4451 ULONG TotLeng;
4452 va_list Args;
4454 // calculates the total length
4455 TotLeng = 0;
4456 va_start(Args, FrameLen);
4459 leng = va_arg(Args, int);
4460 if (leng == END_OF_ARGS)
4462 break;
4464 p = va_arg(Args, PVOID);
4465 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4466 TotLeng = TotLeng + leng;
4467 } while(TRUE);
4469 va_end(Args); /* clean up */
4470 *FrameLen = TotLeng;
4471 return TotLeng;
4474 // ===========================================================================================
4475 // mlme_queue.c
4476 // ===========================================================================================
4478 /*! \brief Initialize The MLME Queue, used by MLME Functions
4479 * \param *Queue The MLME Queue
4480 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4481 * \pre
4482 * \post
4483 * \note Because this is done only once (at the init stage), no need to be locked
4485 IRQL = PASSIVE_LEVEL
4488 NDIS_STATUS MlmeQueueInit(
4489 IN MLME_QUEUE *Queue)
4491 INT i;
4493 NdisAllocateSpinLock(&Queue->Lock);
4495 Queue->Num = 0;
4496 Queue->Head = 0;
4497 Queue->Tail = 0;
4499 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4501 Queue->Entry[i].Occupied = FALSE;
4502 Queue->Entry[i].MsgLen = 0;
4503 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4506 return NDIS_STATUS_SUCCESS;
4509 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4510 * \param *Queue The MLME Queue
4511 * \param Machine The State Machine Id
4512 * \param MsgType The Message Type
4513 * \param MsgLen The Message length
4514 * \param *Msg The message pointer
4515 * \return TRUE if enqueue is successful, FALSE if the queue is full
4516 * \pre
4517 * \post
4518 * \note The message has to be initialized
4520 IRQL = PASSIVE_LEVEL
4521 IRQL = DISPATCH_LEVEL
4524 BOOLEAN MlmeEnqueue(
4525 IN PRTMP_ADAPTER pAd,
4526 IN ULONG Machine,
4527 IN ULONG MsgType,
4528 IN ULONG MsgLen,
4529 IN VOID *Msg)
4531 INT Tail;
4532 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4534 // Do nothing if the driver is starting halt state.
4535 // This might happen when timer already been fired before cancel timer with mlmehalt
4536 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4537 return FALSE;
4539 // First check the size, it MUST not exceed the mlme queue size
4540 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4542 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4543 return FALSE;
4546 if (MlmeQueueFull(Queue))
4548 return FALSE;
4551 NdisAcquireSpinLock(&(Queue->Lock));
4552 Tail = Queue->Tail;
4553 Queue->Tail++;
4554 Queue->Num++;
4555 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4557 Queue->Tail = 0;
4560 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4561 Queue->Entry[Tail].Occupied = TRUE;
4562 Queue->Entry[Tail].Machine = Machine;
4563 Queue->Entry[Tail].MsgType = MsgType;
4564 Queue->Entry[Tail].MsgLen = MsgLen;
4566 if (Msg != NULL)
4568 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4571 NdisReleaseSpinLock(&(Queue->Lock));
4572 return TRUE;
4575 /*! \brief This function is used when Recv gets a MLME message
4576 * \param *Queue The MLME Queue
4577 * \param TimeStampHigh The upper 32 bit of timestamp
4578 * \param TimeStampLow The lower 32 bit of timestamp
4579 * \param Rssi The receiving RSSI strength
4580 * \param MsgLen The length of the message
4581 * \param *Msg The message pointer
4582 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4583 * \pre
4584 * \post
4586 IRQL = DISPATCH_LEVEL
4589 BOOLEAN MlmeEnqueueForRecv(
4590 IN PRTMP_ADAPTER pAd,
4591 IN ULONG Wcid,
4592 IN ULONG TimeStampHigh,
4593 IN ULONG TimeStampLow,
4594 IN UCHAR Rssi0,
4595 IN UCHAR Rssi1,
4596 IN UCHAR Rssi2,
4597 IN ULONG MsgLen,
4598 IN VOID *Msg,
4599 IN UCHAR Signal)
4601 INT Tail, Machine;
4602 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4603 INT MsgType;
4604 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4606 // Do nothing if the driver is starting halt state.
4607 // This might happen when timer already been fired before cancel timer with mlmehalt
4608 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4610 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4611 return FALSE;
4614 // First check the size, it MUST not exceed the mlme queue size
4615 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4617 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4618 return FALSE;
4621 if (MlmeQueueFull(Queue))
4623 return FALSE;
4626 #ifdef CONFIG_STA_SUPPORT
4627 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4629 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4631 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4632 return FALSE;
4635 #endif // CONFIG_STA_SUPPORT //
4637 // OK, we got all the informations, it is time to put things into queue
4638 NdisAcquireSpinLock(&(Queue->Lock));
4639 Tail = Queue->Tail;
4640 Queue->Tail++;
4641 Queue->Num++;
4642 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4644 Queue->Tail = 0;
4646 Queue->Entry[Tail].Occupied = TRUE;
4647 Queue->Entry[Tail].Machine = Machine;
4648 Queue->Entry[Tail].MsgType = MsgType;
4649 Queue->Entry[Tail].MsgLen = MsgLen;
4650 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4651 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4652 Queue->Entry[Tail].Rssi0 = Rssi0;
4653 Queue->Entry[Tail].Rssi1 = Rssi1;
4654 Queue->Entry[Tail].Rssi2 = Rssi2;
4655 Queue->Entry[Tail].Signal = Signal;
4656 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4658 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4660 if (Msg != NULL)
4662 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4665 NdisReleaseSpinLock(&(Queue->Lock));
4667 RT28XX_MLME_HANDLER(pAd);
4669 return TRUE;
4673 /*! \brief Dequeue a message from the MLME Queue
4674 * \param *Queue The MLME Queue
4675 * \param *Elem The message dequeued from MLME Queue
4676 * \return TRUE if the Elem contains something, FALSE otherwise
4677 * \pre
4678 * \post
4680 IRQL = DISPATCH_LEVEL
4683 BOOLEAN MlmeDequeue(
4684 IN MLME_QUEUE *Queue,
4685 OUT MLME_QUEUE_ELEM **Elem)
4687 NdisAcquireSpinLock(&(Queue->Lock));
4688 *Elem = &(Queue->Entry[Queue->Head]);
4689 Queue->Num--;
4690 Queue->Head++;
4691 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4693 Queue->Head = 0;
4695 NdisReleaseSpinLock(&(Queue->Lock));
4696 return TRUE;
4699 // IRQL = DISPATCH_LEVEL
4700 VOID MlmeRestartStateMachine(
4701 IN PRTMP_ADAPTER pAd)
4703 #ifdef CONFIG_STA_SUPPORT
4704 BOOLEAN Cancelled;
4705 #endif // CONFIG_STA_SUPPORT //
4707 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4710 #ifdef CONFIG_STA_SUPPORT
4711 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4713 // Cancel all timer events
4714 // Be careful to cancel new added timer
4715 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4716 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4717 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4718 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4719 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4720 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4722 #endif // CONFIG_STA_SUPPORT //
4724 // Change back to original channel in case of doing scan
4725 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4726 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4728 // Resume MSDU which is turned off durning scan
4729 RTMPResumeMsduTransmission(pAd);
4731 #ifdef CONFIG_STA_SUPPORT
4732 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4734 // Set all state machines back IDLE
4735 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4736 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4737 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4738 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4739 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4740 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4742 #endif // CONFIG_STA_SUPPORT //
4746 /*! \brief test if the MLME Queue is empty
4747 * \param *Queue The MLME Queue
4748 * \return TRUE if the Queue is empty, FALSE otherwise
4749 * \pre
4750 * \post
4752 IRQL = DISPATCH_LEVEL
4755 BOOLEAN MlmeQueueEmpty(
4756 IN MLME_QUEUE *Queue)
4758 BOOLEAN Ans;
4760 NdisAcquireSpinLock(&(Queue->Lock));
4761 Ans = (Queue->Num == 0);
4762 NdisReleaseSpinLock(&(Queue->Lock));
4764 return Ans;
4767 /*! \brief test if the MLME Queue is full
4768 * \param *Queue The MLME Queue
4769 * \return TRUE if the Queue is empty, FALSE otherwise
4770 * \pre
4771 * \post
4773 IRQL = PASSIVE_LEVEL
4774 IRQL = DISPATCH_LEVEL
4777 BOOLEAN MlmeQueueFull(
4778 IN MLME_QUEUE *Queue)
4780 BOOLEAN Ans;
4782 NdisAcquireSpinLock(&(Queue->Lock));
4783 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4784 NdisReleaseSpinLock(&(Queue->Lock));
4786 return Ans;
4789 /*! \brief The destructor of MLME Queue
4790 * \param
4791 * \return
4792 * \pre
4793 * \post
4794 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4796 IRQL = PASSIVE_LEVEL
4799 VOID MlmeQueueDestroy(
4800 IN MLME_QUEUE *pQueue)
4802 NdisAcquireSpinLock(&(pQueue->Lock));
4803 pQueue->Num = 0;
4804 pQueue->Head = 0;
4805 pQueue->Tail = 0;
4806 NdisReleaseSpinLock(&(pQueue->Lock));
4807 NdisFreeSpinLock(&(pQueue->Lock));
4810 /*! \brief To substitute the message type if the message is coming from external
4811 * \param pFrame The frame received
4812 * \param *Machine The state machine
4813 * \param *MsgType the message type for the state machine
4814 * \return TRUE if the substitution is successful, FALSE otherwise
4815 * \pre
4816 * \post
4818 IRQL = DISPATCH_LEVEL
4821 #ifdef CONFIG_STA_SUPPORT
4822 BOOLEAN MsgTypeSubst(
4823 IN PRTMP_ADAPTER pAd,
4824 IN PFRAME_802_11 pFrame,
4825 OUT INT *Machine,
4826 OUT INT *MsgType)
4828 USHORT Seq;
4829 UCHAR EAPType;
4830 PUCHAR pData;
4832 // Pointer to start of data frames including SNAP header
4833 pData = (PUCHAR) pFrame + LENGTH_802_11;
4835 // The only data type will pass to this function is EAPOL frame
4836 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4838 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4840 // Cisco Aironet SNAP header
4841 *Machine = AIRONET_STATE_MACHINE;
4842 *MsgType = MT2_AIRONET_MSG;
4843 return (TRUE);
4846 *Machine = WPA_PSK_STATE_MACHINE;
4847 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4848 return(WpaMsgTypeSubst(EAPType, MsgType));
4852 switch (pFrame->Hdr.FC.SubType)
4854 case SUBTYPE_ASSOC_REQ:
4855 *Machine = ASSOC_STATE_MACHINE;
4856 *MsgType = MT2_PEER_ASSOC_REQ;
4857 break;
4858 case SUBTYPE_ASSOC_RSP:
4859 *Machine = ASSOC_STATE_MACHINE;
4860 *MsgType = MT2_PEER_ASSOC_RSP;
4861 break;
4862 case SUBTYPE_REASSOC_REQ:
4863 *Machine = ASSOC_STATE_MACHINE;
4864 *MsgType = MT2_PEER_REASSOC_REQ;
4865 break;
4866 case SUBTYPE_REASSOC_RSP:
4867 *Machine = ASSOC_STATE_MACHINE;
4868 *MsgType = MT2_PEER_REASSOC_RSP;
4869 break;
4870 case SUBTYPE_PROBE_REQ:
4871 *Machine = SYNC_STATE_MACHINE;
4872 *MsgType = MT2_PEER_PROBE_REQ;
4873 break;
4874 case SUBTYPE_PROBE_RSP:
4875 *Machine = SYNC_STATE_MACHINE;
4876 *MsgType = MT2_PEER_PROBE_RSP;
4877 break;
4878 case SUBTYPE_BEACON:
4879 *Machine = SYNC_STATE_MACHINE;
4880 *MsgType = MT2_PEER_BEACON;
4881 break;
4882 case SUBTYPE_ATIM:
4883 *Machine = SYNC_STATE_MACHINE;
4884 *MsgType = MT2_PEER_ATIM;
4885 break;
4886 case SUBTYPE_DISASSOC:
4887 *Machine = ASSOC_STATE_MACHINE;
4888 *MsgType = MT2_PEER_DISASSOC_REQ;
4889 break;
4890 case SUBTYPE_AUTH:
4891 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4892 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4893 if (Seq == 1 || Seq == 3)
4895 *Machine = AUTH_RSP_STATE_MACHINE;
4896 *MsgType = MT2_PEER_AUTH_ODD;
4898 else if (Seq == 2 || Seq == 4)
4900 *Machine = AUTH_STATE_MACHINE;
4901 *MsgType = MT2_PEER_AUTH_EVEN;
4903 else
4905 return FALSE;
4907 break;
4908 case SUBTYPE_DEAUTH:
4909 *Machine = AUTH_RSP_STATE_MACHINE;
4910 *MsgType = MT2_PEER_DEAUTH;
4911 break;
4912 case SUBTYPE_ACTION:
4913 *Machine = ACTION_STATE_MACHINE;
4914 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4915 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4917 *MsgType = MT2_ACT_INVALID;
4919 else
4921 *MsgType = (pFrame->Octet[0]&0x7F);
4923 break;
4924 default:
4925 return FALSE;
4926 break;
4929 return TRUE;
4931 #endif // CONFIG_STA_SUPPORT //
4933 // ===========================================================================================
4934 // state_machine.c
4935 // ===========================================================================================
4937 /*! \brief Initialize the state machine.
4938 * \param *S pointer to the state machine
4939 * \param Trans State machine transition function
4940 * \param StNr number of states
4941 * \param MsgNr number of messages
4942 * \param DefFunc default function, when there is invalid state/message combination
4943 * \param InitState initial state of the state machine
4944 * \param Base StateMachine base, internal use only
4945 * \pre p_sm should be a legal pointer
4946 * \post
4948 IRQL = PASSIVE_LEVEL
4951 VOID StateMachineInit(
4952 IN STATE_MACHINE *S,
4953 IN STATE_MACHINE_FUNC Trans[],
4954 IN ULONG StNr,
4955 IN ULONG MsgNr,
4956 IN STATE_MACHINE_FUNC DefFunc,
4957 IN ULONG InitState,
4958 IN ULONG Base)
4960 ULONG i, j;
4962 // set number of states and messages
4963 S->NrState = StNr;
4964 S->NrMsg = MsgNr;
4965 S->Base = Base;
4967 S->TransFunc = Trans;
4969 // init all state transition to default function
4970 for (i = 0; i < StNr; i++)
4972 for (j = 0; j < MsgNr; j++)
4974 S->TransFunc[i * MsgNr + j] = DefFunc;
4978 // set the starting state
4979 S->CurrState = InitState;
4982 /*! \brief This function fills in the function pointer into the cell in the state machine
4983 * \param *S pointer to the state machine
4984 * \param St state
4985 * \param Msg incoming message
4986 * \param f the function to be executed when (state, message) combination occurs at the state machine
4987 * \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
4988 * \post
4990 IRQL = PASSIVE_LEVEL
4993 VOID StateMachineSetAction(
4994 IN STATE_MACHINE *S,
4995 IN ULONG St,
4996 IN ULONG Msg,
4997 IN STATE_MACHINE_FUNC Func)
4999 ULONG MsgIdx;
5001 MsgIdx = Msg - S->Base;
5003 if (St < S->NrState && MsgIdx < S->NrMsg)
5005 // boundary checking before setting the action
5006 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5010 /*! \brief This function does the state transition
5011 * \param *Adapter the NIC adapter pointer
5012 * \param *S the state machine
5013 * \param *Elem the message to be executed
5014 * \return None
5016 IRQL = DISPATCH_LEVEL
5019 VOID StateMachinePerformAction(
5020 IN PRTMP_ADAPTER pAd,
5021 IN STATE_MACHINE *S,
5022 IN MLME_QUEUE_ELEM *Elem)
5024 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5028 ==========================================================================
5029 Description:
5030 The drop function, when machine executes this, the message is simply
5031 ignored. This function does nothing, the message is freed in
5032 StateMachinePerformAction()
5033 ==========================================================================
5035 VOID Drop(
5036 IN PRTMP_ADAPTER pAd,
5037 IN MLME_QUEUE_ELEM *Elem)
5041 // ===========================================================================================
5042 // lfsr.c
5043 // ===========================================================================================
5046 ==========================================================================
5047 Description:
5049 IRQL = PASSIVE_LEVEL
5051 ==========================================================================
5053 VOID LfsrInit(
5054 IN PRTMP_ADAPTER pAd,
5055 IN ULONG Seed)
5057 if (Seed == 0)
5058 pAd->Mlme.ShiftReg = 1;
5059 else
5060 pAd->Mlme.ShiftReg = Seed;
5064 ==========================================================================
5065 Description:
5066 ==========================================================================
5068 UCHAR RandomByte(
5069 IN PRTMP_ADAPTER pAd)
5071 ULONG i;
5072 UCHAR R, Result;
5074 R = 0;
5076 if (pAd->Mlme.ShiftReg == 0)
5077 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5079 for (i = 0; i < 8; i++)
5081 if (pAd->Mlme.ShiftReg & 0x00000001)
5083 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5084 Result = 1;
5086 else
5088 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5089 Result = 0;
5091 R = (R << 1) | Result;
5094 return R;
5097 VOID AsicUpdateAutoFallBackTable(
5098 IN PRTMP_ADAPTER pAd,
5099 IN PUCHAR pRateTable)
5101 UCHAR i;
5102 HT_FBK_CFG0_STRUC HtCfg0;
5103 HT_FBK_CFG1_STRUC HtCfg1;
5104 LG_FBK_CFG0_STRUC LgCfg0;
5105 LG_FBK_CFG1_STRUC LgCfg1;
5106 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5108 // set to initial value
5109 HtCfg0.word = 0x65432100;
5110 HtCfg1.word = 0xedcba988;
5111 LgCfg0.word = 0xedcba988;
5112 LgCfg1.word = 0x00002100;
5114 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5115 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5117 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5118 switch (pCurrTxRate->Mode)
5120 case 0: //CCK
5121 break;
5122 case 1: //OFDM
5124 switch(pCurrTxRate->CurrMCS)
5126 case 0:
5127 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5128 break;
5129 case 1:
5130 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5131 break;
5132 case 2:
5133 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5134 break;
5135 case 3:
5136 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5137 break;
5138 case 4:
5139 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5140 break;
5141 case 5:
5142 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5143 break;
5144 case 6:
5145 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5146 break;
5147 case 7:
5148 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5149 break;
5152 break;
5153 #ifdef DOT11_N_SUPPORT
5154 case 2: //HT-MIX
5155 case 3: //HT-GF
5157 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5159 switch(pCurrTxRate->CurrMCS)
5161 case 0:
5162 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5163 break;
5164 case 1:
5165 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5166 break;
5167 case 2:
5168 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5169 break;
5170 case 3:
5171 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5172 break;
5173 case 4:
5174 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5175 break;
5176 case 5:
5177 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5178 break;
5179 case 6:
5180 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5181 break;
5182 case 7:
5183 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5184 break;
5185 case 8:
5186 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5187 break;
5188 case 9:
5189 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5190 break;
5191 case 10:
5192 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5193 break;
5194 case 11:
5195 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5196 break;
5197 case 12:
5198 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5199 break;
5200 case 13:
5201 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5202 break;
5203 case 14:
5204 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5205 break;
5206 case 15:
5207 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5208 break;
5209 default:
5210 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5214 break;
5215 #endif // DOT11_N_SUPPORT //
5218 pNextTxRate = pCurrTxRate;
5221 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5222 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5223 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5224 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5228 ========================================================================
5230 Routine Description:
5231 Set MAC register value according operation mode.
5232 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5233 If MM or GF mask is not set, those passing argument doesn't not take effect.
5235 Operation mode meaning:
5236 = 0 : Pure HT, no preotection.
5237 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5238 = 0x10: No Transmission in 40M is protected.
5239 = 0x11: Transmission in both 40M and 20M shall be protected
5240 if (bNonGFExist)
5241 we should choose not to use GF. But still set correct ASIC registers.
5242 ========================================================================
5244 VOID AsicUpdateProtect(
5245 IN PRTMP_ADAPTER pAd,
5246 IN USHORT OperationMode,
5247 IN UCHAR SetMask,
5248 IN BOOLEAN bDisableBGProtect,
5249 IN BOOLEAN bNonGFExist)
5251 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5252 UINT32 Protect[6];
5253 USHORT offset;
5254 UCHAR i;
5255 UINT32 MacReg = 0;
5257 #ifdef DOT11_N_SUPPORT
5258 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5260 return;
5263 if (pAd->BATable.numAsOriginator)
5266 // enable the RTS/CTS to avoid channel collision
5268 SetMask = ALLN_SETPROTECT;
5269 OperationMode = 8;
5271 #endif // DOT11_N_SUPPORT //
5273 // Config ASIC RTS threshold register
5274 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5275 MacReg &= 0xFF0000FF;
5276 #if 0
5277 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5278 #else
5279 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5280 if ((
5281 #ifdef DOT11_N_SUPPORT
5282 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5283 #endif // DOT11_N_SUPPORT //
5284 (pAd->CommonCfg.bAggregationCapable == TRUE))
5285 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5287 MacReg |= (0x1000 << 8);
5289 else
5291 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5293 #endif
5295 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5297 // Initial common protection settings
5298 RTMPZeroMemory(Protect, sizeof(Protect));
5299 ProtCfg4.word = 0;
5300 ProtCfg.word = 0;
5301 ProtCfg.field.TxopAllowGF40 = 1;
5302 ProtCfg.field.TxopAllowGF20 = 1;
5303 ProtCfg.field.TxopAllowMM40 = 1;
5304 ProtCfg.field.TxopAllowMM20 = 1;
5305 ProtCfg.field.TxopAllowOfdm = 1;
5306 ProtCfg.field.TxopAllowCck = 1;
5307 ProtCfg.field.RTSThEn = 1;
5308 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5310 // update PHY mode and rate
5311 if (pAd->CommonCfg.Channel > 14)
5312 ProtCfg.field.ProtectRate = 0x4000;
5313 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5315 // Handle legacy(B/G) protection
5316 if (bDisableBGProtect)
5318 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5319 ProtCfg.field.ProtectCtrl = 0;
5320 Protect[0] = ProtCfg.word;
5321 Protect[1] = ProtCfg.word;
5323 else
5325 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5326 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5327 Protect[0] = ProtCfg.word;
5328 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5329 Protect[1] = ProtCfg.word;
5332 #ifdef DOT11_N_SUPPORT
5333 // Decide HT frame protection.
5334 if ((SetMask & ALLN_SETPROTECT) != 0)
5336 switch(OperationMode)
5338 case 0x0:
5339 // NO PROTECT
5340 // 1.All STAs in the BSS are 20/40 MHz HT
5341 // 2. in ai 20/40MHz BSS
5342 // 3. all STAs are 20MHz in a 20MHz BSS
5343 // Pure HT. no protection.
5345 // MM20_PROT_CFG
5346 // Reserved (31:27)
5347 // PROT_TXOP(25:20) -- 010111
5348 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5349 // PROT_CTRL(17:16) -- 00 (None)
5350 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5351 Protect[2] = 0x01744004;
5353 // MM40_PROT_CFG
5354 // Reserved (31:27)
5355 // PROT_TXOP(25:20) -- 111111
5356 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5357 // PROT_CTRL(17:16) -- 00 (None)
5358 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5359 Protect[3] = 0x03f44084;
5361 // CF20_PROT_CFG
5362 // Reserved (31:27)
5363 // PROT_TXOP(25:20) -- 010111
5364 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5365 // PROT_CTRL(17:16) -- 00 (None)
5366 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5367 Protect[4] = 0x01744004;
5369 // CF40_PROT_CFG
5370 // Reserved (31:27)
5371 // PROT_TXOP(25:20) -- 111111
5372 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5373 // PROT_CTRL(17:16) -- 00 (None)
5374 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5375 Protect[5] = 0x03f44084;
5377 if (bNonGFExist)
5379 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5380 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5381 Protect[4] = 0x01754004;
5382 Protect[5] = 0x03f54084;
5384 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5385 break;
5387 case 1:
5388 // This is "HT non-member protection mode."
5389 // If there may be non-HT STAs my BSS
5390 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5391 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5392 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5394 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5395 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5397 //Assign Protection method for 20&40 MHz packets
5398 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5399 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5400 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5401 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5402 Protect[2] = ProtCfg.word;
5403 Protect[3] = ProtCfg4.word;
5404 Protect[4] = ProtCfg.word;
5405 Protect[5] = ProtCfg4.word;
5406 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5407 break;
5409 case 2:
5410 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5411 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5412 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5414 //Assign Protection method for 40MHz packets
5415 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5416 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5417 Protect[2] = ProtCfg.word;
5418 Protect[3] = ProtCfg4.word;
5419 if (bNonGFExist)
5421 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5422 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5424 Protect[4] = ProtCfg.word;
5425 Protect[5] = ProtCfg4.word;
5427 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5428 break;
5430 case 3:
5431 // HT mixed mode. PROTECT ALL!
5432 // Assign Rate
5433 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5434 ProtCfg4.word = 0x03f44084;
5435 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5436 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5438 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5439 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5441 //Assign Protection method for 20&40 MHz packets
5442 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5443 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5444 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5445 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5446 Protect[2] = ProtCfg.word;
5447 Protect[3] = ProtCfg4.word;
5448 Protect[4] = ProtCfg.word;
5449 Protect[5] = ProtCfg4.word;
5450 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5451 break;
5453 case 8:
5454 // Special on for Atheros problem n chip.
5455 Protect[2] = 0x01754004;
5456 Protect[3] = 0x03f54084;
5457 Protect[4] = 0x01754004;
5458 Protect[5] = 0x03f54084;
5459 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5460 break;
5463 #endif // DOT11_N_SUPPORT //
5465 offset = CCK_PROT_CFG;
5466 for (i = 0;i < 6;i++)
5468 if ((SetMask & (1<< i)))
5470 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5476 ==========================================================================
5477 Description:
5479 IRQL = PASSIVE_LEVEL
5480 IRQL = DISPATCH_LEVEL
5482 ==========================================================================
5484 VOID AsicSwitchChannel(
5485 IN PRTMP_ADAPTER pAd,
5486 IN UCHAR Channel,
5487 IN BOOLEAN bScan)
5489 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5490 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5491 UCHAR index;
5492 UINT32 Value = 0; //BbpReg, Value;
5493 RTMP_RF_REGS *RFRegTable;
5495 // Search Tx power value
5496 for (index = 0; index < pAd->ChannelListNum; index++)
5498 if (Channel == pAd->ChannelList[index].Channel)
5500 TxPwer = pAd->ChannelList[index].Power;
5501 TxPwer2 = pAd->ChannelList[index].Power2;
5502 break;
5506 if (index == MAX_NUM_OF_CHANNELS)
5508 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5511 #ifdef RT2870
5512 // The RF programming sequence is difference between 3xxx and 2xxx
5513 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5515 /* modify by WY for Read RF Reg. error */
5516 UCHAR RFValue;
5518 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5520 if (Channel == FreqItems3020[index].Channel)
5522 // Programming channel parameters
5523 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5524 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5526 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5527 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5528 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5530 // Set Tx Power
5531 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5532 RFValue = (RFValue & 0xE0) | TxPwer;
5533 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5535 // Set RF offset
5536 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5537 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5538 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5540 // Set BW
5541 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5543 RFValue = pAd->Mlme.CaliBW40RfR24;
5544 //DISABLE_11N_CHECK(pAd);
5546 else
5548 RFValue = pAd->Mlme.CaliBW20RfR24;
5550 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5552 // Enable RF tuning
5553 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5554 RFValue = RFValue | 0x1;
5555 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5557 // latch channel for future usage.
5558 pAd->LatchRfRegs.Channel = Channel;
5560 break;
5564 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5565 Channel,
5566 pAd->RfIcType,
5567 TxPwer,
5568 TxPwer2,
5569 pAd->Antenna.field.TxPath,
5570 FreqItems3020[index].N,
5571 FreqItems3020[index].K,
5572 FreqItems3020[index].R));
5574 else
5575 #endif // RT2870 //
5577 RFRegTable = RF2850RegTable;
5579 switch (pAd->RfIcType)
5581 case RFIC_2820:
5582 case RFIC_2850:
5583 case RFIC_2720:
5584 case RFIC_2750:
5586 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5588 if (Channel == RFRegTable[index].Channel)
5590 R2 = RFRegTable[index].R2;
5591 if (pAd->Antenna.field.TxPath == 1)
5593 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5596 if (pAd->Antenna.field.RxPath == 2)
5598 R2 |= 0x40; // write 1 to off Rxpath.
5600 else if (pAd->Antenna.field.RxPath == 1)
5602 R2 |= 0x20040; // write 1 to off RxPath
5605 if (Channel > 14)
5607 // initialize R3, R4
5608 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5609 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5611 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5612 // R3
5613 if ((TxPwer >= -7) && (TxPwer < 0))
5615 TxPwer = (7+TxPwer);
5616 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5617 R3 |= (TxPwer << 10);
5618 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5620 else
5622 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5623 R3 |= (TxPwer << 10) | (1 << 9);
5626 // R4
5627 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5629 TxPwer2 = (7+TxPwer2);
5630 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5631 R4 |= (TxPwer2 << 7);
5632 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5634 else
5636 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5637 R4 |= (TxPwer2 << 7) | (1 << 6);
5640 else
5642 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5643 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5646 // Based on BBP current mode before changing RF channel.
5647 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5649 R4 |=0x200000;
5652 // Update variables
5653 pAd->LatchRfRegs.Channel = Channel;
5654 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5655 pAd->LatchRfRegs.R2 = R2;
5656 pAd->LatchRfRegs.R3 = R3;
5657 pAd->LatchRfRegs.R4 = R4;
5659 // Set RF value 1's set R3[bit2] = [0]
5660 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5661 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5662 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5663 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5665 RTMPusecDelay(200);
5667 // Set RF value 2's set R3[bit2] = [1]
5668 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5669 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5670 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5671 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5673 RTMPusecDelay(200);
5675 // Set RF value 3's set R3[bit2] = [0]
5676 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5677 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5678 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5679 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5681 break;
5684 break;
5686 default:
5687 break;
5691 // Change BBP setting during siwtch from a->g, g->a
5692 if (Channel <= 14)
5694 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5696 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5697 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5698 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5699 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.
5700 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5702 // Rx High power VGA offset for LNA select
5703 if (pAd->NicConfig2.field.ExternalLNAForG)
5705 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5706 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5708 else
5710 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5711 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5714 // 5G band selection PIN, bit1 and bit2 are complement
5715 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5716 Value &= (~0x6);
5717 Value |= (0x04);
5718 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5720 // Turn off unused PA or LNA when only 1T or 1R
5721 if (pAd->Antenna.field.TxPath == 1)
5723 TxPinCfg &= 0xFFFFFFF3;
5725 if (pAd->Antenna.field.RxPath == 1)
5727 TxPinCfg &= 0xFFFFF3FF;
5730 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5732 else
5734 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5736 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5737 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5738 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5739 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.
5740 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5742 // Rx High power VGA offset for LNA select
5743 if (pAd->NicConfig2.field.ExternalLNAForA)
5745 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5747 else
5749 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5752 // 5G band selection PIN, bit1 and bit2 are complement
5753 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5754 Value &= (~0x6);
5755 Value |= (0x02);
5756 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5758 // Turn off unused PA or LNA when only 1T or 1R
5759 if (pAd->Antenna.field.TxPath == 1)
5761 TxPinCfg &= 0xFFFFFFF3;
5763 if (pAd->Antenna.field.RxPath == 1)
5765 TxPinCfg &= 0xFFFFF3FF;
5768 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5771 // R66 should be set according to Channel and use 20MHz when scanning
5772 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5773 if (bScan)
5774 RTMPSetAGCInitValue(pAd, BW_20);
5775 else
5776 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5779 // On 11A, We should delay and wait RF/BBP to be stable
5780 // and the appropriate time should be 1000 micro seconds
5781 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5783 RTMPusecDelay(1000);
5785 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",
5786 Channel,
5787 pAd->RfIcType,
5788 (R3 & 0x00003e00) >> 9,
5789 (R4 & 0x000007c0) >> 6,
5790 pAd->Antenna.field.TxPath,
5791 pAd->LatchRfRegs.R1,
5792 pAd->LatchRfRegs.R2,
5793 pAd->LatchRfRegs.R3,
5794 pAd->LatchRfRegs.R4));
5798 ==========================================================================
5799 Description:
5800 This function is required for 2421 only, and should not be used during
5801 site survey. It's only required after NIC decided to stay at a channel
5802 for a longer period.
5803 When this function is called, it's always after AsicSwitchChannel().
5805 IRQL = PASSIVE_LEVEL
5806 IRQL = DISPATCH_LEVEL
5808 ==========================================================================
5810 VOID AsicLockChannel(
5811 IN PRTMP_ADAPTER pAd,
5812 IN UCHAR Channel)
5817 ==========================================================================
5818 Description:
5820 IRQL = PASSIVE_LEVEL
5821 IRQL = DISPATCH_LEVEL
5823 ==========================================================================
5825 VOID AsicAntennaSelect(
5826 IN PRTMP_ADAPTER pAd,
5827 IN UCHAR Channel)
5832 ========================================================================
5834 Routine Description:
5835 Antenna miscellaneous setting.
5837 Arguments:
5838 pAd Pointer to our adapter
5839 BandState Indicate current Band State.
5841 Return Value:
5842 None
5844 IRQL <= DISPATCH_LEVEL
5846 Note:
5847 1.) Frame End type control
5848 only valid for G only (RF_2527 & RF_2529)
5849 0: means DPDT, set BBP R4 bit 5 to 1
5850 1: means SPDT, set BBP R4 bit 5 to 0
5853 ========================================================================
5855 VOID AsicAntennaSetting(
5856 IN PRTMP_ADAPTER pAd,
5857 IN ABGBAND_STATE BandState)
5861 VOID AsicRfTuningExec(
5862 IN PVOID SystemSpecific1,
5863 IN PVOID FunctionContext,
5864 IN PVOID SystemSpecific2,
5865 IN PVOID SystemSpecific3)
5870 ==========================================================================
5871 Description:
5872 Gives CCK TX rate 2 more dB TX power.
5873 This routine works only in LINK UP in INFRASTRUCTURE mode.
5875 calculate desired Tx power in RF R3.Tx0~5, should consider -
5876 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
5877 1. TxPowerPercentage
5878 2. auto calibration based on TSSI feedback
5879 3. extra 2 db for CCK
5880 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
5882 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
5883 it should be called AFTER MlmeDynamicTxRatSwitching()
5884 ==========================================================================
5886 VOID AsicAdjustTxPower(
5887 IN PRTMP_ADAPTER pAd)
5889 INT i, j;
5890 CHAR DeltaPwr = 0;
5891 BOOLEAN bAutoTxAgc = FALSE;
5892 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
5893 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
5894 PCHAR pTxAgcCompensate;
5895 ULONG TxPwr[5];
5896 CHAR Value;
5898 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
5900 if (pAd->CommonCfg.CentralChannel > 14)
5902 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
5903 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
5904 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
5905 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
5906 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
5908 else
5910 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
5911 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
5912 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
5913 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
5914 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
5917 else
5919 if (pAd->CommonCfg.Channel > 14)
5921 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
5922 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
5923 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
5924 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
5925 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
5927 else
5929 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
5930 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
5931 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
5932 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
5933 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
5937 // TX power compensation for temperature variation based on TSSI. try every 4 second
5938 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
5940 if (pAd->CommonCfg.Channel <= 14)
5942 /* bg channel */
5943 bAutoTxAgc = pAd->bAutoTxAgcG;
5944 TssiRef = pAd->TssiRefG;
5945 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
5946 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
5947 TxAgcStep = pAd->TxAgcStepG;
5948 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5950 else
5952 /* a channel */
5953 bAutoTxAgc = pAd->bAutoTxAgcA;
5954 TssiRef = pAd->TssiRefA;
5955 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
5956 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
5957 TxAgcStep = pAd->TxAgcStepA;
5958 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5961 if (bAutoTxAgc)
5963 /* BbpR1 is unsigned char */
5964 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
5966 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
5967 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
5968 /* step value is defined in pAd->TxAgcStepG for tx power value */
5970 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
5971 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
5972 above value are examined in mass factory production */
5973 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
5975 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
5976 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
5977 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
5979 if (BbpR49 > pTssiMinusBoundary[1])
5981 // Reading is larger than the reference value
5982 // check for how large we need to decrease the Tx power
5983 for (idx = 1; idx < 5; idx++)
5985 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
5986 break;
5988 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
5989 // if (R3 > (ULONG) (TxAgcStep * (idx-1)))
5990 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
5991 // else
5992 // *pTxAgcCompensate = -((UCHAR)R3);
5994 DeltaPwr += (*pTxAgcCompensate);
5995 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
5996 BbpR49, TssiRef, TxAgcStep, idx-1));
5998 else if (BbpR49 < pTssiPlusBoundary[1])
6000 // Reading is smaller than the reference value
6001 // check for how large we need to increase the Tx power
6002 for (idx = 1; idx < 5; idx++)
6004 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6005 break;
6007 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6008 *pTxAgcCompensate = TxAgcStep * (idx-1);
6009 DeltaPwr += (*pTxAgcCompensate);
6010 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6011 BbpR49, TssiRef, TxAgcStep, idx-1));
6013 else
6015 *pTxAgcCompensate = 0;
6016 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6017 BbpR49, TssiRef, TxAgcStep, 0));
6021 else
6023 if (pAd->CommonCfg.Channel <= 14)
6025 bAutoTxAgc = pAd->bAutoTxAgcG;
6026 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6028 else
6030 bAutoTxAgc = pAd->bAutoTxAgcA;
6031 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6034 if (bAutoTxAgc)
6035 DeltaPwr += (*pTxAgcCompensate);
6038 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6039 BbpR1 &= 0xFC;
6041 /* calculate delta power based on the percentage specified from UI */
6042 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6043 // We lower TX power here according to the percentage specified from UI
6044 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6046 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6048 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6050 DeltaPwr -= 1;
6052 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6054 DeltaPwr -= 3;
6056 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6058 BbpR1 |= 0x01;
6060 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6062 BbpR1 |= 0x01;
6063 DeltaPwr -= 3;
6065 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6067 BbpR1 |= 0x02;
6070 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6072 /* reset different new tx power for different TX rate */
6073 for(i=0; i<5; i++)
6075 if (TxPwr[i] != 0xffffffff)
6077 for (j=0; j<8; j++)
6079 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6081 if ((Value + DeltaPwr) < 0)
6083 Value = 0; /* min */
6085 else if ((Value + DeltaPwr) > 0xF)
6087 Value = 0xF; /* max */
6089 else
6091 Value += DeltaPwr; /* temperature compensation */
6094 /* fill new value to CSR offset */
6095 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6098 /* write tx power value to CSR */
6099 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6100 TX power for OFDM 6M/9M
6101 TX power for CCK5.5M/11M
6102 TX power for CCK1M/2M */
6103 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6104 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6110 #ifdef CONFIG_STA_SUPPORT
6112 ==========================================================================
6113 Description:
6114 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6115 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6116 the wakeup timer timeout. Driver has to issue a separate command to wake
6117 PHY up.
6119 IRQL = DISPATCH_LEVEL
6121 ==========================================================================
6123 VOID AsicSleepThenAutoWakeup(
6124 IN PRTMP_ADAPTER pAd,
6125 IN USHORT TbttNumToNextWakeUp)
6127 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6131 ==========================================================================
6132 Description:
6133 AsicForceWakeup() is used whenever manual wakeup is required
6134 AsicForceSleep() should only be used when not in INFRA BSS. When
6135 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6136 ==========================================================================
6138 VOID AsicForceSleep(
6139 IN PRTMP_ADAPTER pAd)
6145 ==========================================================================
6146 Description:
6147 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6148 expired.
6150 IRQL = PASSIVE_LEVEL
6151 IRQL = DISPATCH_LEVEL
6152 ==========================================================================
6154 VOID AsicForceWakeup(
6155 IN PRTMP_ADAPTER pAd,
6156 IN BOOLEAN bFromTx)
6158 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6159 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6161 #endif // CONFIG_STA_SUPPORT //
6163 ==========================================================================
6164 Description:
6165 Set My BSSID
6167 IRQL = DISPATCH_LEVEL
6169 ==========================================================================
6171 VOID AsicSetBssid(
6172 IN PRTMP_ADAPTER pAd,
6173 IN PUCHAR pBssid)
6175 ULONG Addr4;
6176 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6177 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6179 Addr4 = (ULONG)(pBssid[0]) |
6180 (ULONG)(pBssid[1] << 8) |
6181 (ULONG)(pBssid[2] << 16) |
6182 (ULONG)(pBssid[3] << 24);
6183 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6185 Addr4 = 0;
6186 // always one BSSID in STA mode
6187 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6189 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6192 VOID AsicSetMcastWC(
6193 IN PRTMP_ADAPTER pAd)
6195 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6196 USHORT offset;
6198 pEntry->Sst = SST_ASSOC;
6199 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6200 pEntry->PsMode = PWR_ACTIVE;
6201 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6202 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6206 ==========================================================================
6207 Description:
6209 IRQL = DISPATCH_LEVEL
6211 ==========================================================================
6213 VOID AsicDelWcidTab(
6214 IN PRTMP_ADAPTER pAd,
6215 IN UCHAR Wcid)
6217 ULONG Addr0 = 0x0, Addr1 = 0x0;
6218 ULONG offset;
6220 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6221 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6222 RTMP_IO_WRITE32(pAd, offset, Addr0);
6223 offset += 4;
6224 RTMP_IO_WRITE32(pAd, offset, Addr1);
6228 ==========================================================================
6229 Description:
6231 IRQL = DISPATCH_LEVEL
6233 ==========================================================================
6235 VOID AsicEnableRDG(
6236 IN PRTMP_ADAPTER pAd)
6238 TX_LINK_CFG_STRUC TxLinkCfg;
6239 UINT32 Data = 0;
6241 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6242 TxLinkCfg.field.TxRDGEn = 1;
6243 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6245 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6246 Data &= 0xFFFFFF00;
6247 Data |= 0x80;
6248 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6250 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6254 ==========================================================================
6255 Description:
6257 IRQL = DISPATCH_LEVEL
6259 ==========================================================================
6261 VOID AsicDisableRDG(
6262 IN PRTMP_ADAPTER pAd)
6264 TX_LINK_CFG_STRUC TxLinkCfg;
6265 UINT32 Data = 0;
6268 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6269 TxLinkCfg.field.TxRDGEn = 0;
6270 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6272 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6274 Data &= 0xFFFFFF00;
6275 //Data |= 0x20;
6276 #ifndef WIFI_TEST
6277 //if ( pAd->CommonCfg.bEnableTxBurst )
6278 // Data |= 0x60; // for performance issue not set the TXOP to 0
6279 #endif
6280 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6281 #ifdef DOT11_N_SUPPORT
6282 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6283 #endif // DOT11_N_SUPPORT //
6286 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6287 if (pAd->CommonCfg.bEnableTxBurst)
6288 Data |= 0x20;
6290 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6294 ==========================================================================
6295 Description:
6297 IRQL = PASSIVE_LEVEL
6298 IRQL = DISPATCH_LEVEL
6300 ==========================================================================
6302 VOID AsicDisableSync(
6303 IN PRTMP_ADAPTER pAd)
6305 BCN_TIME_CFG_STRUC csr;
6307 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6309 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6310 // that NIC will never wakes up because TSF stops and no more
6311 // TBTT interrupts
6312 pAd->TbttTickCount = 0;
6313 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6314 csr.field.bBeaconGen = 0;
6315 csr.field.bTBTTEnable = 0;
6316 csr.field.TsfSyncMode = 0;
6317 csr.field.bTsfTicking = 0;
6318 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6323 ==========================================================================
6324 Description:
6326 IRQL = DISPATCH_LEVEL
6328 ==========================================================================
6330 VOID AsicEnableBssSync(
6331 IN PRTMP_ADAPTER pAd)
6333 BCN_TIME_CFG_STRUC csr;
6335 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6337 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6338 // RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);
6339 #ifdef CONFIG_STA_SUPPORT
6340 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6342 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6343 csr.field.bTsfTicking = 1;
6344 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6345 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6346 csr.field.bTBTTEnable = 1;
6348 #endif // CONFIG_STA_SUPPORT //
6349 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6353 ==========================================================================
6354 Description:
6355 Note:
6356 BEACON frame in shared memory should be built ok before this routine
6357 can be called. Otherwise, a garbage frame maybe transmitted out every
6358 Beacon period.
6360 IRQL = DISPATCH_LEVEL
6362 ==========================================================================
6364 VOID AsicEnableIbssSync(
6365 IN PRTMP_ADAPTER pAd)
6367 BCN_TIME_CFG_STRUC csr9;
6368 PUCHAR ptr;
6369 UINT i;
6371 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6373 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6374 csr9.field.bBeaconGen = 0;
6375 csr9.field.bTBTTEnable = 0;
6376 csr9.field.bTsfTicking = 0;
6377 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6380 #ifdef RT2870
6381 // move BEACON TXD and frame content to on-chip memory
6382 ptr = (PUCHAR)&pAd->BeaconTxWI;
6383 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6385 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6386 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6387 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6388 ptr += 2;
6391 // start right after the 16-byte TXWI field
6392 ptr = pAd->BeaconBuf;
6393 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6395 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6396 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6397 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6398 ptr +=2;
6400 #endif // RT2870 //
6403 // For Wi-Fi faily generated beacons between participating stations.
6404 // Set TBTT phase adaptive adjustment step to 8us (default 16us)
6405 // don't change settings 2006-5- by Jerry
6406 //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);
6408 // start sending BEACON
6409 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6410 csr9.field.bTsfTicking = 1;
6411 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6412 csr9.field.bTBTTEnable = 1;
6413 csr9.field.bBeaconGen = 1;
6414 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6418 ==========================================================================
6419 Description:
6421 IRQL = PASSIVE_LEVEL
6422 IRQL = DISPATCH_LEVEL
6424 ==========================================================================
6426 VOID AsicSetEdcaParm(
6427 IN PRTMP_ADAPTER pAd,
6428 IN PEDCA_PARM pEdcaParm)
6430 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6431 AC_TXOP_CSR0_STRUC csr0;
6432 AC_TXOP_CSR1_STRUC csr1;
6433 AIFSN_CSR_STRUC AifsnCsr;
6434 CWMIN_CSR_STRUC CwminCsr;
6435 CWMAX_CSR_STRUC CwmaxCsr;
6436 int i;
6438 Ac0Cfg.word = 0;
6439 Ac1Cfg.word = 0;
6440 Ac2Cfg.word = 0;
6441 Ac3Cfg.word = 0;
6442 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6444 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6445 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6446 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6448 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6449 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6452 //========================================================
6453 // MAC Register has a copy .
6454 //========================================================
6455 //#ifndef WIFI_TEST
6456 if( pAd->CommonCfg.bEnableTxBurst )
6458 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6459 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6461 else
6462 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6463 //#else
6464 // Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6465 //#endif
6466 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6467 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6468 Ac0Cfg.field.Aifsn = 2;
6469 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6471 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6472 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6473 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6474 Ac1Cfg.field.Aifsn = 2;
6475 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6477 if (pAd->CommonCfg.PhyMode == PHY_11B)
6479 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6480 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6482 else
6484 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6485 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6487 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6488 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6489 Ac2Cfg.field.Aifsn = 2;
6490 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6491 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6492 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6493 Ac3Cfg.field.Aifsn = 2;
6494 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6496 //========================================================
6497 // DMA Register has a copy too.
6498 //========================================================
6499 csr0.field.Ac0Txop = 0; // QID_AC_BE
6500 csr0.field.Ac1Txop = 0; // QID_AC_BK
6501 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6502 if (pAd->CommonCfg.PhyMode == PHY_11B)
6504 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6505 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6507 else
6509 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6510 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6512 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6514 CwminCsr.word = 0;
6515 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6516 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6517 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6518 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6519 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6521 CwmaxCsr.word = 0;
6522 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6523 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6524 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6525 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6526 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6528 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6530 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6532 else
6534 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6535 //========================================================
6536 // MAC Register has a copy.
6537 //========================================================
6539 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6540 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6542 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6544 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6545 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6546 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6547 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6549 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6550 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6551 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6552 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6554 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6555 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6556 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6557 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6558 #ifdef CONFIG_STA_SUPPORT
6559 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6561 // Tuning for Wi-Fi WMM S06
6562 if (pAd->CommonCfg.bWiFiTest &&
6563 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6564 Ac2Cfg.field.Aifsn -= 1;
6566 // Tuning for TGn Wi-Fi 5.2.32
6567 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6568 if (STA_TGN_WIFI_ON(pAd) &&
6569 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6571 Ac0Cfg.field.Aifsn = 3;
6572 Ac2Cfg.field.AcTxop = 5;
6575 #endif // CONFIG_STA_SUPPORT //
6577 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6578 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6579 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6580 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6582 //#ifdef WIFI_TEST
6583 if (pAd->CommonCfg.bWiFiTest)
6585 if (Ac3Cfg.field.AcTxop == 102)
6587 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6588 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6589 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6590 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6591 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6592 } /* End of if */
6594 //#endif // WIFI_TEST //
6596 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6597 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6598 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6599 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6602 //========================================================
6603 // DMA Register has a copy too.
6604 //========================================================
6605 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6606 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6607 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6609 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6610 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6611 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6613 CwminCsr.word = 0;
6614 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6615 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6616 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6617 #ifdef CONFIG_STA_SUPPORT
6618 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6619 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6620 #endif // CONFIG_STA_SUPPORT //
6621 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6623 CwmaxCsr.word = 0;
6624 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6625 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6626 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6627 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6628 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6630 AifsnCsr.word = 0;
6631 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6632 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6633 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6634 #ifdef CONFIG_STA_SUPPORT
6635 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6637 // Tuning for Wi-Fi WMM S06
6638 if (pAd->CommonCfg.bWiFiTest &&
6639 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6640 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6642 // Tuning for TGn Wi-Fi 5.2.32
6643 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6644 if (STA_TGN_WIFI_ON(pAd) &&
6645 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6647 AifsnCsr.field.Aifsn0 = 3;
6648 AifsnCsr.field.Aifsn2 = 7;
6651 if (INFRA_ON(pAd))
6652 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
6654 #endif // CONFIG_STA_SUPPORT //
6656 #ifdef CONFIG_STA_SUPPORT
6657 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6658 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6659 #endif // CONFIG_STA_SUPPORT //
6660 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6662 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6663 if (!ADHOC_ON(pAd))
6665 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6666 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6667 pEdcaParm->Aifsn[0],
6668 pEdcaParm->Cwmin[0],
6669 pEdcaParm->Cwmax[0],
6670 pEdcaParm->Txop[0]<<5,
6671 pEdcaParm->bACM[0]));
6672 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6673 pEdcaParm->Aifsn[1],
6674 pEdcaParm->Cwmin[1],
6675 pEdcaParm->Cwmax[1],
6676 pEdcaParm->Txop[1]<<5,
6677 pEdcaParm->bACM[1]));
6678 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6679 pEdcaParm->Aifsn[2],
6680 pEdcaParm->Cwmin[2],
6681 pEdcaParm->Cwmax[2],
6682 pEdcaParm->Txop[2]<<5,
6683 pEdcaParm->bACM[2]));
6684 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6685 pEdcaParm->Aifsn[3],
6686 pEdcaParm->Cwmin[3],
6687 pEdcaParm->Cwmax[3],
6688 pEdcaParm->Txop[3]<<5,
6689 pEdcaParm->bACM[3]));
6695 ==========================================================================
6696 Description:
6698 IRQL = PASSIVE_LEVEL
6699 IRQL = DISPATCH_LEVEL
6701 ==========================================================================
6703 VOID AsicSetSlotTime(
6704 IN PRTMP_ADAPTER pAd,
6705 IN BOOLEAN bUseShortSlotTime)
6707 ULONG SlotTime;
6708 UINT32 RegValue = 0;
6710 #ifdef CONFIG_STA_SUPPORT
6711 if (pAd->CommonCfg.Channel > 14)
6712 bUseShortSlotTime = TRUE;
6713 #endif // CONFIG_STA_SUPPORT //
6715 if (bUseShortSlotTime)
6716 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6717 else
6718 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6720 SlotTime = (bUseShortSlotTime)? 9 : 20;
6722 #ifdef CONFIG_STA_SUPPORT
6723 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6725 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6726 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6727 #ifdef DOT11_N_SUPPORT
6728 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6729 #endif // DOT11_N_SUPPORT //
6732 // In this case, we will think it is doing Wi-Fi test
6733 // And we will not set to short slot when bEnableTxBurst is TRUE.
6735 else if (pAd->CommonCfg.bEnableTxBurst)
6736 SlotTime = 9;
6738 #endif // CONFIG_STA_SUPPORT //
6741 // For some reasons, always set it to short slot time.
6743 // ToDo: Should consider capability with 11B
6745 #ifdef CONFIG_STA_SUPPORT
6746 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6748 if (pAd->StaCfg.BssType == BSS_ADHOC)
6749 SlotTime = 20;
6751 #endif // CONFIG_STA_SUPPORT //
6753 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6754 RegValue = RegValue & 0xFFFFFF00;
6756 RegValue |= SlotTime;
6758 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6762 ========================================================================
6763 Description:
6764 Add Shared key information into ASIC.
6765 Update shared key, TxMic and RxMic to Asic Shared key table
6766 Update its cipherAlg to Asic Shared key Mode.
6768 Return:
6769 ========================================================================
6771 VOID AsicAddSharedKeyEntry(
6772 IN PRTMP_ADAPTER pAd,
6773 IN UCHAR BssIndex,
6774 IN UCHAR KeyIdx,
6775 IN UCHAR CipherAlg,
6776 IN PUCHAR pKey,
6777 IN PUCHAR pTxMic,
6778 IN PUCHAR pRxMic)
6780 ULONG offset; //, csr0;
6781 SHAREDKEY_MODE_STRUC csr1;
6783 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6784 //============================================================================================
6786 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6787 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6788 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]));
6789 if (pRxMic)
6791 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6792 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6794 if (pTxMic)
6796 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6797 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6799 //============================================================================================
6801 // fill key material - key + TX MIC + RX MIC
6804 #ifdef RT2870
6806 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6807 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
6809 offset += MAX_LEN_OF_SHARE_KEY;
6810 if (pTxMic)
6812 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
6815 offset += 8;
6816 if (pRxMic)
6818 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
6821 #endif // RT2870 //
6824 // Update cipher algorithm. WSTA always use BSS0
6826 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6827 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6828 if ((BssIndex%2) == 0)
6830 if (KeyIdx == 0)
6831 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6832 else if (KeyIdx == 1)
6833 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6834 else if (KeyIdx == 2)
6835 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6836 else
6837 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6839 else
6841 if (KeyIdx == 0)
6842 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6843 else if (KeyIdx == 1)
6844 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6845 else if (KeyIdx == 2)
6846 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6847 else
6848 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6850 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6851 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6855 // IRQL = DISPATCH_LEVEL
6856 VOID AsicRemoveSharedKeyEntry(
6857 IN PRTMP_ADAPTER pAd,
6858 IN UCHAR BssIndex,
6859 IN UCHAR KeyIdx)
6861 //ULONG SecCsr0;
6862 SHAREDKEY_MODE_STRUC csr1;
6864 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
6866 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6867 if ((BssIndex%2) == 0)
6869 if (KeyIdx == 0)
6870 csr1.field.Bss0Key0CipherAlg = 0;
6871 else if (KeyIdx == 1)
6872 csr1.field.Bss0Key1CipherAlg = 0;
6873 else if (KeyIdx == 2)
6874 csr1.field.Bss0Key2CipherAlg = 0;
6875 else
6876 csr1.field.Bss0Key3CipherAlg = 0;
6878 else
6880 if (KeyIdx == 0)
6881 csr1.field.Bss1Key0CipherAlg = 0;
6882 else if (KeyIdx == 1)
6883 csr1.field.Bss1Key1CipherAlg = 0;
6884 else if (KeyIdx == 2)
6885 csr1.field.Bss1Key2CipherAlg = 0;
6886 else
6887 csr1.field.Bss1Key3CipherAlg = 0;
6889 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6890 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6891 ASSERT(BssIndex < 4);
6892 ASSERT(KeyIdx < 4);
6897 VOID AsicUpdateWCIDAttribute(
6898 IN PRTMP_ADAPTER pAd,
6899 IN USHORT WCID,
6900 IN UCHAR BssIndex,
6901 IN UCHAR CipherAlg,
6902 IN BOOLEAN bUsePairewiseKeyTable)
6904 ULONG WCIDAttri = 0, offset;
6907 // Update WCID attribute.
6908 // Only TxKey could update WCID attribute.
6910 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
6911 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
6912 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
6915 VOID AsicUpdateWCIDIVEIV(
6916 IN PRTMP_ADAPTER pAd,
6917 IN USHORT WCID,
6918 IN ULONG uIV,
6919 IN ULONG uEIV)
6921 ULONG offset;
6923 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6925 RTMP_IO_WRITE32(pAd, offset, uIV);
6926 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
6929 VOID AsicUpdateRxWCIDTable(
6930 IN PRTMP_ADAPTER pAd,
6931 IN USHORT WCID,
6932 IN PUCHAR pAddr)
6934 ULONG offset;
6935 ULONG Addr;
6937 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
6938 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
6939 RTMP_IO_WRITE32(pAd, offset, Addr);
6940 Addr = pAddr[4] + (pAddr[5] << 8);
6941 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
6946 ========================================================================
6948 Routine Description:
6949 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
6951 Arguments:
6952 pAd Pointer to our adapter
6953 WCID WCID Entry number.
6954 BssIndex BSSID index, station or none multiple BSSID support
6955 this value should be 0.
6956 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
6957 pCipherKey Pointer to Cipher Key.
6958 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
6959 otherwise PairewiseKey table
6960 bTxKey This is the transmit key if enabled.
6962 Return Value:
6963 None
6965 Note:
6966 This routine will set the relative key stuff to Asic including WCID attribute,
6967 Cipher Key, Cipher algorithm and IV/EIV.
6969 IV/EIV will be update if this CipherKey is the transmission key because
6970 ASIC will base on IV's KeyID value to select Cipher Key.
6972 If bTxKey sets to FALSE, this is not the TX key, but it could be
6973 RX key
6975 For AP mode bTxKey must be always set to TRUE.
6976 ========================================================================
6978 VOID AsicAddKeyEntry(
6979 IN PRTMP_ADAPTER pAd,
6980 IN USHORT WCID,
6981 IN UCHAR BssIndex,
6982 IN UCHAR KeyIdx,
6983 IN PCIPHER_KEY pCipherKey,
6984 IN BOOLEAN bUsePairewiseKeyTable,
6985 IN BOOLEAN bTxKey)
6987 ULONG offset;
6988 // ULONG WCIDAttri = 0;
6989 UCHAR IV4 = 0;
6990 PUCHAR pKey = pCipherKey->Key;
6991 // ULONG KeyLen = pCipherKey->KeyLen;
6992 PUCHAR pTxMic = pCipherKey->TxMic;
6993 PUCHAR pRxMic = pCipherKey->RxMic;
6994 PUCHAR pTxtsc = pCipherKey->TxTsc;
6995 UCHAR CipherAlg = pCipherKey->CipherAlg;
6996 SHAREDKEY_MODE_STRUC csr1;
6998 // ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY);
7000 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7002 // 1.) decide key table offset
7004 if (bUsePairewiseKeyTable)
7005 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7006 else
7007 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7010 // 2.) Set Key to Asic
7012 //for (i = 0; i < KeyLen; i++)
7014 #ifdef RT2870
7015 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7016 offset += MAX_LEN_OF_PEER_KEY;
7019 // 3.) Set MIC key if available
7021 if (pTxMic)
7023 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7025 offset += LEN_TKIP_TXMICK;
7027 if (pRxMic)
7029 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7031 #endif // RT2870 //
7034 // 4.) Modify IV/EIV if needs
7035 // This will force Asic to use this key ID by setting IV.
7037 if (bTxKey)
7040 #ifdef RT2870
7041 UINT32 tmpVal;
7044 // Write IV
7046 IV4 = (KeyIdx << 6);
7047 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7048 IV4 |= 0x20; // turn on extension bit means EIV existence
7050 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7051 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7054 // Write EIV
7056 offset += 4;
7057 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7058 #endif // RT2870 //
7059 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7062 if (!bUsePairewiseKeyTable)
7065 // Only update the shared key security mode
7067 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7068 if ((BssIndex % 2) == 0)
7070 if (KeyIdx == 0)
7071 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7072 else if (KeyIdx == 1)
7073 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7074 else if (KeyIdx == 2)
7075 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7076 else
7077 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7079 else
7081 if (KeyIdx == 0)
7082 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7083 else if (KeyIdx == 1)
7084 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7085 else if (KeyIdx == 2)
7086 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7087 else
7088 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7090 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7093 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7098 ========================================================================
7099 Description:
7100 Add Pair-wise key material into ASIC.
7101 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7103 Return:
7104 ========================================================================
7106 VOID AsicAddPairwiseKeyEntry(
7107 IN PRTMP_ADAPTER pAd,
7108 IN PUCHAR pAddr,
7109 IN UCHAR WCID,
7110 IN CIPHER_KEY *pCipherKey)
7112 INT i;
7113 ULONG offset;
7114 PUCHAR pKey = pCipherKey->Key;
7115 PUCHAR pTxMic = pCipherKey->TxMic;
7116 PUCHAR pRxMic = pCipherKey->RxMic;
7117 #ifdef DBG
7118 UCHAR CipherAlg = pCipherKey->CipherAlg;
7119 #endif // DBG //
7121 // EKEY
7122 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7123 #ifdef RT2870
7124 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7125 #endif // RT2870 //
7126 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7128 UINT32 Value;
7129 RTMP_IO_READ32(pAd, offset + i, &Value);
7132 offset += MAX_LEN_OF_PEER_KEY;
7134 // MIC KEY
7135 if (pTxMic)
7137 #ifdef RT2870
7138 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7139 #endif // RT2870 //
7141 offset += 8;
7142 if (pRxMic)
7144 #ifdef RT2870
7145 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7146 #endif // RT2870 //
7149 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7150 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7151 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]));
7152 if (pRxMic)
7154 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7155 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7157 if (pTxMic)
7159 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7160 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7164 ========================================================================
7165 Description:
7166 Remove Pair-wise key material from ASIC.
7168 Return:
7169 ========================================================================
7171 VOID AsicRemovePairwiseKeyEntry(
7172 IN PRTMP_ADAPTER pAd,
7173 IN UCHAR BssIdx,
7174 IN UCHAR Wcid)
7176 ULONG WCIDAttri;
7177 USHORT offset;
7179 // re-set the entry's WCID attribute as OPEN-NONE.
7180 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7181 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7182 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7185 BOOLEAN AsicSendCommandToMcu(
7186 IN PRTMP_ADAPTER pAd,
7187 IN UCHAR Command,
7188 IN UCHAR Token,
7189 IN UCHAR Arg0,
7190 IN UCHAR Arg1)
7192 HOST_CMD_CSR_STRUC H2MCmd;
7193 H2M_MAILBOX_STRUC H2MMailbox;
7194 ULONG i = 0;
7197 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7198 if (H2MMailbox.field.Owner == 0)
7199 break;
7201 RTMPusecDelay(2);
7202 } while(i++ < 100);
7204 if (i >= 100)
7207 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7209 return FALSE;
7213 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7214 H2MMailbox.field.CmdToken = Token;
7215 H2MMailbox.field.HighByte = Arg1;
7216 H2MMailbox.field.LowByte = Arg0;
7217 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7219 H2MCmd.word = 0;
7220 H2MCmd.field.HostCommand = Command;
7221 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7223 if (Command != 0x80)
7227 return TRUE;
7232 ========================================================================
7234 Routine Description:
7235 Verify the support rate for different PHY type
7237 Arguments:
7238 pAd Pointer to our adapter
7240 Return Value:
7241 None
7243 IRQL = PASSIVE_LEVEL
7245 ========================================================================
7247 VOID RTMPCheckRates(
7248 IN PRTMP_ADAPTER pAd,
7249 IN OUT UCHAR SupRate[],
7250 IN OUT UCHAR *SupRateLen)
7252 UCHAR RateIdx, i, j;
7253 UCHAR NewRate[12], NewRateLen;
7255 NewRateLen = 0;
7257 if (pAd->CommonCfg.PhyMode == PHY_11B)
7258 RateIdx = 4;
7259 else
7260 RateIdx = 12;
7262 // Check for support rates exclude basic rate bit
7263 for (i = 0; i < *SupRateLen; i++)
7264 for (j = 0; j < RateIdx; j++)
7265 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7266 NewRate[NewRateLen++] = SupRate[i];
7268 *SupRateLen = NewRateLen;
7269 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7272 #ifdef CONFIG_STA_SUPPORT
7273 #ifdef DOT11_N_SUPPORT
7274 BOOLEAN RTMPCheckChannel(
7275 IN PRTMP_ADAPTER pAd,
7276 IN UCHAR CentralChannel,
7277 IN UCHAR Channel)
7279 UCHAR k;
7280 UCHAR UpperChannel = 0, LowerChannel = 0;
7281 UCHAR NoEffectChannelinList = 0;
7283 // Find upper and lower channel according to 40MHz current operation.
7284 if (CentralChannel < Channel)
7286 UpperChannel = Channel;
7287 if (CentralChannel > 2)
7288 LowerChannel = CentralChannel - 2;
7289 else
7290 return FALSE;
7292 else if (CentralChannel > Channel)
7294 UpperChannel = CentralChannel + 2;
7295 LowerChannel = Channel;
7298 for (k = 0;k < pAd->ChannelListNum;k++)
7300 if (pAd->ChannelList[k].Channel == UpperChannel)
7302 NoEffectChannelinList ++;
7304 if (pAd->ChannelList[k].Channel == LowerChannel)
7306 NoEffectChannelinList ++;
7310 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7311 if (NoEffectChannelinList == 2)
7312 return TRUE;
7313 else
7314 return FALSE;
7318 ========================================================================
7320 Routine Description:
7321 Verify the support rate for HT phy type
7323 Arguments:
7324 pAd Pointer to our adapter
7326 Return Value:
7327 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7329 IRQL = PASSIVE_LEVEL
7331 ========================================================================
7333 BOOLEAN RTMPCheckHt(
7334 IN PRTMP_ADAPTER pAd,
7335 IN UCHAR Wcid,
7336 IN HT_CAPABILITY_IE *pHtCapability,
7337 IN ADD_HT_INFO_IE *pAddHtInfo)
7339 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7340 return FALSE;
7342 // If use AMSDU, set flag.
7343 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7344 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7345 // Save Peer Capability
7346 if (pHtCapability->HtCapInfo.ShortGIfor20)
7347 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7348 if (pHtCapability->HtCapInfo.ShortGIfor40)
7349 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7350 if (pHtCapability->HtCapInfo.TxSTBC)
7351 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7352 if (pHtCapability->HtCapInfo.RxSTBC)
7353 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7354 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7356 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7359 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7361 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7364 // Will check ChannelWidth for MCSSet[4] below
7365 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7366 switch (pAd->CommonCfg.RxStream)
7368 case 1:
7369 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7370 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7371 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7372 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7373 break;
7374 case 2:
7375 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7376 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7377 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7378 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7379 break;
7380 case 3:
7381 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7382 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7383 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7384 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7385 break;
7388 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7390 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7391 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7392 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7394 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7396 // Send Assoc Req with my HT capability.
7397 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7398 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7399 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7400 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7401 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7402 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7403 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7404 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7405 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7406 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7407 if (pAd->CommonCfg.bRdg)
7409 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7410 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7413 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7414 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7416 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7417 return TRUE;
7419 #endif // DOT11_N_SUPPORT //
7420 #endif // CONFIG_STA_SUPPORT //
7423 ========================================================================
7425 Routine Description:
7426 Verify the support rate for different PHY type
7428 Arguments:
7429 pAd Pointer to our adapter
7431 Return Value:
7432 None
7434 IRQL = PASSIVE_LEVEL
7436 ========================================================================
7438 VOID RTMPUpdateMlmeRate(
7439 IN PRTMP_ADAPTER pAd)
7441 UCHAR MinimumRate;
7442 UCHAR ProperMlmeRate; //= RATE_54;
7443 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7444 BOOLEAN bMatch = FALSE;
7446 switch (pAd->CommonCfg.PhyMode)
7448 case PHY_11B:
7449 ProperMlmeRate = RATE_11;
7450 MinimumRate = RATE_1;
7451 break;
7452 case PHY_11BG_MIXED:
7453 #ifdef DOT11_N_SUPPORT
7454 case PHY_11ABGN_MIXED:
7455 case PHY_11BGN_MIXED:
7456 #endif // DOT11_N_SUPPORT //
7457 if ((pAd->MlmeAux.SupRateLen == 4) &&
7458 (pAd->MlmeAux.ExtRateLen == 0))
7459 // B only AP
7460 ProperMlmeRate = RATE_11;
7461 else
7462 ProperMlmeRate = RATE_24;
7464 if (pAd->MlmeAux.Channel <= 14)
7465 MinimumRate = RATE_1;
7466 else
7467 MinimumRate = RATE_6;
7468 break;
7469 case PHY_11A:
7470 #ifdef DOT11_N_SUPPORT
7471 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7472 case PHY_11GN_MIXED:
7473 case PHY_11AGN_MIXED:
7474 case PHY_11AN_MIXED:
7475 case PHY_11N_5G:
7476 #endif // DOT11_N_SUPPORT //
7477 ProperMlmeRate = RATE_24;
7478 MinimumRate = RATE_6;
7479 break;
7480 case PHY_11ABG_MIXED:
7481 ProperMlmeRate = RATE_24;
7482 if (pAd->MlmeAux.Channel <= 14)
7483 MinimumRate = RATE_1;
7484 else
7485 MinimumRate = RATE_6;
7486 break;
7487 default: // error
7488 ProperMlmeRate = RATE_1;
7489 MinimumRate = RATE_1;
7490 break;
7493 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7495 for (j = 0; j < RateIdx; j++)
7497 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7499 if (j == ProperMlmeRate)
7501 bMatch = TRUE;
7502 break;
7507 if (bMatch)
7508 break;
7511 if (bMatch == FALSE)
7513 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7515 for (j = 0; j < RateIdx; j++)
7517 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7519 if (j == ProperMlmeRate)
7521 bMatch = TRUE;
7522 break;
7527 if (bMatch)
7528 break;
7532 if (bMatch == FALSE)
7534 ProperMlmeRate = MinimumRate;
7537 pAd->CommonCfg.MlmeRate = MinimumRate;
7538 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7539 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7541 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7542 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7543 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7544 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7546 else
7548 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7549 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7550 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7551 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7554 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7557 CHAR RTMPMaxRssi(
7558 IN PRTMP_ADAPTER pAd,
7559 IN CHAR Rssi0,
7560 IN CHAR Rssi1,
7561 IN CHAR Rssi2)
7563 CHAR larger = -127;
7565 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7567 larger = Rssi0;
7570 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7572 larger = max(Rssi0, Rssi1);
7575 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7577 larger = max(larger, Rssi2);
7580 if (larger == -127)
7581 larger = 0;
7583 return larger;
7587 ========================================================================
7588 Routine Description:
7589 Periodic evaluate antenna link status
7591 Arguments:
7592 pAd - Adapter pointer
7594 Return Value:
7595 None
7597 ========================================================================
7599 VOID AsicEvaluateRxAnt(
7600 IN PRTMP_ADAPTER pAd)
7602 UCHAR BBPR3 = 0;
7604 #ifdef CONFIG_STA_SUPPORT
7605 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7607 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7608 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7609 fRTMP_ADAPTER_RADIO_OFF |
7610 fRTMP_ADAPTER_NIC_NOT_EXIST |
7611 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7612 return;
7614 if (pAd->StaCfg.Psm == PWR_SAVE)
7615 return;
7617 #endif // CONFIG_STA_SUPPORT //
7619 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7620 BBPR3 &= (~0x18);
7621 if(pAd->Antenna.field.RxPath == 3)
7623 BBPR3 |= (0x10);
7625 else if(pAd->Antenna.field.RxPath == 2)
7627 BBPR3 |= (0x8);
7629 else if(pAd->Antenna.field.RxPath == 1)
7631 BBPR3 |= (0x0);
7633 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7634 #ifdef CONFIG_STA_SUPPORT
7635 #endif // CONFIG_STA_SUPPORT //
7636 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7639 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7640 pAd->RalinkCounters.OneSecTxRetryOkCount +
7641 pAd->RalinkCounters.OneSecTxFailCount;
7643 if (TxTotalCnt > 50)
7645 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7646 pAd->Mlme.bLowThroughput = FALSE;
7648 else
7650 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7651 pAd->Mlme.bLowThroughput = TRUE;
7657 ========================================================================
7658 Routine Description:
7659 After evaluation, check antenna link status
7661 Arguments:
7662 pAd - Adapter pointer
7664 Return Value:
7665 None
7667 ========================================================================
7669 VOID AsicRxAntEvalTimeout(
7670 IN PVOID SystemSpecific1,
7671 IN PVOID FunctionContext,
7672 IN PVOID SystemSpecific2,
7673 IN PVOID SystemSpecific3)
7675 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7676 #ifdef CONFIG_STA_SUPPORT
7677 UCHAR BBPR3 = 0;
7678 CHAR larger = -127, rssi0, rssi1, rssi2;
7679 #endif // CONFIG_STA_SUPPORT //
7681 #ifdef CONFIG_STA_SUPPORT
7682 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7684 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7685 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7686 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7687 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7688 return;
7690 if (pAd->StaCfg.Psm == PWR_SAVE)
7691 return;
7694 // if the traffic is low, use average rssi as the criteria
7695 if (pAd->Mlme.bLowThroughput == TRUE)
7697 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7698 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7699 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7701 else
7703 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7704 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7705 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7708 if(pAd->Antenna.field.RxPath == 3)
7710 larger = max(rssi0, rssi1);
7712 if (larger > (rssi2 + 20))
7713 pAd->Mlme.RealRxPath = 2;
7714 else
7715 pAd->Mlme.RealRxPath = 3;
7717 else if(pAd->Antenna.field.RxPath == 2)
7719 if (rssi0 > (rssi1 + 20))
7720 pAd->Mlme.RealRxPath = 1;
7721 else
7722 pAd->Mlme.RealRxPath = 2;
7725 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7726 BBPR3 &= (~0x18);
7727 if(pAd->Mlme.RealRxPath == 3)
7729 BBPR3 |= (0x10);
7731 else if(pAd->Mlme.RealRxPath == 2)
7733 BBPR3 |= (0x8);
7735 else if(pAd->Mlme.RealRxPath == 1)
7737 BBPR3 |= (0x0);
7739 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7742 #endif // CONFIG_STA_SUPPORT //
7748 VOID APSDPeriodicExec(
7749 IN PVOID SystemSpecific1,
7750 IN PVOID FunctionContext,
7751 IN PVOID SystemSpecific2,
7752 IN PVOID SystemSpecific3)
7754 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7756 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7757 return;
7759 pAd->CommonCfg.TriggerTimerCount++;
7761 // Driver should not send trigger frame, it should be send by application layer
7763 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
7764 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
7765 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
7767 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
7768 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
7769 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
7770 pAd->CommonCfg.TriggerTimerCount = 0;
7771 pAd->CommonCfg.bInServicePeriod = TRUE;
7776 ========================================================================
7777 Routine Description:
7778 Set/reset MAC registers according to bPiggyBack parameter
7780 Arguments:
7781 pAd - Adapter pointer
7782 bPiggyBack - Enable / Disable Piggy-Back
7784 Return Value:
7785 None
7787 ========================================================================
7789 VOID RTMPSetPiggyBack(
7790 IN PRTMP_ADAPTER pAd,
7791 IN BOOLEAN bPiggyBack)
7793 TX_LINK_CFG_STRUC TxLinkCfg;
7795 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
7797 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
7798 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
7802 ========================================================================
7803 Routine Description:
7804 check if this entry need to switch rate automatically
7806 Arguments:
7808 pEntry
7810 Return Value:
7811 TURE
7812 FALSE
7814 ========================================================================
7816 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
7817 IN PRTMP_ADAPTER pAd,
7818 IN PMAC_TABLE_ENTRY pEntry)
7820 BOOLEAN result = TRUE;
7823 #ifdef CONFIG_STA_SUPPORT
7824 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7826 // only associated STA counts
7827 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
7829 result = pAd->StaCfg.bAutoTxRateSwitch;
7831 else
7832 result = FALSE;
7834 #endif // CONFIG_STA_SUPPORT //
7838 return result;
7842 BOOLEAN RTMPAutoRateSwitchCheck(
7843 IN PRTMP_ADAPTER pAd)
7846 #ifdef CONFIG_STA_SUPPORT
7847 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7849 if (pAd->StaCfg.bAutoTxRateSwitch)
7850 return TRUE;
7852 #endif // CONFIG_STA_SUPPORT //
7853 return FALSE;
7858 ========================================================================
7859 Routine Description:
7860 check if this entry need to fix tx legacy rate
7862 Arguments:
7864 pEntry
7866 Return Value:
7867 TURE
7868 FALSE
7870 ========================================================================
7872 UCHAR RTMPStaFixedTxMode(
7873 IN PRTMP_ADAPTER pAd,
7874 IN PMAC_TABLE_ENTRY pEntry)
7876 UCHAR tx_mode = FIXED_TXMODE_HT;
7879 #ifdef CONFIG_STA_SUPPORT
7880 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7882 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
7884 #endif // CONFIG_STA_SUPPORT //
7886 return tx_mode;
7890 ========================================================================
7891 Routine Description:
7892 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
7894 Arguments:
7896 pEntry
7898 Return Value:
7899 TURE
7900 FALSE
7902 ========================================================================
7904 VOID RTMPUpdateLegacyTxSetting(
7905 UCHAR fixed_tx_mode,
7906 PMAC_TABLE_ENTRY pEntry)
7908 HTTRANSMIT_SETTING TransmitSetting;
7910 if (fixed_tx_mode == FIXED_TXMODE_HT)
7911 return;
7913 TransmitSetting.word = 0;
7915 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
7916 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
7918 if (fixed_tx_mode == FIXED_TXMODE_CCK)
7920 TransmitSetting.field.MODE = MODE_CCK;
7921 // CCK mode allow MCS 0~3
7922 if (TransmitSetting.field.MCS > MCS_3)
7923 TransmitSetting.field.MCS = MCS_3;
7925 else
7927 TransmitSetting.field.MODE = MODE_OFDM;
7928 // OFDM mode allow MCS 0~7
7929 if (TransmitSetting.field.MCS > MCS_7)
7930 TransmitSetting.field.MCS = MCS_7;
7933 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
7935 pEntry->HTPhyMode.word = TransmitSetting.word;
7936 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
7937 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
7941 #ifdef CONFIG_STA_SUPPORT
7943 ==========================================================================
7944 Description:
7945 dynamic tune BBP R66 to find a balance between sensibility and
7946 noise isolation
7948 IRQL = DISPATCH_LEVEL
7950 ==========================================================================
7952 VOID AsicStaBbpTuning(
7953 IN PRTMP_ADAPTER pAd)
7955 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
7956 CHAR Rssi;
7958 // 2860C did not support Fase CCA, therefore can't tune
7959 if (pAd->MACVersion == 0x28600100)
7960 return;
7963 // work as a STA
7965 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
7966 return;
7968 if ((pAd->OpMode == OPMODE_STA)
7969 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7971 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
7974 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
7975 R66 = OrigR66Value;
7977 if (pAd->Antenna.field.RxPath > 1)
7978 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
7979 else
7980 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
7982 if (pAd->LatchRfRegs.Channel <= 14)
7983 { //BG band
7984 #ifdef RT2870
7985 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
7986 // Otherwise, it will have some throughput side effect when low RSSI
7987 if (IS_RT3070(pAd))
7989 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7991 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
7992 if (OrigR66Value != R66)
7994 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
7997 else
7999 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8000 if (OrigR66Value != R66)
8002 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8006 else
8007 #endif // RT2870 //
8009 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8011 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8012 if (OrigR66Value != R66)
8014 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8017 else
8019 R66 = 0x2E + GET_LNA_GAIN(pAd);
8020 if (OrigR66Value != R66)
8022 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8027 else
8028 { //A band
8029 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8031 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8033 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8034 if (OrigR66Value != R66)
8036 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8039 else
8041 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8042 if (OrigR66Value != R66)
8044 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8048 else
8050 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8052 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8053 if (OrigR66Value != R66)
8055 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8058 else
8060 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8061 if (OrigR66Value != R66)
8063 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8072 #endif // CONFIG_STA_SUPPORT //
8074 VOID RTMPSetAGCInitValue(
8075 IN PRTMP_ADAPTER pAd,
8076 IN UCHAR BandWidth)
8078 UCHAR R66 = 0x30;
8080 if (pAd->LatchRfRegs.Channel <= 14)
8081 { // BG band
8082 R66 = 0x2E + GET_LNA_GAIN(pAd);
8083 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8085 else
8086 { //A band
8087 if (BandWidth == BW_20)
8089 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8090 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8092 #ifdef DOT11_N_SUPPORT
8093 else
8095 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8096 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8098 #endif // DOT11_N_SUPPORT //
8103 VOID AsicTurnOffRFClk(
8104 IN PRTMP_ADAPTER pAd,
8105 IN UCHAR Channel)
8108 // RF R2 bit 18 = 0
8109 UINT32 R1 = 0, R2 = 0, R3 = 0;
8110 UCHAR index;
8111 RTMP_RF_REGS *RFRegTable;
8113 RFRegTable = RF2850RegTable;
8115 switch (pAd->RfIcType)
8117 case RFIC_2820:
8118 case RFIC_2850:
8119 case RFIC_2720:
8120 case RFIC_2750:
8122 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8124 if (Channel == RFRegTable[index].Channel)
8126 R1 = RFRegTable[index].R1 & 0xffffdfff;
8127 R2 = RFRegTable[index].R2 & 0xfffbffff;
8128 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8130 RTMP_RF_IO_WRITE32(pAd, R1);
8131 RTMP_RF_IO_WRITE32(pAd, R2);
8133 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8134 // Set RF R2 bit18=0, R3 bit[18:19]=0
8135 //if (pAd->StaCfg.bRadio == FALSE)
8136 if (1)
8138 RTMP_RF_IO_WRITE32(pAd, R3);
8140 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8141 Channel, pAd->RfIcType, R2, R3));
8143 else
8144 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8145 Channel, pAd->RfIcType, R2));
8146 break;
8149 break;
8151 default:
8152 break;
8157 VOID AsicTurnOnRFClk(
8158 IN PRTMP_ADAPTER pAd,
8159 IN UCHAR Channel)
8162 // RF R2 bit 18 = 0
8163 UINT32 R1 = 0, R2 = 0, R3 = 0;
8164 UCHAR index;
8165 RTMP_RF_REGS *RFRegTable;
8167 RFRegTable = RF2850RegTable;
8169 switch (pAd->RfIcType)
8171 case RFIC_2820:
8172 case RFIC_2850:
8173 case RFIC_2720:
8174 case RFIC_2750:
8176 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8178 if (Channel == RFRegTable[index].Channel)
8180 R3 = pAd->LatchRfRegs.R3;
8181 R3 &= 0xfff3ffff;
8182 R3 |= 0x00080000;
8183 RTMP_RF_IO_WRITE32(pAd, R3);
8185 R1 = RFRegTable[index].R1;
8186 RTMP_RF_IO_WRITE32(pAd, R1);
8188 R2 = RFRegTable[index].R2;
8189 if (pAd->Antenna.field.TxPath == 1)
8191 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8194 if (pAd->Antenna.field.RxPath == 2)
8196 R2 |= 0x40; // write 1 to off Rxpath.
8198 else if (pAd->Antenna.field.RxPath == 1)
8200 R2 |= 0x20040; // write 1 to off RxPath
8202 RTMP_RF_IO_WRITE32(pAd, R2);
8204 break;
8207 break;
8209 default:
8210 break;
8213 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
8214 Channel,
8215 pAd->RfIcType,
8216 R2));