2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
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. *
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. *
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. *
25 *************************************************************************
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"
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,
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,
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,
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,
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[] = {
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",
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",
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;
350 UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
351 #endif // DOT11N_DRAFT3 //
352 #endif // DOT11_N_SUPPORT //
353 UCHAR ErpIe = IE_ERP;
354 UCHAR DsIe = IE_DS_PARM;
355 UCHAR TimIe = IE_TIM;
356 UCHAR WpaIe = IE_WPA;
357 UCHAR Wpa2Ie = IE_WPA2;
358 UCHAR IbssIe = IE_IBSS_PARM;
359 UCHAR Ccx2Ie = IE_CCX_V2;
360 UCHAR WapiIe = IE_WAPI;
362 extern UCHAR WPA_OUI[];
364 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
366 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
367 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
369 // Reset the RFIC setting to new series
370 RTMP_RF_REGS RF2850RegTable[] = {
371 // ch R1 R2 R3(TX0~4=0) R4
372 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
373 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
374 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
375 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
376 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
377 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
378 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
379 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
380 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
381 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
382 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
383 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
384 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
385 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
387 // 802.11 UNI / HyperLan 2
388 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
389 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
390 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
391 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
392 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
393 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
394 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
395 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
396 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
397 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
398 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
399 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
402 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
404 // 2008.04.30 modified
405 // The system team has AN to improve the EVM value
406 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
407 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
408 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
409 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
411 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
412 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
413 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
414 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
415 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
416 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
417 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
418 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
419 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
420 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
421 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
422 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
425 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
426 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
427 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
428 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
429 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
430 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
431 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
434 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
435 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
436 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
437 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
438 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
439 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
440 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
442 // still lack of MMAC(Japan) ch 34,38,42,46
444 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
446 FREQUENCY_ITEM FreqItems3020[] =
448 /**************************************************/
449 // ISM : 2.4 to 2.483 GHz //
450 /**************************************************/
452 /**************************************************/
453 //-CH---N-------R---K-----------
469 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
472 ==========================================================================
474 initialize the MLME task and its data structure (queue, spinlock,
475 timer, state machines).
480 always return NDIS_STATUS_SUCCESS
482 ==========================================================================
484 NDIS_STATUS MlmeInit(
485 IN PRTMP_ADAPTER pAd)
487 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
489 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
493 Status = MlmeQueueInit(&pAd->Mlme.Queue);
494 if(Status != NDIS_STATUS_SUCCESS)
497 pAd->Mlme.bRunning = FALSE;
498 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
500 #ifdef CONFIG_STA_SUPPORT
501 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
503 BssTableInit(&pAd->ScanTab);
505 // init STA state machines
506 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
507 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
508 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
509 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
510 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
511 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
513 #ifdef QOS_DLS_SUPPORT
514 DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc);
515 #endif // QOS_DLS_SUPPORT //
518 // Since we are using switch/case to implement it, the init is different from the above
519 // state machine init
520 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
522 #endif // CONFIG_STA_SUPPORT //
526 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
528 // Init mlme periodic timer
529 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
531 // Set mlme periodic timer
532 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
534 // software-based RX Antenna diversity
535 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
539 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
545 ==========================================================================
547 main loop of the MLME
549 Mlme has to be initialized, and there are something inside the queue
551 This function is invoked from MPSetInformation and MPReceive;
552 This task guarantee only one MlmeHandler will run.
554 IRQL = DISPATCH_LEVEL
556 ==========================================================================
559 IN PRTMP_ADAPTER pAd)
561 MLME_QUEUE_ELEM *Elem = NULL;
563 // Only accept MLME and Frame from peer side, no other (control/data) frame should
564 // get into this state machine
566 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
567 if(pAd->Mlme.bRunning)
569 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
574 pAd->Mlme.bRunning = TRUE;
576 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
578 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
580 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
581 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
582 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
584 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
588 //From message type, determine which state machine I should drive
589 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
592 if (Elem->MsgType == MT2_RESET_CONF)
594 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
595 MlmeRestartStateMachine(pAd);
596 Elem->Occupied = FALSE;
602 // if dequeue success
603 switch (Elem->Machine)
605 // STA state machines
606 #ifdef CONFIG_STA_SUPPORT
607 case ASSOC_STATE_MACHINE:
608 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
610 case AUTH_STATE_MACHINE:
611 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
613 case AUTH_RSP_STATE_MACHINE:
614 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
616 case SYNC_STATE_MACHINE:
617 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
619 case MLME_CNTL_STATE_MACHINE:
620 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
622 case WPA_PSK_STATE_MACHINE:
623 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
626 case LEAP_STATE_MACHINE:
627 LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
630 case AIRONET_STATE_MACHINE:
631 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
634 #ifdef QOS_DLS_SUPPORT
635 case DLS_STATE_MACHINE:
636 StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem);
638 #endif // QOS_DLS_SUPPORT //
639 #endif // CONFIG_STA_SUPPORT //
641 case ACTION_STATE_MACHINE:
642 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
649 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
654 Elem->Occupied = FALSE;
659 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
663 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
664 pAd->Mlme.bRunning = FALSE;
665 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
669 ==========================================================================
671 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
673 Adapter - NIC Adapter pointer
675 The MLME task will no longer work properly
679 ==========================================================================
682 IN PRTMP_ADAPTER pAd)
686 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
688 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
690 // disable BEACON generation and other BEACON related hardware timers
691 AsicDisableSync(pAd);
694 #ifdef CONFIG_STA_SUPPORT
695 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
697 #ifdef QOS_DLS_SUPPORT
699 #endif // QOS_DLS_SUPPORT //
700 // Cancel pending timers
701 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
702 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
703 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
704 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
705 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
706 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
708 #ifdef QOS_DLS_SUPPORT
709 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
711 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
713 #endif // QOS_DLS_SUPPORT //
715 #endif // CONFIG_STA_SUPPORT //
717 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
718 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
722 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
725 RTMPSetLED(pAd, LED_HALT);
726 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
729 LED_CFG_STRUC LedCfg;
730 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
731 LedCfg.field.LedPolar = 0;
732 LedCfg.field.RLedMode = 0;
733 LedCfg.field.GLedMode = 0;
734 LedCfg.field.YLedMode = 0;
735 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
740 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
742 MlmeQueueDestroy(&pAd->Mlme.Queue);
743 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
745 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
748 VOID MlmeResetRalinkCounters(
749 IN PRTMP_ADAPTER pAd)
751 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
752 // clear all OneSecxxx counters.
753 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
754 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
755 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
756 pAd->RalinkCounters.OneSecRxOkCnt = 0;
757 pAd->RalinkCounters.OneSecTxFailCount = 0;
758 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
759 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
760 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
762 // TODO: for debug only. to be removed
763 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
764 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
765 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
766 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
767 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
768 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
769 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
770 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
771 pAd->RalinkCounters.OneSecTxDoneCount = 0;
772 pAd->RalinkCounters.OneSecRxCount = 0;
773 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
774 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
779 unsigned long rx_AMSDU;
780 unsigned long rx_Total;
783 ==========================================================================
785 This routine is executed periodically to -
786 1. Decide if it's a right time to turn on PwrMgmt bit of all
788 2. Calculate ChannelQuality based on statistics of the last
789 period, so that TX rate won't toggling very frequently between a
790 successful TX and a failed TX.
791 3. If the calculated ChannelQuality indicated current connection not
792 healthy, then a ROAMing attempt is tried here.
794 IRQL = DISPATCH_LEVEL
796 ==========================================================================
798 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
799 VOID MlmePeriodicExec(
800 IN PVOID SystemSpecific1,
801 IN PVOID FunctionContext,
802 IN PVOID SystemSpecific2,
803 IN PVOID SystemSpecific3)
806 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
808 // Do nothing if the driver is starting halt state.
809 // This might happen when timer already been fired before cancel timer with mlmehalt
810 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
811 fRTMP_ADAPTER_RADIO_OFF |
812 fRTMP_ADAPTER_RADIO_MEASUREMENT |
813 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
816 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
818 #ifdef CONFIG_STA_SUPPORT
819 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
821 // Do nothing if monitor mode is on
825 if (pAd->Mlme.PeriodicRound & 0x1)
827 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
828 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
829 (STA_TGN_WIFI_ON(pAd)) &&
830 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
833 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
834 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
836 else if ((STA_TGN_WIFI_ON(pAd)) &&
837 ((pAd->MACVersion & 0xffff) == 0x0101))
839 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
840 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
844 #endif // CONFIG_STA_SUPPORT //
846 pAd->bUpdateBcnCntDone = FALSE;
848 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
849 pAd->Mlme.PeriodicRound ++;
851 // execute every 500ms
852 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
854 #ifdef CONFIG_STA_SUPPORT
855 // perform dynamic tx rate switching based on past TX history
856 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
858 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
860 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
861 MlmeDynamicTxRateSwitching(pAd);
863 #endif // CONFIG_STA_SUPPORT //
866 // Normal 1 second Mlme PeriodicExec.
867 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
869 pAd->Mlme.OneSecPeriodicRound ++;
879 //ORIBATimerTimeout(pAd);
881 // Media status changed, report to NDIS
882 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
884 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
885 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
887 pAd->IndicateMediaState = NdisMediaStateConnected;
888 RTMP_IndicateMediaState(pAd);
893 pAd->IndicateMediaState = NdisMediaStateDisconnected;
894 RTMP_IndicateMediaState(pAd);
898 NdisGetSystemUpTime(&pAd->Mlme.Now32);
900 // add the most up-to-date h/w raw counters into software variable, so that
901 // the dynamic tuning mechanism below are based on most up-to-date information
902 NICUpdateRawCounters(pAd);
905 RT2870_WatchDog(pAd);
908 #ifdef DOT11_N_SUPPORT
909 // Need statistics after read counter. So put after NICUpdateRawCounters
910 ORIBATimerTimeout(pAd);
911 #endif // DOT11_N_SUPPORT //
913 // if MGMT RING is full more than twice within 1 second, we consider there's
914 // a hardware problem stucking the TX path. In this case, try a hardware reset
915 // to recover the system
916 // if (pAd->RalinkCounters.MgmtRingFullCount >= 2)
917 // RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR);
919 // pAd->RalinkCounters.MgmtRingFullCount = 0;
921 // The time period for checking antenna is according to traffic
922 if (pAd->Mlme.bEnableAutoAntennaCheck)
924 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
925 pAd->RalinkCounters.OneSecTxRetryOkCount +
926 pAd->RalinkCounters.OneSecTxFailCount;
930 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
932 AsicEvaluateRxAnt(pAd);
937 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
939 AsicEvaluateRxAnt(pAd);
944 #ifdef CONFIG_STA_SUPPORT
945 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
946 STAMlmePeriodicExec(pAd);
947 #endif // CONFIG_STA_SUPPORT //
949 MlmeResetRalinkCounters(pAd);
951 #ifdef CONFIG_STA_SUPPORT
952 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
955 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
956 // and sending CTS-to-self over and over.
957 // Software Patch Solution:
958 // 1. Polling debug state register 0x10F4 every one second.
959 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
960 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
964 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
965 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
967 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
969 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
971 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
975 #endif // CONFIG_STA_SUPPORT //
977 RT28XX_MLME_HANDLER(pAd);
981 pAd->bUpdateBcnCntDone = FALSE;
984 #ifdef CONFIG_STA_SUPPORT
985 VOID STAMlmePeriodicExec(
991 #ifdef WPA_SUPPLICANT_SUPPORT
992 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
993 #endif // WPA_SUPPLICANT_SUPPORT //
995 // WPA MIC error should block association attempt for 60 seconds
996 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
997 pAd->StaCfg.bBlockAssoc = FALSE;
1000 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1002 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1004 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1006 pAd->PreMediaState = pAd->IndicateMediaState;
1012 AsicStaBbpTuning(pAd);
1014 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1015 pAd->RalinkCounters.OneSecTxRetryOkCount +
1016 pAd->RalinkCounters.OneSecTxFailCount;
1018 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1020 // update channel quality for Roaming and UI LinkQuality display
1021 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1024 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1025 // Radio is currently in noisy environment
1026 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1027 AsicAdjustTxPower(pAd);
1031 #ifdef QOS_DLS_SUPPORT
1032 // Check DLS time out, then tear down those session
1033 RTMPCheckDLSTimeOut(pAd);
1034 #endif // QOS_DLS_SUPPORT //
1036 // Is PSM bit consistent with user power management policy?
1037 // This is the only place that will set PSM bit ON.
1038 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1039 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1041 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1043 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1044 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1045 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1047 RTMPSetAGCInitValue(pAd, BW_20);
1048 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1051 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1052 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1054 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1056 // When APSD is enabled, the period changes as 20 sec
1057 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1058 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1062 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1063 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1065 if (pAd->CommonCfg.bWmmCapable)
1066 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1068 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1073 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1075 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1076 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1077 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1079 // Lost AP, send disconnect & link down event
1080 LinkDown(pAd, FALSE);
1082 #ifdef WPA_SUPPLICANT_SUPPORT
1083 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1084 if (pAd->StaCfg.WpaSupplicantUP)
1086 union iwreq_data wrqu;
1087 //send disassociate event to wpa_supplicant
1088 memset(&wrqu, 0, sizeof(wrqu));
1089 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1090 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1092 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1093 #endif // WPA_SUPPLICANT_SUPPORT //
1095 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1097 union iwreq_data wrqu;
1098 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1099 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1101 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1103 // RTMPPatchMacBbpBug(pAd);
1104 MlmeAutoReconnectLastSSID(pAd);
1106 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1108 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1109 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1110 MlmeAutoReconnectLastSSID(pAd);
1113 // Add auto seamless roaming
1114 if (pAd->StaCfg.bFastRoaming)
1116 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1118 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));
1120 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1122 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1126 else if (ADHOC_ON(pAd))
1129 if ((pAd->CommonCfg.Channel > 14)
1130 && (pAd->CommonCfg.bIEEE80211H == 1)
1131 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1133 RadarDetectPeriodic(pAd);
1136 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1137 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1139 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1140 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1142 MLME_START_REQ_STRUCT StartReq;
1144 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1145 LinkDown(pAd, FALSE);
1147 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1148 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1149 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1152 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1154 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1156 if (pEntry->ValidAsCLI == FALSE)
1159 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1160 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1163 else // no INFRA nor ADHOC connection
1166 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1167 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1168 goto SKIP_AUTO_SCAN_CONN;
1170 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1172 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1173 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1174 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1176 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1178 MLME_SCAN_REQ_STRUCT ScanReq;
1180 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1182 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1183 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1184 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1185 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1186 // Reset Missed scan number
1187 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1189 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1190 MlmeAutoReconnectLastSSID(pAd);
1192 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1194 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1197 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1201 MlmeAutoReconnectLastSSID(pAd);
1207 SKIP_AUTO_SCAN_CONN:
1209 #ifdef DOT11_N_SUPPORT
1210 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1212 pAd->MacTab.fAnyBASession = TRUE;
1213 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1215 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1217 pAd->MacTab.fAnyBASession = FALSE;
1218 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1220 #endif // DOT11_N_SUPPORT //
1223 #ifdef DOT11_N_SUPPORT
1224 #ifdef DOT11N_DRAFT3
1225 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1226 TriEventCounterMaintenance(pAd);
1227 #endif // DOT11N_DRAFT3 //
1228 #endif // DOT11_N_SUPPORT //
1235 IN PVOID SystemSpecific1,
1236 IN PVOID FunctionContext,
1237 IN PVOID SystemSpecific2,
1238 IN PVOID SystemSpecific3)
1241 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1243 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1244 RTMP_IndicateMediaState(pAd);
1245 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1248 // IRQL = DISPATCH_LEVEL
1250 IN PRTMP_ADAPTER pAd)
1252 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1253 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1255 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1257 MLME_CNTL_STATE_MACHINE,
1258 OID_802_11_BSSID_LIST_SCAN,
1261 RT28XX_MLME_HANDLER(pAd);
1265 // IRQL = DISPATCH_LEVEL
1266 VOID MlmeAutoReconnectLastSSID(
1267 IN PRTMP_ADAPTER pAd)
1271 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1272 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1273 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1275 NDIS_802_11_SSID OidSsid;
1276 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1277 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1279 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1281 MLME_CNTL_STATE_MACHINE,
1283 sizeof(NDIS_802_11_SSID),
1285 RT28XX_MLME_HANDLER(pAd);
1288 #endif // CONFIG_STA_SUPPORT //
1291 ==========================================================================
1292 Validate SSID for connection try and rescan purpose
1293 Valid SSID will have visible chars only.
1294 The valid length is from 0 to 32.
1295 IRQL = DISPATCH_LEVEL
1296 ==========================================================================
1298 BOOLEAN MlmeValidateSSID(
1304 if (SsidLen > MAX_LEN_OF_SSID)
1307 // Check each character value
1308 for (index = 0; index < SsidLen; index++)
1310 if (pSsid[index] < 0x20)
1318 VOID MlmeSelectTxRateTable(
1319 IN PRTMP_ADAPTER pAd,
1320 IN PMAC_TABLE_ENTRY pEntry,
1322 IN PUCHAR pTableSize,
1323 IN PUCHAR pInitTxRateIdx)
1327 // decide the rate table for tuning
1328 if (pAd->CommonCfg.TxRateTableSize > 0)
1330 *ppTable = RateSwitchTable;
1331 *pTableSize = RateSwitchTable[0];
1332 *pInitTxRateIdx = RateSwitchTable[1];
1337 #ifdef CONFIG_STA_SUPPORT
1338 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1340 #ifdef DOT11_N_SUPPORT
1341 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1342 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1343 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1345 *ppTable = RateSwitchTable11N1S;
1346 *pTableSize = RateSwitchTable11N1S[0];
1347 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1350 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1351 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1352 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1353 (pAd->Antenna.field.TxPath == 2))
1355 if (pAd->LatchRfRegs.Channel <= 14)
1357 *ppTable = RateSwitchTable11N2S;
1358 *pTableSize = RateSwitchTable11N2S[0];
1359 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1363 *ppTable = RateSwitchTable11N2SForABand;
1364 *pTableSize = RateSwitchTable11N2SForABand[0];
1365 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1370 #endif // DOT11_N_SUPPORT //
1371 if ((pEntry->RateLen == 4)
1372 #ifdef DOT11_N_SUPPORT
1373 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1374 #endif // DOT11_N_SUPPORT //
1377 *ppTable = RateSwitchTable11B;
1378 *pTableSize = RateSwitchTable11B[0];
1379 *pInitTxRateIdx = RateSwitchTable11B[1];
1382 else if (pAd->LatchRfRegs.Channel <= 14)
1384 *ppTable = RateSwitchTable11BG;
1385 *pTableSize = RateSwitchTable11BG[0];
1386 *pInitTxRateIdx = RateSwitchTable11BG[1];
1391 *ppTable = RateSwitchTable11G;
1392 *pTableSize = RateSwitchTable11G[0];
1393 *pInitTxRateIdx = RateSwitchTable11G[1];
1398 #endif // CONFIG_STA_SUPPORT //
1400 #ifdef DOT11_N_SUPPORT
1401 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1402 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1403 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1404 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1406 *ppTable = RateSwitchTable11BGN1S;
1407 *pTableSize = RateSwitchTable11BGN1S[0];
1408 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1413 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1414 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1415 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1416 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1418 if (pAd->LatchRfRegs.Channel <= 14)
1420 *ppTable = RateSwitchTable11BGN2S;
1421 *pTableSize = RateSwitchTable11BGN2S[0];
1422 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1427 *ppTable = RateSwitchTable11BGN2SForABand;
1428 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1429 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1435 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1436 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1438 *ppTable = RateSwitchTable11N1S;
1439 *pTableSize = RateSwitchTable11N1S[0];
1440 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1445 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1446 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1448 if (pAd->LatchRfRegs.Channel <= 14)
1450 *ppTable = RateSwitchTable11N2S;
1451 *pTableSize = RateSwitchTable11N2S[0];
1452 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1456 *ppTable = RateSwitchTable11N2SForABand;
1457 *pTableSize = RateSwitchTable11N2SForABand[0];
1458 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1463 #endif // DOT11_N_SUPPORT //
1464 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1465 if ((pEntry->RateLen == 4)
1466 #ifdef DOT11_N_SUPPORT
1467 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1468 #endif // DOT11_N_SUPPORT //
1471 *ppTable = RateSwitchTable11B;
1472 *pTableSize = RateSwitchTable11B[0];
1473 *pInitTxRateIdx = RateSwitchTable11B[1];
1478 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1479 if ((pEntry->RateLen > 8)
1480 #ifdef DOT11_N_SUPPORT
1481 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1482 #endif // DOT11_N_SUPPORT //
1485 *ppTable = RateSwitchTable11BG;
1486 *pTableSize = RateSwitchTable11BG[0];
1487 *pInitTxRateIdx = RateSwitchTable11BG[1];
1492 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1493 if ((pEntry->RateLen == 8)
1494 #ifdef DOT11_N_SUPPORT
1495 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1496 #endif // DOT11_N_SUPPORT //
1499 *ppTable = RateSwitchTable11G;
1500 *pTableSize = RateSwitchTable11G[0];
1501 *pInitTxRateIdx = RateSwitchTable11G[1];
1505 #ifdef DOT11_N_SUPPORT
1506 #endif // DOT11_N_SUPPORT //
1508 #ifdef CONFIG_STA_SUPPORT
1509 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1511 #ifdef DOT11_N_SUPPORT
1512 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1513 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1514 #endif // DOT11_N_SUPPORT //
1516 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1518 *ppTable = RateSwitchTable11B;
1519 *pTableSize = RateSwitchTable11B[0];
1520 *pInitTxRateIdx = RateSwitchTable11B[1];
1522 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1524 *ppTable = RateSwitchTable11G;
1525 *pTableSize = RateSwitchTable11G[0];
1526 *pInitTxRateIdx = RateSwitchTable11G[1];
1531 *ppTable = RateSwitchTable11BG;
1532 *pTableSize = RateSwitchTable11BG[0];
1533 *pInitTxRateIdx = RateSwitchTable11BG[1];
1537 #ifdef DOT11_N_SUPPORT
1538 if (pAd->LatchRfRegs.Channel <= 14)
1540 if (pAd->CommonCfg.TxStream == 1)
1542 *ppTable = RateSwitchTable11N1S;
1543 *pTableSize = RateSwitchTable11N1S[0];
1544 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1545 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1549 *ppTable = RateSwitchTable11N2S;
1550 *pTableSize = RateSwitchTable11N2S[0];
1551 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1552 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1557 if (pAd->CommonCfg.TxStream == 1)
1559 *ppTable = RateSwitchTable11N1S;
1560 *pTableSize = RateSwitchTable11N1S[0];
1561 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1562 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1566 *ppTable = RateSwitchTable11N2SForABand;
1567 *pTableSize = RateSwitchTable11N2SForABand[0];
1568 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1569 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1572 #endif // DOT11_N_SUPPORT //
1573 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1574 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1576 #endif // CONFIG_STA_SUPPORT //
1580 #ifdef CONFIG_STA_SUPPORT
1582 ==========================================================================
1584 This routine checks if there're other APs out there capable for
1585 roaming. Caller should call this routine only when Link up in INFRA mode
1586 and channel quality is below CQI_GOOD_THRESHOLD.
1588 IRQL = DISPATCH_LEVEL
1591 ==========================================================================
1593 VOID MlmeCheckForRoaming(
1594 IN PRTMP_ADAPTER pAd,
1598 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1601 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1602 // put all roaming candidates into RoamTab, and sort in RSSI order
1603 BssTableInit(pRoamTab);
1604 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1606 pBss = &pAd->ScanTab.BssEntry[i];
1608 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1609 continue; // AP disappear
1610 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1611 continue; // RSSI too weak. forget it.
1612 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1613 continue; // skip current AP
1614 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1615 continue; // only AP with stronger RSSI is eligible for roaming
1617 // AP passing all above rules is put into roaming candidate table
1618 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1619 pRoamTab->BssNr += 1;
1622 if (pRoamTab->BssNr > 0)
1624 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1625 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1627 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1628 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1629 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1630 RT28XX_MLME_HANDLER(pAd);
1633 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1637 ==========================================================================
1639 This routine checks if there're other APs out there capable for
1640 roaming. Caller should call this routine only when link up in INFRA mode
1641 and channel quality is below CQI_GOOD_THRESHOLD.
1643 IRQL = DISPATCH_LEVEL
1646 ==========================================================================
1648 VOID MlmeCheckForFastRoaming(
1649 IN PRTMP_ADAPTER pAd,
1653 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1656 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1657 // put all roaming candidates into RoamTab, and sort in RSSI order
1658 BssTableInit(pRoamTab);
1659 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1661 pBss = &pAd->ScanTab.BssEntry[i];
1663 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1664 continue; // RSSI too weak. forget it.
1665 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1666 continue; // skip current AP
1667 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1668 continue; // skip different SSID
1669 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1670 continue; // skip AP without better RSSI
1672 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));
1673 // AP passing all above rules is put into roaming candidate table
1674 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1675 pRoamTab->BssNr += 1;
1678 if (pRoamTab->BssNr > 0)
1680 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1681 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1683 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1684 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1685 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1686 RT28XX_MLME_HANDLER(pAd);
1689 // Maybe site survey required
1692 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1694 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1695 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1696 pAd->StaCfg.ScanCnt = 2;
1697 pAd->StaCfg.LastScanTime = Now;
1702 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1706 ==========================================================================
1708 This routine calculates TxPER, RxPER of the past N-sec period. And
1709 according to the calculation result, ChannelQuality is calculated here
1710 to decide if current AP is still doing the job.
1712 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1714 StaCfg.ChannelQuality - 0..100
1716 IRQL = DISPATCH_LEVEL
1718 NOTE: This routine decide channle quality based on RX CRC error ratio.
1719 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1720 is performed right before this routine, so that this routine can decide
1721 channel quality based on the most up-to-date information
1722 ==========================================================================
1724 VOID MlmeCalculateChannelQuality(
1725 IN PRTMP_ADAPTER pAd,
1728 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1732 ULONG BeaconLostTime = BEACON_LOST_TIME;
1734 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1737 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1739 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1740 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1748 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1749 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1753 // calculate RX PER - don't take RxPER into consideration if too few sample
1755 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1759 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1762 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1764 if (INFRA_ON(pAd) &&
1765 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1766 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1768 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1769 pAd->Mlme.ChannelQuality = 0;
1776 else if (MaxRssi < -90)
1779 NorRssi = (MaxRssi + 90) * 2;
1781 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1782 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1783 TX_WEIGHTING * (100 - TxPRR) +
1784 RX_WEIGHTING* (100 - RxPER)) / 100;
1785 if (pAd->Mlme.ChannelQuality >= 100)
1786 pAd->Mlme.ChannelQuality = 100;
1792 IN PRTMP_ADAPTER pAd,
1793 IN PMAC_TABLE_ENTRY pEntry,
1794 IN PRTMP_TX_RATE_SWITCH pTxRate)
1796 UCHAR MaxMode = MODE_OFDM;
1798 #ifdef DOT11_N_SUPPORT
1799 MaxMode = MODE_HTGREENFIELD;
1801 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1802 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1804 #endif // DOT11_N_SUPPORT //
1805 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1807 if (pTxRate->CurrMCS < MCS_AUTO)
1808 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1810 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1811 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1815 // If peer adhoc is b-only mode, we can't send 11g rate.
1816 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1817 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1820 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1822 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1823 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1824 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1826 // Patch speed error in status page
1827 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1831 if (pTxRate->Mode <= MaxMode)
1832 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1834 #ifdef DOT11_N_SUPPORT
1835 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1836 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1838 #endif // DOT11_N_SUPPORT //
1839 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1841 #ifdef DOT11_N_SUPPORT
1842 // Reexam each bandwidth's SGI support.
1843 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1845 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1846 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1847 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1848 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1851 // Turn RTS/CTS rate to 6Mbps.
1852 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1854 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1855 if (pAd->MacTab.fAnyBASession)
1857 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1861 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1864 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1866 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1867 if (pAd->MacTab.fAnyBASession)
1869 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1873 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1876 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1878 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1881 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1883 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1885 #endif // DOT11_N_SUPPORT //
1887 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1888 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1889 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1890 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1891 #ifdef DOT11_N_SUPPORT
1892 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1893 pAd->WIFItestbed.bGreenField)
1894 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1895 #endif // DOT11_N_SUPPORT //
1898 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1902 ==========================================================================
1904 This routine calculates the acumulated TxPER of eaxh TxRate. And
1905 according to the calculation result, change CommonCfg.TxRate which
1906 is the stable TX Rate we expect the Radio situation could sustained.
1908 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1912 IRQL = DISPATCH_LEVEL
1915 call this routine every second
1916 ==========================================================================
1918 VOID MlmeDynamicTxRateSwitching(
1919 IN PRTMP_ADAPTER pAd)
1921 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1922 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1923 ULONG TxErrorRatio = 0;
1924 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1925 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1927 UCHAR TableSize = 0;
1928 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1929 CHAR Rssi, RssiOffset = 0;
1930 TX_STA_CNT1_STRUC StaTx1;
1931 TX_STA_CNT0_STRUC TxStaCnt0;
1932 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1933 MAC_TABLE_ENTRY *pEntry;
1936 // walk through MAC table, see if need to change AP's TX rate toward each entry
1938 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1940 pEntry = &pAd->MacTab.Content[i];
1942 // check if this entry need to switch rate automatically
1943 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1946 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1948 Rssi = RTMPMaxRssi(pAd,
1949 pAd->StaCfg.RssiSample.AvgRssi0,
1950 pAd->StaCfg.RssiSample.AvgRssi1,
1951 pAd->StaCfg.RssiSample.AvgRssi2);
1953 // Update statistic counter
1954 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1955 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1956 pAd->bUpdateBcnCntDone = TRUE;
1957 TxRetransmit = StaTx1.field.TxRetransmit;
1958 TxSuccess = StaTx1.field.TxSuccess;
1959 TxFailCount = TxStaCnt0.field.TxFailCount;
1960 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1962 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1963 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1964 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1965 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1966 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1967 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1969 // if no traffic in the past 1-sec period, don't change TX rate,
1970 // but clear all bad history. because the bad history may affect the next
1971 // Chariot throughput test
1972 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1973 pAd->RalinkCounters.OneSecTxRetryOkCount +
1974 pAd->RalinkCounters.OneSecTxFailCount;
1977 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1981 if (INFRA_ON(pAd) && (i == 1))
1982 Rssi = RTMPMaxRssi(pAd,
1983 pAd->StaCfg.RssiSample.AvgRssi0,
1984 pAd->StaCfg.RssiSample.AvgRssi1,
1985 pAd->StaCfg.RssiSample.AvgRssi2);
1987 Rssi = RTMPMaxRssi(pAd,
1988 pEntry->RssiSample.AvgRssi0,
1989 pEntry->RssiSample.AvgRssi1,
1990 pEntry->RssiSample.AvgRssi2);
1992 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1993 pEntry->OneSecTxRetryOkCount +
1994 pEntry->OneSecTxFailCount;
1997 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2000 CurrRateIdx = pEntry->CurrTxRateIndex;
2002 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2004 if (CurrRateIdx >= TableSize)
2006 CurrRateIdx = TableSize - 1;
2009 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2010 // So need to sync here.
2011 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2012 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2013 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2017 // Need to sync Real Tx rate and our record.
2018 // Then return for next DRS.
2019 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2020 pEntry->CurrTxRateIndex = InitTxRateIdx;
2021 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2023 // reset all OneSecTx counters
2024 RESET_ONE_SEC_TX_CNT(pEntry);
2028 // decide the next upgrade rate and downgrade rate, if any
2029 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2031 UpRateIdx = CurrRateIdx + 1;
2032 DownRateIdx = CurrRateIdx -1;
2034 else if (CurrRateIdx == 0)
2036 UpRateIdx = CurrRateIdx + 1;
2037 DownRateIdx = CurrRateIdx;
2039 else if (CurrRateIdx == (TableSize - 1))
2041 UpRateIdx = CurrRateIdx;
2042 DownRateIdx = CurrRateIdx - 1;
2045 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2047 #ifdef DOT11_N_SUPPORT
2048 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2050 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2051 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2054 #endif // DOT11_N_SUPPORT //
2056 TrainUp = pCurrTxRate->TrainUp;
2057 TrainDown = pCurrTxRate->TrainDown;
2060 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2063 // Keep the last time TxRateChangeAction status.
2065 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2070 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2071 // (criteria copied from RT2500 for Netopia case)
2073 if (TxTotalCnt <= 15)
2077 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2078 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2079 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2080 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2082 // check the existence and index of each needed MCS
2083 while (idx < pTable[0])
2085 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2087 if (pCurrTxRate->CurrMCS == MCS_0)
2091 else if (pCurrTxRate->CurrMCS == MCS_1)
2095 else if (pCurrTxRate->CurrMCS == MCS_2)
2099 else if (pCurrTxRate->CurrMCS == MCS_3)
2103 else if (pCurrTxRate->CurrMCS == MCS_4)
2107 else if (pCurrTxRate->CurrMCS == MCS_5)
2111 else if (pCurrTxRate->CurrMCS == MCS_6)
2115 //else if (pCurrTxRate->CurrMCS == MCS_7)
2116 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2120 else if (pCurrTxRate->CurrMCS == MCS_12)
2124 else if (pCurrTxRate->CurrMCS == MCS_13)
2128 else if (pCurrTxRate->CurrMCS == MCS_14)
2132 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2133 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
2137 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2141 else if (pCurrTxRate->CurrMCS == MCS_21)
2145 else if (pCurrTxRate->CurrMCS == MCS_22)
2149 else if (pCurrTxRate->CurrMCS == MCS_23)
2156 if (pAd->LatchRfRegs.Channel <= 14)
2158 if (pAd->NicConfig2.field.ExternalLNAForG)
2169 if (pAd->NicConfig2.field.ExternalLNAForA)
2178 #ifdef DOT11_N_SUPPORT
2180 if ((pTable == RateSwitchTable11BGN3S) ||
2181 (pTable == RateSwitchTable11N3S) ||
2182 (pTable == RateSwitchTable))
2183 {// N mode with 3 stream // 3*3
2184 if (MCS23 && (Rssi >= -70))
2186 else if (MCS22 && (Rssi >= -72))
2188 else if (MCS21 && (Rssi >= -76))
2190 else if (MCS20 && (Rssi >= -78))
2192 else if (MCS4 && (Rssi >= -82))
2194 else if (MCS3 && (Rssi >= -84))
2196 else if (MCS2 && (Rssi >= -86))
2198 else if (MCS1 && (Rssi >= -88))
2203 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2204 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2205 {// N mode with 2 stream
2206 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2208 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2210 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2212 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2214 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2216 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2218 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2220 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2225 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2226 {// N mode with 1 stream
2227 if (MCS7 && (Rssi > (-72+RssiOffset)))
2229 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2231 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2233 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2235 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2237 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2239 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2245 #endif // DOT11_N_SUPPORT //
2247 if (MCS7 && (Rssi > -70))
2249 else if (MCS6 && (Rssi > -74))
2251 else if (MCS5 && (Rssi > -78))
2253 else if (MCS4 && (Rssi > -82))
2255 else if (MCS4 == 0) // for B-only mode
2257 else if (MCS3 && (Rssi > -85))
2259 else if (MCS2 && (Rssi > -87))
2261 else if (MCS1 && (Rssi > -90))
2267 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2269 pEntry->CurrTxRateIndex = TxRateIdx;
2270 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2271 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2274 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2275 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2276 pEntry->fLastSecAccordingRSSI = TRUE;
2277 // reset all OneSecTx counters
2278 RESET_ONE_SEC_TX_CNT(pEntry);
2283 if (pEntry->fLastSecAccordingRSSI == TRUE)
2285 pEntry->fLastSecAccordingRSSI = FALSE;
2286 pEntry->LastSecTxRateChangeAction = 0;
2287 // reset all OneSecTx counters
2288 RESET_ONE_SEC_TX_CNT(pEntry);
2295 BOOLEAN bTrainUpDown = FALSE;
2297 pEntry->CurrTxRateStableTime ++;
2299 // downgrade TX quality if PER >= Rate-Down threshold
2300 if (TxErrorRatio >= TrainDown)
2302 bTrainUpDown = TRUE;
2303 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2305 // upgrade TX quality if PER <= Rate-Up threshold
2306 else if (TxErrorRatio <= TrainUp)
2308 bTrainUpDown = TRUE;
2309 bUpgradeQuality = TRUE;
2310 if (pEntry->TxQuality[CurrRateIdx])
2311 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2313 if (pEntry->TxRateUpPenalty)
2314 pEntry->TxRateUpPenalty --;
2315 else if (pEntry->TxQuality[UpRateIdx])
2316 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2319 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2323 // perform DRS - consider TxRate Down first, then rate up.
2324 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2326 pEntry->CurrTxRateIndex = DownRateIdx;
2328 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2330 pEntry->CurrTxRateIndex = UpRateIdx;
2335 // if rate-up happen, clear all bad history of all TX rates
2336 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2338 pEntry->CurrTxRateStableTime = 0;
2339 pEntry->TxRateUpPenalty = 0;
2340 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2341 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2342 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2345 // For TxRate fast train up
2347 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2349 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2351 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2353 bTxRateChanged = TRUE;
2355 // if rate-down happen, only clear DownRate's bad history
2356 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2358 pEntry->CurrTxRateStableTime = 0;
2359 pEntry->TxRateUpPenalty = 0; // no penalty
2360 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2361 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2362 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2365 // For TxRate fast train down
2367 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2369 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2371 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2373 bTxRateChanged = TRUE;
2377 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2378 bTxRateChanged = FALSE;
2381 pEntry->LastTxOkCount = TxSuccess;
2383 // reset all OneSecTx counters
2384 RESET_ONE_SEC_TX_CNT(pEntry);
2386 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2387 if (bTxRateChanged && pNextTxRate)
2389 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2395 ========================================================================
2396 Routine Description:
2397 Station side, Auto TxRate faster train up timer call back function.
2400 SystemSpecific1 - Not used.
2401 FunctionContext - Pointer to our Adapter context.
2402 SystemSpecific2 - Not used.
2403 SystemSpecific3 - Not used.
2408 ========================================================================
2410 VOID StaQuickResponeForRateUpExec(
2411 IN PVOID SystemSpecific1,
2412 IN PVOID FunctionContext,
2413 IN PVOID SystemSpecific2,
2414 IN PVOID SystemSpecific3)
2416 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2417 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2419 ULONG TxErrorRatio = 0;
2420 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2421 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2423 UCHAR TableSize = 0;
2424 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2425 TX_STA_CNT1_STRUC StaTx1;
2426 TX_STA_CNT0_STRUC TxStaCnt0;
2428 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2429 MAC_TABLE_ENTRY *pEntry;
2432 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2435 // walk through MAC table, see if need to change AP's TX rate toward each entry
2437 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2439 pEntry = &pAd->MacTab.Content[i];
2441 // check if this entry need to switch rate automatically
2442 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2445 if (INFRA_ON(pAd) && (i == 1))
2446 Rssi = RTMPMaxRssi(pAd,
2447 pAd->StaCfg.RssiSample.AvgRssi0,
2448 pAd->StaCfg.RssiSample.AvgRssi1,
2449 pAd->StaCfg.RssiSample.AvgRssi2);
2451 Rssi = RTMPMaxRssi(pAd,
2452 pEntry->RssiSample.AvgRssi0,
2453 pEntry->RssiSample.AvgRssi1,
2454 pEntry->RssiSample.AvgRssi2);
2456 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2458 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2460 // decide the next upgrade rate and downgrade rate, if any
2461 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2463 UpRateIdx = CurrRateIdx + 1;
2464 DownRateIdx = CurrRateIdx -1;
2466 else if (CurrRateIdx == 0)
2468 UpRateIdx = CurrRateIdx + 1;
2469 DownRateIdx = CurrRateIdx;
2471 else if (CurrRateIdx == (TableSize - 1))
2473 UpRateIdx = CurrRateIdx;
2474 DownRateIdx = CurrRateIdx - 1;
2477 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2479 #ifdef DOT11_N_SUPPORT
2480 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2482 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2483 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2486 #endif // DOT11_N_SUPPORT //
2488 TrainUp = pCurrTxRate->TrainUp;
2489 TrainDown = pCurrTxRate->TrainDown;
2492 if (pAd->MacTab.Size == 1)
2494 // Update statistic counter
2495 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2496 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2498 TxRetransmit = StaTx1.field.TxRetransmit;
2499 TxSuccess = StaTx1.field.TxSuccess;
2500 TxFailCount = TxStaCnt0.field.TxFailCount;
2501 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2503 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2504 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2505 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2506 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2507 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2508 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2510 #if 0 // test by Gary.
2511 // if no traffic in the past 1-sec period, don't change TX rate,
2512 // but clear all bad history. because the bad history may affect the next
2513 // Chariot throughput test
2514 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2515 pAd->RalinkCounters.OneSecTxRetryOkCount +
2516 pAd->RalinkCounters.OneSecTxFailCount;
2519 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2523 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2524 pEntry->OneSecTxRetryOkCount +
2525 pEntry->OneSecTxFailCount;
2528 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2533 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2534 // (criteria copied from RT2500 for Netopia case)
2536 if (TxTotalCnt <= 12)
2538 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2539 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2541 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2543 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2544 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2546 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2548 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2551 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2557 ULONG OneSecTxNoRetryOKRationCount;
2559 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2564 // downgrade TX quality if PER >= Rate-Down threshold
2565 if (TxErrorRatio >= TrainDown)
2567 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2570 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2572 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2574 // perform DRS - consider TxRate Down first, then rate up.
2575 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2577 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2579 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2580 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2585 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2587 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2591 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2593 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2598 // if rate-up happen, clear all bad history of all TX rates
2599 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2601 pAd->DrsCounters.TxRateUpPenalty = 0;
2602 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2603 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2604 bTxRateChanged = TRUE;
2606 // if rate-down happen, only clear DownRate's bad history
2607 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2609 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2611 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2612 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2613 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2614 bTxRateChanged = TRUE;
2618 bTxRateChanged = FALSE;
2621 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2622 if (bTxRateChanged && pNextTxRate)
2624 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2630 ==========================================================================
2632 This routine is executed periodically inside MlmePeriodicExec() after
2633 association with an AP.
2634 It checks if StaCfg.Psm is consistent with user policy (recorded in
2635 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2636 there're some conditions to consider:
2637 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2638 the time when Mibss==TRUE
2639 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2640 if outgoing traffic available in TxRing or MgmtRing.
2642 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2644 IRQL = DISPATCH_LEVEL
2646 ==========================================================================
2648 VOID MlmeCheckPsmChange(
2649 IN PRTMP_ADAPTER pAd,
2655 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2656 // 2. user wants either MAX_PSP or FAST_PSP
2657 // 3. but current psm is not in PWR_SAVE
2658 // 4. CNTL state machine is not doing SCANning
2659 // 5. no TX SUCCESS event for the past 1-sec period
2660 #ifdef NDIS51_MINIPORT
2661 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2662 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2665 PowerMode = pAd->StaCfg.WindowsPowerMode;
2667 if (INFRA_ON(pAd) &&
2668 (PowerMode != Ndis802_11PowerModeCAM) &&
2669 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2670 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2671 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2672 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2673 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2675 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2676 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2677 MlmeSetPsmBit(pAd, PWR_SAVE);
2678 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2680 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2684 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2689 // IRQL = PASSIVE_LEVEL
2690 // IRQL = DISPATCH_LEVEL
2692 IN PRTMP_ADAPTER pAd,
2695 AUTO_RSP_CFG_STRUC csr4;
2697 pAd->StaCfg.Psm = psm;
2698 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2699 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2700 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2701 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2703 #endif // CONFIG_STA_SUPPORT //
2706 // IRQL = DISPATCH_LEVEL
2707 VOID MlmeSetTxPreamble(
2708 IN PRTMP_ADAPTER pAd,
2709 IN USHORT TxPreamble)
2711 AUTO_RSP_CFG_STRUC csr4;
2714 // Always use Long preamble before verifiation short preamble functionality works well.
2715 // Todo: remove the following line if short preamble functionality works
2717 //TxPreamble = Rt802_11PreambleLong;
2719 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2720 if (TxPreamble == Rt802_11PreambleLong)
2722 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2723 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2724 csr4.field.AutoResponderPreamble = 0;
2728 // NOTE: 1Mbps should always use long preamble
2729 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2730 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2731 csr4.field.AutoResponderPreamble = 1;
2734 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2738 ==========================================================================
2740 Update basic rate bitmap
2741 ==========================================================================
2744 VOID UpdateBasicRateBitmap(
2745 IN PRTMP_ADAPTER pAdapter)
2748 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2749 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2750 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2751 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2752 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2755 /* if A mode, always use fix BasicRateBitMap */
2756 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2757 if (pAdapter->CommonCfg.Channel > 14)
2758 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2761 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2763 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2767 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2773 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2775 if (bitmap & (1 << i))
2777 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2779 if (sup_p[j] == rate[i])
2784 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2786 if (ext_p[j] == rate[i])
2792 } /* End of UpdateBasicRateBitmap */
2794 // IRQL = PASSIVE_LEVEL
2795 // IRQL = DISPATCH_LEVEL
2796 // bLinkUp is to identify the inital link speed.
2797 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2798 VOID MlmeUpdateTxRates(
2799 IN PRTMP_ADAPTER pAd,
2804 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2805 UCHAR MinSupport = RATE_54;
2806 ULONG BasicRateBitmap = 0;
2807 UCHAR CurrBasicRate = RATE_1;
2808 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2809 PHTTRANSMIT_SETTING pHtPhy = NULL;
2810 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2811 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2812 BOOLEAN *auto_rate_cur_p;
2813 UCHAR HtMcs = MCS_AUTO;
2815 // find max desired rate
2816 UpdateBasicRateBitmap(pAd);
2819 auto_rate_cur_p = NULL;
2820 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2822 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2824 case 2: Rate = RATE_1; num++; break;
2825 case 4: Rate = RATE_2; num++; break;
2826 case 11: Rate = RATE_5_5; num++; break;
2827 case 22: Rate = RATE_11; num++; break;
2828 case 12: Rate = RATE_6; num++; break;
2829 case 18: Rate = RATE_9; num++; break;
2830 case 24: Rate = RATE_12; num++; break;
2831 case 36: Rate = RATE_18; num++; break;
2832 case 48: Rate = RATE_24; num++; break;
2833 case 72: Rate = RATE_36; num++; break;
2834 case 96: Rate = RATE_48; num++; break;
2835 case 108: Rate = RATE_54; num++; break;
2836 //default: Rate = RATE_1; break;
2838 if (MaxDesire < Rate) MaxDesire = Rate;
2841 //===========================================================================
2842 //===========================================================================
2844 #ifdef CONFIG_STA_SUPPORT
2845 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2847 pHtPhy = &pAd->StaCfg.HTPhyMode;
2848 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2849 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2851 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2852 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2854 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2855 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2856 (MaxDesire > RATE_11))
2858 MaxDesire = RATE_11;
2861 #endif // CONFIG_STA_SUPPORT //
2863 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2864 pMinHtPhy->word = 0;
2865 pMaxHtPhy->word = 0;
2868 // Auto rate switching is enabled only if more than one DESIRED RATES are
2869 // specified; otherwise disabled
2872 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2873 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2874 *auto_rate_cur_p = FALSE;
2878 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2879 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2880 *auto_rate_cur_p = TRUE;
2884 if (HtMcs != MCS_AUTO)
2886 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2887 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2888 *auto_rate_cur_p = FALSE;
2892 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2893 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2894 *auto_rate_cur_p = TRUE;
2898 #ifdef CONFIG_STA_SUPPORT
2899 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2901 pSupRate = &pAd->StaActive.SupRate[0];
2902 pExtRate = &pAd->StaActive.ExtRate[0];
2903 SupRateLen = pAd->StaActive.SupRateLen;
2904 ExtRateLen = pAd->StaActive.ExtRateLen;
2907 #endif // CONFIG_STA_SUPPORT //
2909 pSupRate = &pAd->CommonCfg.SupRate[0];
2910 pExtRate = &pAd->CommonCfg.ExtRate[0];
2911 SupRateLen = pAd->CommonCfg.SupRateLen;
2912 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2915 // find max supported rate
2916 for (i=0; i<SupRateLen; i++)
2918 switch (pSupRate[i] & 0x7f)
2920 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2921 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2922 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2923 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2924 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2925 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2926 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2927 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2928 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2929 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2930 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2931 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2932 default: Rate = RATE_1; break;
2934 if (MaxSupport < Rate) MaxSupport = Rate;
2936 if (MinSupport > Rate) MinSupport = Rate;
2939 for (i=0; i<ExtRateLen; i++)
2941 switch (pExtRate[i] & 0x7f)
2943 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2944 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2945 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2946 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2947 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2948 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2949 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2950 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2951 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2952 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2953 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2954 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2955 default: Rate = RATE_1; break;
2957 if (MaxSupport < Rate) MaxSupport = Rate;
2959 if (MinSupport > Rate) MinSupport = Rate;
2962 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2965 // pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap;
2967 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2968 // the DURATION field of outgoing uniicast DATA/MGMT frame
2969 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2971 if (BasicRateBitmap & (0x01 << i))
2972 CurrBasicRate = (UCHAR)i;
2973 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2976 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2977 // max tx rate = min {max desire rate, max supported rate}
2978 if (MaxSupport < MaxDesire)
2979 pAd->CommonCfg.MaxTxRate = MaxSupport;
2981 pAd->CommonCfg.MaxTxRate = MaxDesire;
2983 pAd->CommonCfg.MinTxRate = MinSupport;
2984 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
2985 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
2987 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
2988 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
2989 // 3. -75 > RSSI, start at 11 Mbps (long distance)
2990 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
2991 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
2992 if (*auto_rate_cur_p)
2995 #ifdef CONFIG_STA_SUPPORT
2996 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2997 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2998 #endif // CONFIG_STA_SUPPORT //
2999 if (bLinkUp == TRUE)
3000 pAd->CommonCfg.TxRate = RATE_24;
3002 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3005 pAd->CommonCfg.TxRate = RATE_11;
3007 pAd->CommonCfg.TxRate = RATE_24;
3009 // should never exceed MaxTxRate (consider 11B-only mode)
3010 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3011 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3013 pAd->CommonCfg.TxRateIndex = 0;
3017 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3018 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3019 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3021 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3022 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3023 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3024 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3027 if (pAd->CommonCfg.TxRate <= RATE_11)
3029 pMaxHtPhy->field.MODE = MODE_CCK;
3030 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3031 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3035 pMaxHtPhy->field.MODE = MODE_OFDM;
3036 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3037 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3038 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3040 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3043 pHtPhy->word = (pMaxHtPhy->word);
3044 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3046 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3047 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3048 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3052 switch (pAd->CommonCfg.PhyMode)
3054 case PHY_11BG_MIXED:
3056 #ifdef DOT11_N_SUPPORT
3057 case PHY_11BGN_MIXED:
3058 #endif // DOT11_N_SUPPORT //
3059 pAd->CommonCfg.MlmeRate = RATE_1;
3060 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3061 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3064 pAd->CommonCfg.RtsRate = RATE_11;
3066 // pAd->CommonCfg.RtsRate = RATE_1;
3071 #ifdef DOT11_N_SUPPORT
3072 case PHY_11AGN_MIXED:
3073 case PHY_11GN_MIXED:
3075 case PHY_11AN_MIXED:
3077 #endif // DOT11_N_SUPPORT //
3078 pAd->CommonCfg.MlmeRate = RATE_6;
3079 pAd->CommonCfg.RtsRate = RATE_6;
3080 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3081 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3083 case PHY_11ABG_MIXED:
3084 #ifdef DOT11_N_SUPPORT
3085 case PHY_11ABGN_MIXED:
3086 #endif // DOT11_N_SUPPORT //
3087 if (pAd->CommonCfg.Channel <= 14)
3089 pAd->CommonCfg.MlmeRate = RATE_1;
3090 pAd->CommonCfg.RtsRate = RATE_1;
3091 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3092 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3096 pAd->CommonCfg.MlmeRate = RATE_6;
3097 pAd->CommonCfg.RtsRate = RATE_6;
3098 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3099 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3103 pAd->CommonCfg.MlmeRate = RATE_6;
3104 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3105 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3106 pAd->CommonCfg.RtsRate = RATE_1;
3110 // Keep Basic Mlme Rate.
3112 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3113 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3114 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3116 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3117 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3120 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3121 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3122 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3123 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3124 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3125 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3126 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 ));
3129 #ifdef DOT11_N_SUPPORT
3131 ==========================================================================
3133 This function update HT Rate setting.
3134 Input Wcid value is valid for 2 case :
3135 1. it's used for Station in infra mode that copy AP rate to Mactable.
3136 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3138 IRQL = DISPATCH_LEVEL
3140 ==========================================================================
3142 VOID MlmeUpdateHtTxRates(
3143 IN PRTMP_ADAPTER pAd,
3146 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3148 RT_HT_CAPABILITY *pRtHtCap = NULL;
3149 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3152 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3153 PHTTRANSMIT_SETTING pHtPhy = NULL;
3154 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3155 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3156 BOOLEAN *auto_rate_cur_p;
3158 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3160 auto_rate_cur_p = NULL;
3162 #ifdef CONFIG_STA_SUPPORT
3163 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3165 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3166 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3167 pHtPhy = &pAd->StaCfg.HTPhyMode;
3168 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3169 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3171 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3173 #endif // CONFIG_STA_SUPPORT //
3175 #ifdef CONFIG_STA_SUPPORT
3176 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3178 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3181 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3182 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3183 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3184 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3185 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3186 pMaxHtPhy->field.STBC = STBC_USE;
3188 pMaxHtPhy->field.STBC = STBC_NONE;
3191 #endif // CONFIG_STA_SUPPORT //
3193 if (pDesireHtPhy->bHtEnable == FALSE)
3196 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3197 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3198 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3199 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3200 pMaxHtPhy->field.STBC = STBC_USE;
3202 pMaxHtPhy->field.STBC = STBC_NONE;
3205 // Decide MAX ht rate.
3206 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3207 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3209 pMaxHtPhy->field.MODE = MODE_HTMIX;
3211 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3212 pMaxHtPhy->field.BW = BW_40;
3214 pMaxHtPhy->field.BW = BW_20;
3216 if (pMaxHtPhy->field.BW == BW_20)
3217 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3219 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3221 for (i=23; i>=0; i--) // 3*3
3224 bitmask = (1<<(i-(j*8)));
3226 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3228 pMaxHtPhy->field.MCS = i;
3236 // Copy MIN ht rate. rt2860???
3237 pMinHtPhy->field.BW = BW_20;
3238 pMinHtPhy->field.MCS = 0;
3239 pMinHtPhy->field.STBC = 0;
3240 pMinHtPhy->field.ShortGI = 0;
3241 //If STA assigns fixed rate. update to fixed here.
3242 #ifdef CONFIG_STA_SUPPORT
3243 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3245 if (pDesireHtPhy->MCSSet[4] != 0)
3247 pMaxHtPhy->field.MCS = 32;
3248 pMinHtPhy->field.MCS = 32;
3249 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3252 for (i=23; (CHAR)i >= 0; i--) // 3*3
3255 bitmask = (1<<(i-(j*8)));
3256 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3258 pMaxHtPhy->field.MCS = i;
3259 pMinHtPhy->field.MCS = i;
3266 #endif // CONFIG_STA_SUPPORT //
3270 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3271 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3272 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3273 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3274 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3276 // use default now. rt2860
3277 if (pDesireHtPhy->MCSSet[0] != 0xff)
3278 *auto_rate_cur_p = FALSE;
3280 *auto_rate_cur_p = TRUE;
3282 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3283 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3284 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3285 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3287 #endif // DOT11_N_SUPPORT //
3289 // IRQL = DISPATCH_LEVEL
3291 IN PRTMP_ADAPTER pAd)
3293 RT28XX_MLME_RADIO_OFF(pAd);
3296 // IRQL = DISPATCH_LEVEL
3298 IN PRTMP_ADAPTER pAd)
3300 RT28XX_MLME_RADIO_ON(pAd);
3303 // ===========================================================================================
3305 // ===========================================================================================
3308 /*! \brief initialize BSS table
3309 * \param p_tab pointer to the table
3314 IRQL = PASSIVE_LEVEL
3315 IRQL = DISPATCH_LEVEL
3324 Tab->BssOverlapNr = 0;
3325 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3327 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3328 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3332 #ifdef DOT11_N_SUPPORT
3334 IN PRTMP_ADAPTER pAd,
3339 Tab->numAsOriginator = 0;
3340 Tab->numAsRecipient = 0;
3341 NdisAllocateSpinLock(&pAd->BATabLock);
3342 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3344 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3345 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3347 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3349 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3352 #endif // DOT11_N_SUPPORT //
3354 /*! \brief search the BSS table by SSID
3355 * \param p_tab pointer to the bss table
3356 * \param ssid SSID string
3357 * \return index of the table, BSS_NOT_FOUND if not in the table
3360 * \note search by sequential search
3362 IRQL = DISPATCH_LEVEL
3365 ULONG BssTableSearch(
3372 for (i = 0; i < Tab->BssNr; i++)
3375 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3376 // We should distinguish this case.
3378 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3379 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3380 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3385 return (ULONG)BSS_NOT_FOUND;
3388 ULONG BssSsidTableSearch(
3397 for (i = 0; i < Tab->BssNr; i++)
3400 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3401 // We should distinguish this case.
3403 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3404 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3405 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3406 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3411 return (ULONG)BSS_NOT_FOUND;
3414 ULONG BssTableSearchWithSSID(
3423 for (i = 0; i < Tab->BssNr; i++)
3425 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3426 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3427 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3428 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3429 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3430 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3435 return (ULONG)BSS_NOT_FOUND;
3438 // IRQL = DISPATCH_LEVEL
3439 VOID BssTableDeleteEntry(
3440 IN OUT BSS_TABLE *Tab,
3446 for (i = 0; i < Tab->BssNr; i++)
3448 if ((Tab->BssEntry[i].Channel == Channel) &&
3449 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3451 for (j = i; j < Tab->BssNr - 1; j++)
3453 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3455 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3462 #ifdef DOT11_N_SUPPORT
3464 ========================================================================
3465 Routine Description:
3466 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3469 // IRQL = DISPATCH_LEVEL
3470 ========================================================================
3472 VOID BATableDeleteORIEntry(
3473 IN OUT PRTMP_ADAPTER pAd,
3474 IN BA_ORI_ENTRY *pBAORIEntry)
3477 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3479 NdisAcquireSpinLock(&pAd->BATabLock);
3480 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3482 pAd->BATable.numAsOriginator -= 1;
3483 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3484 // Erase Bitmap flag.
3486 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3487 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3488 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3489 pBAORIEntry->Token = 1;
3490 // Not clear Sequence here.
3491 NdisReleaseSpinLock(&pAd->BATabLock);
3494 #endif // DOT11_N_SUPPORT //
3502 IRQL = DISPATCH_LEVEL
3506 IN PRTMP_ADAPTER pAd,
3507 OUT BSS_ENTRY *pBss,
3512 IN USHORT BeaconPeriod,
3513 IN PCF_PARM pCfParm,
3515 IN USHORT CapabilityInfo,
3517 IN UCHAR SupRateLen,
3519 IN UCHAR ExtRateLen,
3520 IN HT_CAPABILITY_IE *pHtCapability,
3521 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3522 IN UCHAR HtCapabilityLen,
3523 IN UCHAR AddHtInfoLen,
3524 IN UCHAR NewExtChanOffset,
3527 IN LARGE_INTEGER TimeStamp,
3529 IN PEDCA_PARM pEdcaParm,
3530 IN PQOS_CAPABILITY_PARM pQosCapability,
3531 IN PQBSS_LOAD_PARM pQbssLoad,
3532 IN USHORT LengthVIE,
3533 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3535 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3536 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3540 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3541 // Or send beacon /probe response with SSID len matching real SSID length,
3542 // but SSID is all zero. such as "00-00-00-00" with length 4.
3543 // We have to prevent this case overwrite correct table
3544 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3546 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3547 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3548 pBss->SsidLen = SsidLen;
3554 pBss->BssType = BssType;
3555 pBss->BeaconPeriod = BeaconPeriod;
3556 if (BssType == BSS_INFRA)
3558 if (pCfParm->bValid)
3560 pBss->CfpCount = pCfParm->CfpCount;
3561 pBss->CfpPeriod = pCfParm->CfpPeriod;
3562 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3563 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3568 pBss->AtimWin = AtimWin;
3571 pBss->CapabilityInfo = CapabilityInfo;
3572 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3573 // Combine with AuthMode, they will decide the connection methods.
3574 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3575 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3576 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3577 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3579 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3580 pBss->SupRateLen = SupRateLen;
3581 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3582 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3583 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3584 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3585 pBss->NewExtChanOffset = NewExtChanOffset;
3586 pBss->ExtRateLen = ExtRateLen;
3587 pBss->Channel = Channel;
3588 pBss->CentralChannel = Channel;
3590 // Update CkipFlag. if not exists, the value is 0x0
3591 pBss->CkipFlag = CkipFlag;
3593 // New for microsoft Fixed IEs
3594 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3595 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3596 pBss->FixIEs.Capabilities = CapabilityInfo;
3598 // New for microsoft Variable IEs
3601 pBss->VarIELen = LengthVIE;
3602 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3609 pBss->AddHtInfoLen = 0;
3610 pBss->HtCapabilityLen = 0;
3611 #ifdef DOT11_N_SUPPORT
3612 if (HtCapabilityLen> 0)
3614 pBss->HtCapabilityLen = HtCapabilityLen;
3615 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3616 if (AddHtInfoLen > 0)
3618 pBss->AddHtInfoLen = AddHtInfoLen;
3619 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3621 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3623 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3625 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3627 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3631 #endif // DOT11_N_SUPPORT //
3633 BssCipherParse(pBss);
3637 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3639 pBss->EdcaParm.bValid = FALSE;
3641 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3643 pBss->QosCapability.bValid = FALSE;
3645 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3647 pBss->QbssLoad.bValid = FALSE;
3649 #ifdef CONFIG_STA_SUPPORT
3650 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3656 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3657 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3658 #ifdef EXT_BUILD_CHANNEL_LIST
3659 NdisZeroMemory(&pBss->CountryString[0], 3);
3660 pBss->bHasCountryIE = FALSE;
3661 #endif // EXT_BUILD_CHANNEL_LIST //
3662 pEid = (PEID_STRUCT) pVIE;
3663 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3668 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3670 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3672 pBss->WpaIE.IELen = 0;
3675 pBss->WpaIE.IELen = pEid->Len + 2;
3676 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3680 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3682 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3684 pBss->RsnIE.IELen = 0;
3687 pBss->RsnIE.IELen = pEid->Len + 2;
3688 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3691 #ifdef EXT_BUILD_CHANNEL_LIST
3693 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3694 pBss->bHasCountryIE = TRUE;
3696 #endif // EXT_BUILD_CHANNEL_LIST //
3698 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3699 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3702 #endif // CONFIG_STA_SUPPORT //
3706 * \brief insert an entry into the bss table
3707 * \param p_tab The BSS table
3708 * \param Bssid BSSID
3710 * \param ssid_len Length of SSID
3712 * \param beacon_period
3719 * \param channel_idx
3723 * \note If SSID is identical, the old entry will be replaced by the new one
3725 IRQL = DISPATCH_LEVEL
3728 ULONG BssTableSetEntry(
3729 IN PRTMP_ADAPTER pAd,
3735 IN USHORT BeaconPeriod,
3738 IN USHORT CapabilityInfo,
3740 IN UCHAR SupRateLen,
3742 IN UCHAR ExtRateLen,
3743 IN HT_CAPABILITY_IE *pHtCapability,
3744 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3745 IN UCHAR HtCapabilityLen,
3746 IN UCHAR AddHtInfoLen,
3747 IN UCHAR NewExtChanOffset,
3750 IN LARGE_INTEGER TimeStamp,
3752 IN PEDCA_PARM pEdcaParm,
3753 IN PQOS_CAPABILITY_PARM pQosCapability,
3754 IN PQBSS_LOAD_PARM pQbssLoad,
3755 IN USHORT LengthVIE,
3756 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3760 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3761 if (Idx == BSS_NOT_FOUND)
3763 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3766 // It may happen when BSS Table was full.
3767 // The desired AP will not be added into BSS Table
3768 // In this case, if we found the desired AP then overwrite BSS Table.
3770 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3772 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3773 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3775 Idx = Tab->BssOverlapNr;
3776 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3777 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3778 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3779 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3785 return BSS_NOT_FOUND;
3789 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3790 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3791 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3796 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3797 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3798 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3804 #ifdef CONFIG_STA_SUPPORT
3805 #ifdef DOT11_N_SUPPORT
3806 #ifdef DOT11N_DRAFT3
3808 IN PRTMP_ADAPTER pAd)
3812 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3813 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3815 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3816 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3819 ULONG TriEventTableSetEntry(
3820 IN PRTMP_ADAPTER pAd,
3821 OUT TRIGGER_EVENT_TAB *Tab,
3823 IN HT_CAPABILITY_IE *pHtCapability,
3824 IN UCHAR HtCapabilityLen,
3829 if (HtCapabilityLen == 0)
3831 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3833 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3834 Tab->EventA[Tab->EventANo].bValid = TRUE;
3835 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3836 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3839 // Beacon has Regulatory class IE. So use beacon's
3840 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3844 // Use Station's Regulatory class instead.
3845 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3847 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3849 Tab->EventA[Tab->EventANo].RegClass = 32;
3851 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3852 Tab->EventA[Tab->EventANo].RegClass = 33;
3855 Tab->EventA[Tab->EventANo].RegClass = ??;
3862 else if (pHtCapability->HtCapInfo.Intolerant40)
3864 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3870 ========================================================================
3871 Routine Description:
3872 Trigger Event table Maintainence called once every second.
3875 // IRQL = DISPATCH_LEVEL
3876 ========================================================================
3878 VOID TriEventCounterMaintenance(
3879 IN PRTMP_ADAPTER pAd)
3882 BOOLEAN bNotify = FALSE;
3883 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3885 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3887 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3888 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3890 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3891 pAd->CommonCfg.TriggerEventTab.EventANo --;
3892 // Need to send 20/40 Coexistence Notify frame if has status change.
3897 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
3899 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
3900 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
3904 if (bNotify == TRUE)
3905 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
3907 #endif // DOT11N_DRAFT3 //
3908 #endif // DOT11_N_SUPPORT //
3910 // IRQL = DISPATCH_LEVEL
3911 VOID BssTableSsidSort(
3912 IN PRTMP_ADAPTER pAd,
3913 OUT BSS_TABLE *OutTab,
3918 BssTableInit(OutTab);
3920 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3922 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3923 BOOLEAN bIsHiddenApIncluded = FALSE;
3925 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3926 (pAd->MlmeAux.Channel > 14) &&
3927 RadarChannelCheck(pAd, pInBss->Channel))
3931 bIsHiddenApIncluded = TRUE;
3934 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3935 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3937 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3940 #ifdef EXT_BUILD_CHANNEL_LIST
3941 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
3942 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
3943 (pInBss->bHasCountryIE == FALSE))
3945 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
3948 #endif // EXT_BUILD_CHANNEL_LIST //
3950 #ifdef DOT11_N_SUPPORT
3951 // 2.4G/5G N only mode
3952 if ((pInBss->HtCapabilityLen == 0) &&
3953 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3955 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3958 #endif // DOT11_N_SUPPORT //
3961 // Check the Authmode first
3962 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3964 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3965 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3969 // Check cipher suite, AP must have more secured cipher than station setting
3970 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3972 // If it's not mixed mode, we should only let BSS pass with the same encryption
3973 if (pInBss->WPA.bMixMode == FALSE)
3974 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3977 // check group cipher
3978 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3979 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3980 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3983 // check pairwise cipher, skip if none matched
3984 // If profile set to AES, let it pass without question.
3985 // If profile set to TKIP, we must find one mateched
3986 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3987 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3988 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3991 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3993 // If it's not mixed mode, we should only let BSS pass with the same encryption
3994 if (pInBss->WPA2.bMixMode == FALSE)
3995 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3998 // check group cipher
3999 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4000 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4001 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
4004 // check pairwise cipher, skip if none matched
4005 // If profile set to AES, let it pass without question.
4006 // If profile set to TKIP, we must find one mateched
4007 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4008 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4009 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4013 // Bss Type matched, SSID matched.
4014 // We will check wepstatus for qualification Bss
4015 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4017 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4019 // For the SESv2 case, we will not qualify WepStatus.
4025 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4026 // It definitely will fail. So, skip it.
4027 // CCX also require not even try to connect it!!
4031 #ifdef DOT11_N_SUPPORT
4032 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4033 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4034 if ((pInBss->CentralChannel != pInBss->Channel) &&
4035 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4037 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4039 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4041 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4045 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4051 #endif // DOT11_N_SUPPORT //
4053 // copy matching BSS from InTab to OutTab
4054 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4058 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4060 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4063 #ifdef DOT11_N_SUPPORT
4064 // 2.4G/5G N only mode
4065 if ((pInBss->HtCapabilityLen == 0) &&
4066 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4068 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4071 #endif // DOT11_N_SUPPORT //
4074 // Check the Authmode first
4075 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4077 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4078 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4082 // Check cipher suite, AP must have more secured cipher than station setting
4083 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4085 // If it's not mixed mode, we should only let BSS pass with the same encryption
4086 if (pInBss->WPA.bMixMode == FALSE)
4087 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4090 // check group cipher
4091 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4094 // check pairwise cipher, skip if none matched
4095 // If profile set to AES, let it pass without question.
4096 // If profile set to TKIP, we must find one mateched
4097 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4098 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4099 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4102 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4104 // If it's not mixed mode, we should only let BSS pass with the same encryption
4105 if (pInBss->WPA2.bMixMode == FALSE)
4106 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4109 // check group cipher
4110 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4113 // check pairwise cipher, skip if none matched
4114 // If profile set to AES, let it pass without question.
4115 // If profile set to TKIP, we must find one mateched
4116 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4117 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4118 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4122 // Bss Type matched, SSID matched.
4123 // We will check wepstatus for qualification Bss
4124 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4127 #ifdef DOT11_N_SUPPORT
4128 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4129 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4130 if ((pInBss->CentralChannel != pInBss->Channel) &&
4131 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4133 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4135 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4137 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4140 #endif // DOT11_N_SUPPORT //
4142 // copy matching BSS from InTab to OutTab
4143 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4148 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4152 BssTableSortByRssi(OutTab);
4156 // IRQL = DISPATCH_LEVEL
4157 VOID BssTableSortByRssi(
4158 IN OUT BSS_TABLE *OutTab)
4163 for (i = 0; i < OutTab->BssNr - 1; i++)
4165 for (j = i+1; j < OutTab->BssNr; j++)
4167 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4169 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4170 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4171 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4176 #endif // CONFIG_STA_SUPPORT //
4179 VOID BssCipherParse(
4180 IN OUT PBSS_ENTRY pBss)
4184 PRSN_IE_HEADER_STRUCT pRsnHeader;
4185 PCIPHER_SUITE_STRUCT pCipher;
4186 PAKM_SUITE_STRUCT pAKM;
4189 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4192 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4196 pBss->WepStatus = Ndis802_11WEPEnabled;
4200 pBss->WepStatus = Ndis802_11WEPDisabled;
4202 // Set default to disable & open authentication before parsing variable IE
4203 pBss->AuthMode = Ndis802_11AuthModeOpen;
4204 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4207 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4208 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4209 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4210 pBss->WPA.RsnCapability = 0;
4211 pBss->WPA.bMixMode = FALSE;
4213 // Init WPA2 setting
4214 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4215 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4216 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4217 pBss->WPA2.RsnCapability = 0;
4218 pBss->WPA2.bMixMode = FALSE;
4221 Length = (INT) pBss->VarIELen;
4225 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4226 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4227 pEid = (PEID_STRUCT) pTmp;
4231 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4232 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4238 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4239 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4240 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4241 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4244 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4245 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4246 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4249 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4250 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4251 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4257 // if Cisco IE_WPA, break
4260 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4265 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4267 // if unsupported vendor specific IE
4270 // Skip OUI, version, and multicast suite
4271 // This part should be improved in the future when AP supported multiple cipher suite.
4272 // For now, it's OK since almost all APs have fixed cipher suite supported.
4273 // pTmp = (PUCHAR) pEid->Octet;
4276 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4284 // Parse group cipher
4288 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4291 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4294 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4297 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4302 // number of unicast suite
4305 // skip all unicast cipher suites
4306 //Count = *(PUSHORT) pTmp;
4307 Count = (pTmp[1]<<8) + pTmp[0];
4308 pTmp += sizeof(USHORT);
4310 // Parsing all unicast cipher suite
4315 TmpCipher = Ndis802_11WEPDisabled;
4319 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4320 TmpCipher = Ndis802_11Encryption1Enabled;
4323 TmpCipher = Ndis802_11Encryption2Enabled;
4326 TmpCipher = Ndis802_11Encryption3Enabled;
4331 if (TmpCipher > pBss->WPA.PairCipher)
4333 // Move the lower cipher suite to PairCipherAux
4334 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4335 pBss->WPA.PairCipher = TmpCipher;
4339 pBss->WPA.PairCipherAux = TmpCipher;
4345 // 4. get AKM suite counts
4346 //Count = *(PUSHORT) pTmp;
4347 Count = (pTmp[1]<<8) + pTmp[0];
4348 pTmp += sizeof(USHORT);
4354 // Set AP support WPA mode
4355 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4356 pBss->AuthMode = Ndis802_11AuthModeWPA;
4358 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4361 // Set AP support WPA mode
4362 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4363 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4365 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4372 // Fixed for WPA-None
4373 if (pBss->BssType == BSS_ADHOC)
4375 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4376 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4377 pBss->WepStatus = pBss->WPA.GroupCipher;
4378 // Patched bugs for old driver
4379 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4380 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4383 pBss->WepStatus = pBss->WPA.PairCipher;
4385 // Check the Pair & Group, if different, turn on mixed mode flag
4386 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4387 pBss->WPA.bMixMode = TRUE;
4392 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4394 // 0. Version must be 1
4395 if (le2cpu16(pRsnHeader->Version) != 1)
4397 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4399 // 1. Check group cipher
4400 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4401 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4404 // Parse group cipher
4405 switch (pCipher->Type)
4408 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4411 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4414 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4417 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4422 // set to correct offset for next parsing
4423 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4425 // 2. Get pairwise cipher counts
4426 //Count = *(PUSHORT) pTmp;
4427 Count = (pTmp[1]<<8) + pTmp[0];
4428 pTmp += sizeof(USHORT);
4430 // 3. Get pairwise cipher
4431 // Parsing all unicast cipher suite
4435 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4436 TmpCipher = Ndis802_11WEPDisabled;
4437 switch (pCipher->Type)
4440 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4441 TmpCipher = Ndis802_11Encryption1Enabled;
4444 TmpCipher = Ndis802_11Encryption2Enabled;
4447 TmpCipher = Ndis802_11Encryption3Enabled;
4452 if (TmpCipher > pBss->WPA2.PairCipher)
4454 // Move the lower cipher suite to PairCipherAux
4455 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4456 pBss->WPA2.PairCipher = TmpCipher;
4460 pBss->WPA2.PairCipherAux = TmpCipher;
4462 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4466 // 4. get AKM suite counts
4467 //Count = *(PUSHORT) pTmp;
4468 Count = (pTmp[1]<<8) + pTmp[0];
4469 pTmp += sizeof(USHORT);
4471 // 5. Get AKM ciphers
4472 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4473 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4479 // Set AP support WPA mode
4480 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4481 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4483 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4486 // Set AP support WPA mode
4487 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4488 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4490 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4495 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4497 // Fixed for WPA-None
4498 if (pBss->BssType == BSS_ADHOC)
4500 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4501 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4502 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4503 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4504 pBss->WepStatus = pBss->WPA.GroupCipher;
4505 // Patched bugs for old driver
4506 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4507 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4509 pBss->WepStatus = pBss->WPA2.PairCipher;
4511 // 6. Get RSN capability
4512 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4513 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4514 pTmp += sizeof(USHORT);
4516 // Check the Pair & Group, if different, turn on mixed mode flag
4517 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4518 pBss->WPA2.bMixMode = TRUE;
4524 Length -= (pEid->Len + 2);
4528 // ===========================================================================================
4530 // ===========================================================================================
4532 /*! \brief generates a random mac address value for IBSS BSSID
4533 * \param Addr the bssid location
4538 VOID MacAddrRandomBssid(
4539 IN PRTMP_ADAPTER pAd,
4544 for (i = 0; i < MAC_ADDR_LEN; i++)
4546 pAddr[i] = RandomByte(pAd);
4549 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4552 /*! \brief init the management mac frame header
4553 * \param p_hdr mac header
4554 * \param subtype subtype of the frame
4555 * \param p_ds destination address, don't care if it is a broadcast address
4557 * \pre the station has the following information in the pAd->StaCfg
4561 * \note this function initializes the following field
4563 IRQL = PASSIVE_LEVEL
4564 IRQL = DISPATCH_LEVEL
4567 VOID MgtMacHeaderInit(
4568 IN PRTMP_ADAPTER pAd,
4569 IN OUT PHEADER_802_11 pHdr80211,
4575 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4577 pHdr80211->FC.Type = BTYPE_MGMT;
4578 pHdr80211->FC.SubType = SubType;
4579 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4580 // pHdr80211->FC.Type = BTYPE_CNTL;
4581 pHdr80211->FC.ToDs = ToDs;
4582 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4583 #ifdef CONFIG_STA_SUPPORT
4584 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4585 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4586 #endif // CONFIG_STA_SUPPORT //
4587 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4590 // ===========================================================================================
4592 // ===========================================================================================
4594 /*!***************************************************************************
4595 * This routine build an outgoing frame, and fill all information specified
4596 * in argument list to the frame body. The actual frame size is the summation
4599 * Buffer - pointer to a pre-allocated memory segment
4600 * args - a list of <int arg_size, arg> pairs.
4601 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4602 * function will FAIL!!!
4604 * Size of the buffer
4606 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4608 IRQL = PASSIVE_LEVEL
4609 IRQL = DISPATCH_LEVEL
4611 ****************************************************************************/
4612 ULONG MakeOutgoingFrame(
4614 OUT ULONG *FrameLen, ...)
4621 // calculates the total length
4623 va_start(Args, FrameLen);
4626 leng = va_arg(Args, int);
4627 if (leng == END_OF_ARGS)
4631 p = va_arg(Args, PVOID);
4632 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4633 TotLeng = TotLeng + leng;
4636 va_end(Args); /* clean up */
4637 *FrameLen = TotLeng;
4641 // ===========================================================================================
4643 // ===========================================================================================
4645 /*! \brief Initialize The MLME Queue, used by MLME Functions
4646 * \param *Queue The MLME Queue
4647 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4650 * \note Because this is done only once (at the init stage), no need to be locked
4652 IRQL = PASSIVE_LEVEL
4655 NDIS_STATUS MlmeQueueInit(
4656 IN MLME_QUEUE *Queue)
4660 NdisAllocateSpinLock(&Queue->Lock);
4666 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4668 Queue->Entry[i].Occupied = FALSE;
4669 Queue->Entry[i].MsgLen = 0;
4670 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4673 return NDIS_STATUS_SUCCESS;
4676 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4677 * \param *Queue The MLME Queue
4678 * \param Machine The State Machine Id
4679 * \param MsgType The Message Type
4680 * \param MsgLen The Message length
4681 * \param *Msg The message pointer
4682 * \return TRUE if enqueue is successful, FALSE if the queue is full
4685 * \note The message has to be initialized
4687 IRQL = PASSIVE_LEVEL
4688 IRQL = DISPATCH_LEVEL
4691 BOOLEAN MlmeEnqueue(
4692 IN PRTMP_ADAPTER pAd,
4699 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4701 // Do nothing if the driver is starting halt state.
4702 // This might happen when timer already been fired before cancel timer with mlmehalt
4703 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4706 // First check the size, it MUST not exceed the mlme queue size
4707 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4709 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4713 if (MlmeQueueFull(Queue))
4718 NdisAcquireSpinLock(&(Queue->Lock));
4722 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4727 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4728 Queue->Entry[Tail].Occupied = TRUE;
4729 Queue->Entry[Tail].Machine = Machine;
4730 Queue->Entry[Tail].MsgType = MsgType;
4731 Queue->Entry[Tail].MsgLen = MsgLen;
4735 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4738 NdisReleaseSpinLock(&(Queue->Lock));
4742 /*! \brief This function is used when Recv gets a MLME message
4743 * \param *Queue The MLME Queue
4744 * \param TimeStampHigh The upper 32 bit of timestamp
4745 * \param TimeStampLow The lower 32 bit of timestamp
4746 * \param Rssi The receiving RSSI strength
4747 * \param MsgLen The length of the message
4748 * \param *Msg The message pointer
4749 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4753 IRQL = DISPATCH_LEVEL
4756 BOOLEAN MlmeEnqueueForRecv(
4757 IN PRTMP_ADAPTER pAd,
4759 IN ULONG TimeStampHigh,
4760 IN ULONG TimeStampLow,
4769 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4771 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4773 // Do nothing if the driver is starting halt state.
4774 // This might happen when timer already been fired before cancel timer with mlmehalt
4775 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4777 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4781 // First check the size, it MUST not exceed the mlme queue size
4782 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4784 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4788 if (MlmeQueueFull(Queue))
4793 #ifdef CONFIG_STA_SUPPORT
4794 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4796 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4798 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4802 #endif // CONFIG_STA_SUPPORT //
4804 // OK, we got all the informations, it is time to put things into queue
4805 NdisAcquireSpinLock(&(Queue->Lock));
4809 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4813 Queue->Entry[Tail].Occupied = TRUE;
4814 Queue->Entry[Tail].Machine = Machine;
4815 Queue->Entry[Tail].MsgType = MsgType;
4816 Queue->Entry[Tail].MsgLen = MsgLen;
4817 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4818 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4819 Queue->Entry[Tail].Rssi0 = Rssi0;
4820 Queue->Entry[Tail].Rssi1 = Rssi1;
4821 Queue->Entry[Tail].Rssi2 = Rssi2;
4822 Queue->Entry[Tail].Signal = Signal;
4823 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4825 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4829 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4832 NdisReleaseSpinLock(&(Queue->Lock));
4834 RT28XX_MLME_HANDLER(pAd);
4840 /*! \brief Dequeue a message from the MLME Queue
4841 * \param *Queue The MLME Queue
4842 * \param *Elem The message dequeued from MLME Queue
4843 * \return TRUE if the Elem contains something, FALSE otherwise
4847 IRQL = DISPATCH_LEVEL
4850 BOOLEAN MlmeDequeue(
4851 IN MLME_QUEUE *Queue,
4852 OUT MLME_QUEUE_ELEM **Elem)
4854 NdisAcquireSpinLock(&(Queue->Lock));
4855 *Elem = &(Queue->Entry[Queue->Head]);
4858 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4862 NdisReleaseSpinLock(&(Queue->Lock));
4866 // IRQL = DISPATCH_LEVEL
4867 VOID MlmeRestartStateMachine(
4868 IN PRTMP_ADAPTER pAd)
4870 #ifdef CONFIG_STA_SUPPORT
4872 #endif // CONFIG_STA_SUPPORT //
4874 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4877 #ifdef CONFIG_STA_SUPPORT
4878 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4880 #ifdef QOS_DLS_SUPPORT
4882 #endif // QOS_DLS_SUPPORT //
4883 // Cancel all timer events
4884 // Be careful to cancel new added timer
4885 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4886 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4887 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4888 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4889 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4890 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4892 #ifdef QOS_DLS_SUPPORT
4893 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
4895 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
4897 #endif // QOS_DLS_SUPPORT //
4899 #endif // CONFIG_STA_SUPPORT //
4901 // Change back to original channel in case of doing scan
4902 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4903 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4905 // Resume MSDU which is turned off durning scan
4906 RTMPResumeMsduTransmission(pAd);
4908 #ifdef CONFIG_STA_SUPPORT
4909 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4911 // Set all state machines back IDLE
4912 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4913 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4914 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4915 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4916 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4917 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4918 #ifdef QOS_DLS_SUPPORT
4919 pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
4920 #endif // QOS_DLS_SUPPORT //
4922 #endif // CONFIG_STA_SUPPORT //
4926 /*! \brief test if the MLME Queue is empty
4927 * \param *Queue The MLME Queue
4928 * \return TRUE if the Queue is empty, FALSE otherwise
4932 IRQL = DISPATCH_LEVEL
4935 BOOLEAN MlmeQueueEmpty(
4936 IN MLME_QUEUE *Queue)
4940 NdisAcquireSpinLock(&(Queue->Lock));
4941 Ans = (Queue->Num == 0);
4942 NdisReleaseSpinLock(&(Queue->Lock));
4947 /*! \brief test if the MLME Queue is full
4948 * \param *Queue The MLME Queue
4949 * \return TRUE if the Queue is empty, FALSE otherwise
4953 IRQL = PASSIVE_LEVEL
4954 IRQL = DISPATCH_LEVEL
4957 BOOLEAN MlmeQueueFull(
4958 IN MLME_QUEUE *Queue)
4962 NdisAcquireSpinLock(&(Queue->Lock));
4963 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4964 NdisReleaseSpinLock(&(Queue->Lock));
4969 /*! \brief The destructor of MLME Queue
4974 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4976 IRQL = PASSIVE_LEVEL
4979 VOID MlmeQueueDestroy(
4980 IN MLME_QUEUE *pQueue)
4982 NdisAcquireSpinLock(&(pQueue->Lock));
4986 NdisReleaseSpinLock(&(pQueue->Lock));
4987 NdisFreeSpinLock(&(pQueue->Lock));
4990 /*! \brief To substitute the message type if the message is coming from external
4991 * \param pFrame The frame received
4992 * \param *Machine The state machine
4993 * \param *MsgType the message type for the state machine
4994 * \return TRUE if the substitution is successful, FALSE otherwise
4998 IRQL = DISPATCH_LEVEL
5001 #ifdef CONFIG_STA_SUPPORT
5002 BOOLEAN MsgTypeSubst(
5003 IN PRTMP_ADAPTER pAd,
5004 IN PFRAME_802_11 pFrame,
5012 // Pointer to start of data frames including SNAP header
5013 pData = (PUCHAR) pFrame + LENGTH_802_11;
5015 // The only data type will pass to this function is EAPOL frame
5016 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5018 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5020 // Cisco Aironet SNAP header
5021 *Machine = AIRONET_STATE_MACHINE;
5022 *MsgType = MT2_AIRONET_MSG;
5026 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5029 *Machine = LEAP_STATE_MACHINE;
5030 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5031 return (LeapMsgTypeSubst(EAPType, MsgType));
5034 #endif // LEAP_SUPPORT //
5036 *Machine = WPA_PSK_STATE_MACHINE;
5037 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5038 return(WpaMsgTypeSubst(EAPType, MsgType));
5042 switch (pFrame->Hdr.FC.SubType)
5044 case SUBTYPE_ASSOC_REQ:
5045 *Machine = ASSOC_STATE_MACHINE;
5046 *MsgType = MT2_PEER_ASSOC_REQ;
5048 case SUBTYPE_ASSOC_RSP:
5049 *Machine = ASSOC_STATE_MACHINE;
5050 *MsgType = MT2_PEER_ASSOC_RSP;
5052 case SUBTYPE_REASSOC_REQ:
5053 *Machine = ASSOC_STATE_MACHINE;
5054 *MsgType = MT2_PEER_REASSOC_REQ;
5056 case SUBTYPE_REASSOC_RSP:
5057 *Machine = ASSOC_STATE_MACHINE;
5058 *MsgType = MT2_PEER_REASSOC_RSP;
5060 case SUBTYPE_PROBE_REQ:
5061 *Machine = SYNC_STATE_MACHINE;
5062 *MsgType = MT2_PEER_PROBE_REQ;
5064 case SUBTYPE_PROBE_RSP:
5065 *Machine = SYNC_STATE_MACHINE;
5066 *MsgType = MT2_PEER_PROBE_RSP;
5068 case SUBTYPE_BEACON:
5069 *Machine = SYNC_STATE_MACHINE;
5070 *MsgType = MT2_PEER_BEACON;
5073 *Machine = SYNC_STATE_MACHINE;
5074 *MsgType = MT2_PEER_ATIM;
5076 case SUBTYPE_DISASSOC:
5077 *Machine = ASSOC_STATE_MACHINE;
5078 *MsgType = MT2_PEER_DISASSOC_REQ;
5081 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5082 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5083 if (Seq == 1 || Seq == 3)
5085 *Machine = AUTH_RSP_STATE_MACHINE;
5086 *MsgType = MT2_PEER_AUTH_ODD;
5088 else if (Seq == 2 || Seq == 4)
5090 *Machine = AUTH_STATE_MACHINE;
5091 *MsgType = MT2_PEER_AUTH_EVEN;
5098 case SUBTYPE_DEAUTH:
5099 *Machine = AUTH_RSP_STATE_MACHINE;
5100 *MsgType = MT2_PEER_DEAUTH;
5102 case SUBTYPE_ACTION:
5103 *Machine = ACTION_STATE_MACHINE;
5104 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5105 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5107 *MsgType = MT2_ACT_INVALID;
5111 *MsgType = (pFrame->Octet[0]&0x7F);
5121 #endif // CONFIG_STA_SUPPORT //
5123 // ===========================================================================================
5125 // ===========================================================================================
5127 /*! \brief Initialize the state machine.
5128 * \param *S pointer to the state machine
5129 * \param Trans State machine transition function
5130 * \param StNr number of states
5131 * \param MsgNr number of messages
5132 * \param DefFunc default function, when there is invalid state/message combination
5133 * \param InitState initial state of the state machine
5134 * \param Base StateMachine base, internal use only
5135 * \pre p_sm should be a legal pointer
5138 IRQL = PASSIVE_LEVEL
5141 VOID StateMachineInit(
5142 IN STATE_MACHINE *S,
5143 IN STATE_MACHINE_FUNC Trans[],
5146 IN STATE_MACHINE_FUNC DefFunc,
5152 // set number of states and messages
5157 S->TransFunc = Trans;
5159 // init all state transition to default function
5160 for (i = 0; i < StNr; i++)
5162 for (j = 0; j < MsgNr; j++)
5164 S->TransFunc[i * MsgNr + j] = DefFunc;
5168 // set the starting state
5169 S->CurrState = InitState;
5172 /*! \brief This function fills in the function pointer into the cell in the state machine
5173 * \param *S pointer to the state machine
5175 * \param Msg incoming message
5176 * \param f the function to be executed when (state, message) combination occurs at the state machine
5177 * \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
5180 IRQL = PASSIVE_LEVEL
5183 VOID StateMachineSetAction(
5184 IN STATE_MACHINE *S,
5187 IN STATE_MACHINE_FUNC Func)
5191 MsgIdx = Msg - S->Base;
5193 if (St < S->NrState && MsgIdx < S->NrMsg)
5195 // boundary checking before setting the action
5196 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5200 /*! \brief This function does the state transition
5201 * \param *Adapter the NIC adapter pointer
5202 * \param *S the state machine
5203 * \param *Elem the message to be executed
5206 IRQL = DISPATCH_LEVEL
5209 VOID StateMachinePerformAction(
5210 IN PRTMP_ADAPTER pAd,
5211 IN STATE_MACHINE *S,
5212 IN MLME_QUEUE_ELEM *Elem)
5214 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5218 ==========================================================================
5220 The drop function, when machine executes this, the message is simply
5221 ignored. This function does nothing, the message is freed in
5222 StateMachinePerformAction()
5223 ==========================================================================
5226 IN PRTMP_ADAPTER pAd,
5227 IN MLME_QUEUE_ELEM *Elem)
5231 // ===========================================================================================
5233 // ===========================================================================================
5236 ==========================================================================
5239 IRQL = PASSIVE_LEVEL
5241 ==========================================================================
5244 IN PRTMP_ADAPTER pAd,
5248 pAd->Mlme.ShiftReg = 1;
5250 pAd->Mlme.ShiftReg = Seed;
5254 ==========================================================================
5256 ==========================================================================
5259 IN PRTMP_ADAPTER pAd)
5266 if (pAd->Mlme.ShiftReg == 0)
5267 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5269 for (i = 0; i < 8; i++)
5271 if (pAd->Mlme.ShiftReg & 0x00000001)
5273 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5278 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5281 R = (R << 1) | Result;
5287 VOID AsicUpdateAutoFallBackTable(
5288 IN PRTMP_ADAPTER pAd,
5289 IN PUCHAR pRateTable)
5292 HT_FBK_CFG0_STRUC HtCfg0;
5293 HT_FBK_CFG1_STRUC HtCfg1;
5294 LG_FBK_CFG0_STRUC LgCfg0;
5295 LG_FBK_CFG1_STRUC LgCfg1;
5296 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5298 // set to initial value
5299 HtCfg0.word = 0x65432100;
5300 HtCfg1.word = 0xedcba988;
5301 LgCfg0.word = 0xedcba988;
5302 LgCfg1.word = 0x00002100;
5304 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5305 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5307 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5308 switch (pCurrTxRate->Mode)
5314 switch(pCurrTxRate->CurrMCS)
5317 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5320 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5323 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5326 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5329 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5332 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5335 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5338 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5343 #ifdef DOT11_N_SUPPORT
5347 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5349 switch(pCurrTxRate->CurrMCS)
5352 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5355 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5358 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5361 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5364 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5367 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5370 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5373 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5376 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5379 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5382 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5385 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5388 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5391 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5394 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5397 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5400 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5405 #endif // DOT11_N_SUPPORT //
5408 pNextTxRate = pCurrTxRate;
5411 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5412 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5413 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5414 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5418 ========================================================================
5420 Routine Description:
5421 Set MAC register value according operation mode.
5422 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5423 If MM or GF mask is not set, those passing argument doesn't not take effect.
5425 Operation mode meaning:
5426 = 0 : Pure HT, no preotection.
5427 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5428 = 0x10: No Transmission in 40M is protected.
5429 = 0x11: Transmission in both 40M and 20M shall be protected
5431 we should choose not to use GF. But still set correct ASIC registers.
5432 ========================================================================
5434 VOID AsicUpdateProtect(
5435 IN PRTMP_ADAPTER pAd,
5436 IN USHORT OperationMode,
5438 IN BOOLEAN bDisableBGProtect,
5439 IN BOOLEAN bNonGFExist)
5441 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5447 #ifdef DOT11_N_SUPPORT
5448 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5453 if (pAd->BATable.numAsOriginator)
5456 // enable the RTS/CTS to avoid channel collision
5458 SetMask = ALLN_SETPROTECT;
5461 #endif // DOT11_N_SUPPORT //
5463 // Config ASIC RTS threshold register
5464 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5465 MacReg &= 0xFF0000FF;
5467 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5469 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5471 #ifdef DOT11_N_SUPPORT
5472 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5473 #endif // DOT11_N_SUPPORT //
5474 (pAd->CommonCfg.bAggregationCapable == TRUE))
5475 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5477 MacReg |= (0x1000 << 8);
5481 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5485 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5487 // Initial common protection settings
5488 RTMPZeroMemory(Protect, sizeof(Protect));
5491 ProtCfg.field.TxopAllowGF40 = 1;
5492 ProtCfg.field.TxopAllowGF20 = 1;
5493 ProtCfg.field.TxopAllowMM40 = 1;
5494 ProtCfg.field.TxopAllowMM20 = 1;
5495 ProtCfg.field.TxopAllowOfdm = 1;
5496 ProtCfg.field.TxopAllowCck = 1;
5497 ProtCfg.field.RTSThEn = 1;
5498 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5500 // update PHY mode and rate
5501 if (pAd->CommonCfg.Channel > 14)
5502 ProtCfg.field.ProtectRate = 0x4000;
5503 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5505 // Handle legacy(B/G) protection
5506 if (bDisableBGProtect)
5508 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5509 ProtCfg.field.ProtectCtrl = 0;
5510 Protect[0] = ProtCfg.word;
5511 Protect[1] = ProtCfg.word;
5515 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5516 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5517 Protect[0] = ProtCfg.word;
5518 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5519 Protect[1] = ProtCfg.word;
5522 #ifdef DOT11_N_SUPPORT
5523 // Decide HT frame protection.
5524 if ((SetMask & ALLN_SETPROTECT) != 0)
5526 switch(OperationMode)
5530 // 1.All STAs in the BSS are 20/40 MHz HT
5531 // 2. in ai 20/40MHz BSS
5532 // 3. all STAs are 20MHz in a 20MHz BSS
5533 // Pure HT. no protection.
5537 // PROT_TXOP(25:20) -- 010111
5538 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5539 // PROT_CTRL(17:16) -- 00 (None)
5540 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5541 Protect[2] = 0x01744004;
5545 // PROT_TXOP(25:20) -- 111111
5546 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5547 // PROT_CTRL(17:16) -- 00 (None)
5548 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5549 Protect[3] = 0x03f44084;
5553 // PROT_TXOP(25:20) -- 010111
5554 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5555 // PROT_CTRL(17:16) -- 00 (None)
5556 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5557 Protect[4] = 0x01744004;
5561 // PROT_TXOP(25:20) -- 111111
5562 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5563 // PROT_CTRL(17:16) -- 00 (None)
5564 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5565 Protect[5] = 0x03f44084;
5569 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5570 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5571 Protect[4] = 0x01754004;
5572 Protect[5] = 0x03f54084;
5574 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5578 // This is "HT non-member protection mode."
5579 // If there may be non-HT STAs my BSS
5580 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5581 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5582 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5584 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5585 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5587 //Assign Protection method for 20&40 MHz packets
5588 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5589 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5590 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5591 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5592 Protect[2] = ProtCfg.word;
5593 Protect[3] = ProtCfg4.word;
5594 Protect[4] = ProtCfg.word;
5595 Protect[5] = ProtCfg4.word;
5596 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5600 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5601 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5602 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5604 //Assign Protection method for 40MHz packets
5605 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5606 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5607 Protect[2] = ProtCfg.word;
5608 Protect[3] = ProtCfg4.word;
5611 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5612 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5614 Protect[4] = ProtCfg.word;
5615 Protect[5] = ProtCfg4.word;
5617 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5621 // HT mixed mode. PROTECT ALL!
5623 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5624 ProtCfg4.word = 0x03f44084;
5625 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5626 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5628 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5629 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5631 //Assign Protection method for 20&40 MHz packets
5632 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5633 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5634 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5635 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5636 Protect[2] = ProtCfg.word;
5637 Protect[3] = ProtCfg4.word;
5638 Protect[4] = ProtCfg.word;
5639 Protect[5] = ProtCfg4.word;
5640 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5644 // Special on for Atheros problem n chip.
5645 Protect[2] = 0x01754004;
5646 Protect[3] = 0x03f54084;
5647 Protect[4] = 0x01754004;
5648 Protect[5] = 0x03f54084;
5649 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5653 #endif // DOT11_N_SUPPORT //
5655 offset = CCK_PROT_CFG;
5656 for (i = 0;i < 6;i++)
5658 if ((SetMask & (1<< i)))
5660 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5666 ==========================================================================
5669 IRQL = PASSIVE_LEVEL
5670 IRQL = DISPATCH_LEVEL
5672 ==========================================================================
5674 VOID AsicSwitchChannel(
5675 IN PRTMP_ADAPTER pAd,
5679 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5680 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5682 UINT32 Value = 0; //BbpReg, Value;
5683 RTMP_RF_REGS *RFRegTable;
5685 // Search Tx power value
5686 for (index = 0; index < pAd->ChannelListNum; index++)
5688 if (Channel == pAd->ChannelList[index].Channel)
5690 TxPwer = pAd->ChannelList[index].Power;
5691 TxPwer2 = pAd->ChannelList[index].Power2;
5696 if (index == MAX_NUM_OF_CHANNELS)
5698 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5702 // The RF programming sequence is difference between 3xxx and 2xxx
5703 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5705 /* modify by WY for Read RF Reg. error */
5708 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5710 if (Channel == FreqItems3020[index].Channel)
5712 // Programming channel parameters
5713 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5714 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5716 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5717 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5718 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5721 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5722 RFValue = (RFValue & 0xE0) | TxPwer;
5723 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5726 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5727 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5728 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5731 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5733 RFValue = pAd->Mlme.CaliBW40RfR24;
5734 //DISABLE_11N_CHECK(pAd);
5738 RFValue = pAd->Mlme.CaliBW20RfR24;
5740 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5743 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5744 RFValue = RFValue | 0x1;
5745 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5747 // latch channel for future usage.
5748 pAd->LatchRfRegs.Channel = Channel;
5754 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5759 pAd->Antenna.field.TxPath,
5760 FreqItems3020[index].N,
5761 FreqItems3020[index].K,
5762 FreqItems3020[index].R));
5767 RFRegTable = RF2850RegTable;
5769 switch (pAd->RfIcType)
5776 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5778 if (Channel == RFRegTable[index].Channel)
5780 R2 = RFRegTable[index].R2;
5781 if (pAd->Antenna.field.TxPath == 1)
5783 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5786 if (pAd->Antenna.field.RxPath == 2)
5788 R2 |= 0x40; // write 1 to off Rxpath.
5790 else if (pAd->Antenna.field.RxPath == 1)
5792 R2 |= 0x20040; // write 1 to off RxPath
5797 // initialize R3, R4
5798 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5799 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5801 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5803 if ((TxPwer >= -7) && (TxPwer < 0))
5805 TxPwer = (7+TxPwer);
5806 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5807 R3 |= (TxPwer << 10);
5808 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5812 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5813 R3 |= (TxPwer << 10) | (1 << 9);
5817 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5819 TxPwer2 = (7+TxPwer2);
5820 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5821 R4 |= (TxPwer2 << 7);
5822 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5826 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5827 R4 |= (TxPwer2 << 7) | (1 << 6);
5832 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5833 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5836 // Based on BBP current mode before changing RF channel.
5837 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5843 pAd->LatchRfRegs.Channel = Channel;
5844 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5845 pAd->LatchRfRegs.R2 = R2;
5846 pAd->LatchRfRegs.R3 = R3;
5847 pAd->LatchRfRegs.R4 = R4;
5849 // Set RF value 1's set R3[bit2] = [0]
5850 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5851 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5852 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5853 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5857 // Set RF value 2's set R3[bit2] = [1]
5858 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5859 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5860 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5861 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5865 // Set RF value 3's set R3[bit2] = [0]
5866 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5867 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5868 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5869 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5881 // Change BBP setting during siwtch from a->g, g->a
5884 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5886 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5887 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5888 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5889 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.
5890 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5892 // Rx High power VGA offset for LNA select
5893 if (pAd->NicConfig2.field.ExternalLNAForG)
5895 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5896 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5900 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5901 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5904 // 5G band selection PIN, bit1 and bit2 are complement
5905 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5908 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5910 // Turn off unused PA or LNA when only 1T or 1R
5911 if (pAd->Antenna.field.TxPath == 1)
5913 TxPinCfg &= 0xFFFFFFF3;
5915 if (pAd->Antenna.field.RxPath == 1)
5917 TxPinCfg &= 0xFFFFF3FF;
5920 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5924 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5926 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5927 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5928 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5929 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.
5930 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5932 // Rx High power VGA offset for LNA select
5933 if (pAd->NicConfig2.field.ExternalLNAForA)
5935 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5939 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5942 // 5G band selection PIN, bit1 and bit2 are complement
5943 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5946 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5948 // Turn off unused PA or LNA when only 1T or 1R
5949 if (pAd->Antenna.field.TxPath == 1)
5951 TxPinCfg &= 0xFFFFFFF3;
5953 if (pAd->Antenna.field.RxPath == 1)
5955 TxPinCfg &= 0xFFFFF3FF;
5958 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5961 // R66 should be set according to Channel and use 20MHz when scanning
5962 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5964 RTMPSetAGCInitValue(pAd, BW_20);
5966 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5969 // On 11A, We should delay and wait RF/BBP to be stable
5970 // and the appropriate time should be 1000 micro seconds
5971 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5973 RTMPusecDelay(1000);
5975 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",
5978 (R3 & 0x00003e00) >> 9,
5979 (R4 & 0x000007c0) >> 6,
5980 pAd->Antenna.field.TxPath,
5981 pAd->LatchRfRegs.R1,
5982 pAd->LatchRfRegs.R2,
5983 pAd->LatchRfRegs.R3,
5984 pAd->LatchRfRegs.R4));
5988 ==========================================================================
5990 This function is required for 2421 only, and should not be used during
5991 site survey. It's only required after NIC decided to stay at a channel
5992 for a longer period.
5993 When this function is called, it's always after AsicSwitchChannel().
5995 IRQL = PASSIVE_LEVEL
5996 IRQL = DISPATCH_LEVEL
5998 ==========================================================================
6000 VOID AsicLockChannel(
6001 IN PRTMP_ADAPTER pAd,
6007 ==========================================================================
6010 IRQL = PASSIVE_LEVEL
6011 IRQL = DISPATCH_LEVEL
6013 ==========================================================================
6015 VOID AsicAntennaSelect(
6016 IN PRTMP_ADAPTER pAd,
6022 ========================================================================
6024 Routine Description:
6025 Antenna miscellaneous setting.
6028 pAd Pointer to our adapter
6029 BandState Indicate current Band State.
6034 IRQL <= DISPATCH_LEVEL
6037 1.) Frame End type control
6038 only valid for G only (RF_2527 & RF_2529)
6039 0: means DPDT, set BBP R4 bit 5 to 1
6040 1: means SPDT, set BBP R4 bit 5 to 0
6043 ========================================================================
6045 VOID AsicAntennaSetting(
6046 IN PRTMP_ADAPTER pAd,
6047 IN ABGBAND_STATE BandState)
6051 VOID AsicRfTuningExec(
6052 IN PVOID SystemSpecific1,
6053 IN PVOID FunctionContext,
6054 IN PVOID SystemSpecific2,
6055 IN PVOID SystemSpecific3)
6060 ==========================================================================
6062 Gives CCK TX rate 2 more dB TX power.
6063 This routine works only in LINK UP in INFRASTRUCTURE mode.
6065 calculate desired Tx power in RF R3.Tx0~5, should consider -
6066 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6067 1. TxPowerPercentage
6068 2. auto calibration based on TSSI feedback
6069 3. extra 2 db for CCK
6070 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6072 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6073 it should be called AFTER MlmeDynamicTxRatSwitching()
6074 ==========================================================================
6076 VOID AsicAdjustTxPower(
6077 IN PRTMP_ADAPTER pAd)
6081 BOOLEAN bAutoTxAgc = FALSE;
6082 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6083 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6084 PCHAR pTxAgcCompensate;
6088 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6090 if (pAd->CommonCfg.CentralChannel > 14)
6092 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6093 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6094 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6095 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6096 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6100 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6101 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6102 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6103 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6104 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6109 if (pAd->CommonCfg.Channel > 14)
6111 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6112 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6113 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6114 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6115 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6119 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6120 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6121 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6122 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6123 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6127 // TX power compensation for temperature variation based on TSSI. try every 4 second
6128 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6130 if (pAd->CommonCfg.Channel <= 14)
6133 bAutoTxAgc = pAd->bAutoTxAgcG;
6134 TssiRef = pAd->TssiRefG;
6135 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6136 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6137 TxAgcStep = pAd->TxAgcStepG;
6138 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6143 bAutoTxAgc = pAd->bAutoTxAgcA;
6144 TssiRef = pAd->TssiRefA;
6145 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6146 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6147 TxAgcStep = pAd->TxAgcStepA;
6148 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6153 /* BbpR1 is unsigned char */
6154 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6156 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6157 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6158 /* step value is defined in pAd->TxAgcStepG for tx power value */
6160 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6161 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6162 above value are examined in mass factory production */
6163 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6165 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6166 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6167 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6169 if (BbpR49 > pTssiMinusBoundary[1])
6171 // Reading is larger than the reference value
6172 // check for how large we need to decrease the Tx power
6173 for (idx = 1; idx < 5; idx++)
6175 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6178 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6179 // if (R3 > (ULONG) (TxAgcStep * (idx-1)))
6180 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6182 // *pTxAgcCompensate = -((UCHAR)R3);
6184 DeltaPwr += (*pTxAgcCompensate);
6185 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6186 BbpR49, TssiRef, TxAgcStep, idx-1));
6188 else if (BbpR49 < pTssiPlusBoundary[1])
6190 // Reading is smaller than the reference value
6191 // check for how large we need to increase the Tx power
6192 for (idx = 1; idx < 5; idx++)
6194 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6197 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6198 *pTxAgcCompensate = TxAgcStep * (idx-1);
6199 DeltaPwr += (*pTxAgcCompensate);
6200 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6201 BbpR49, TssiRef, TxAgcStep, idx-1));
6205 *pTxAgcCompensate = 0;
6206 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6207 BbpR49, TssiRef, TxAgcStep, 0));
6213 if (pAd->CommonCfg.Channel <= 14)
6215 bAutoTxAgc = pAd->bAutoTxAgcG;
6216 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6220 bAutoTxAgc = pAd->bAutoTxAgcA;
6221 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6225 DeltaPwr += (*pTxAgcCompensate);
6228 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6232 // Handle regulatory max tx power constrain
6235 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6236 UCHAR AdjustMaxTxPwr[40];
6238 if (pAd->CommonCfg.Channel > 14) // 5G band
6239 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6241 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6242 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6244 // error handling, range check
6245 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6247 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6251 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6253 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6255 // Adjust max tx power according to the relationship of tx power in E2PROM
6258 // CCK will have 4dBm larger than OFDM
6259 // Therefore, we should separate to parse the tx power field
6264 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6268 // CCK will have 4dBm larger than OFDM
6269 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6273 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6275 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6282 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6284 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6285 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6290 // Adjust tx power according to the relationship
6293 if (TxPwr[i] != 0xffffffff)
6297 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6299 // The system tx power is larger than the regulatory, the power should be restrain
6300 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6302 // decrease to zero and don't need to take care BBPR1
6303 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6304 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6308 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6311 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6313 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6318 #endif // SINGLE_SKU //
6320 /* calculate delta power based on the percentage specified from UI */
6321 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6322 // We lower TX power here according to the percentage specified from UI
6323 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6325 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6327 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6331 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6335 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6339 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6344 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6349 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6351 /* reset different new tx power for different TX rate */
6354 if (TxPwr[i] != 0xffffffff)
6358 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6360 if ((Value + DeltaPwr) < 0)
6362 Value = 0; /* min */
6364 else if ((Value + DeltaPwr) > 0xF)
6366 Value = 0xF; /* max */
6370 Value += DeltaPwr; /* temperature compensation */
6373 /* fill new value to CSR offset */
6374 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6377 /* write tx power value to CSR */
6378 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6379 TX power for OFDM 6M/9M
6380 TX power for CCK5.5M/11M
6381 TX power for CCK1M/2M */
6382 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6383 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6389 #ifdef CONFIG_STA_SUPPORT
6391 ==========================================================================
6393 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6394 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6395 the wakeup timer timeout. Driver has to issue a separate command to wake
6398 IRQL = DISPATCH_LEVEL
6400 ==========================================================================
6402 VOID AsicSleepThenAutoWakeup(
6403 IN PRTMP_ADAPTER pAd,
6404 IN USHORT TbttNumToNextWakeUp)
6406 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6410 ==========================================================================
6412 AsicForceWakeup() is used whenever manual wakeup is required
6413 AsicForceSleep() should only be used when not in INFRA BSS. When
6414 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6415 ==========================================================================
6417 VOID AsicForceSleep(
6418 IN PRTMP_ADAPTER pAd)
6424 ==========================================================================
6426 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6429 IRQL = PASSIVE_LEVEL
6430 IRQL = DISPATCH_LEVEL
6431 ==========================================================================
6433 VOID AsicForceWakeup(
6434 IN PRTMP_ADAPTER pAd,
6437 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6438 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6440 #endif // CONFIG_STA_SUPPORT //
6442 ==========================================================================
6446 IRQL = DISPATCH_LEVEL
6448 ==========================================================================
6451 IN PRTMP_ADAPTER pAd,
6455 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6456 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6458 Addr4 = (ULONG)(pBssid[0]) |
6459 (ULONG)(pBssid[1] << 8) |
6460 (ULONG)(pBssid[2] << 16) |
6461 (ULONG)(pBssid[3] << 24);
6462 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6465 // always one BSSID in STA mode
6466 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6468 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6471 VOID AsicSetMcastWC(
6472 IN PRTMP_ADAPTER pAd)
6474 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6477 pEntry->Sst = SST_ASSOC;
6478 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6479 pEntry->PsMode = PWR_ACTIVE;
6480 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6481 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6485 ==========================================================================
6488 IRQL = DISPATCH_LEVEL
6490 ==========================================================================
6492 VOID AsicDelWcidTab(
6493 IN PRTMP_ADAPTER pAd,
6496 ULONG Addr0 = 0x0, Addr1 = 0x0;
6499 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6500 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6501 RTMP_IO_WRITE32(pAd, offset, Addr0);
6503 RTMP_IO_WRITE32(pAd, offset, Addr1);
6507 ==========================================================================
6510 IRQL = DISPATCH_LEVEL
6512 ==========================================================================
6515 IN PRTMP_ADAPTER pAd)
6517 TX_LINK_CFG_STRUC TxLinkCfg;
6520 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6521 TxLinkCfg.field.TxRDGEn = 1;
6522 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6524 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6527 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6529 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6533 ==========================================================================
6536 IRQL = DISPATCH_LEVEL
6538 ==========================================================================
6540 VOID AsicDisableRDG(
6541 IN PRTMP_ADAPTER pAd)
6543 TX_LINK_CFG_STRUC TxLinkCfg;
6547 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6548 TxLinkCfg.field.TxRDGEn = 0;
6549 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6551 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6556 //if ( pAd->CommonCfg.bEnableTxBurst )
6557 // Data |= 0x60; // for performance issue not set the TXOP to 0
6559 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6560 #ifdef DOT11_N_SUPPORT
6561 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6562 #endif // DOT11_N_SUPPORT //
6565 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6566 if (pAd->CommonCfg.bEnableTxBurst)
6569 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6573 ==========================================================================
6576 IRQL = PASSIVE_LEVEL
6577 IRQL = DISPATCH_LEVEL
6579 ==========================================================================
6581 VOID AsicDisableSync(
6582 IN PRTMP_ADAPTER pAd)
6584 BCN_TIME_CFG_STRUC csr;
6586 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6588 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6589 // that NIC will never wakes up because TSF stops and no more
6591 pAd->TbttTickCount = 0;
6592 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6593 csr.field.bBeaconGen = 0;
6594 csr.field.bTBTTEnable = 0;
6595 csr.field.TsfSyncMode = 0;
6596 csr.field.bTsfTicking = 0;
6597 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6602 ==========================================================================
6605 IRQL = DISPATCH_LEVEL
6607 ==========================================================================
6609 VOID AsicEnableBssSync(
6610 IN PRTMP_ADAPTER pAd)
6612 BCN_TIME_CFG_STRUC csr;
6614 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6616 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6617 // RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);
6618 #ifdef CONFIG_STA_SUPPORT
6619 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6621 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6622 csr.field.bTsfTicking = 1;
6623 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6624 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6625 csr.field.bTBTTEnable = 1;
6627 #endif // CONFIG_STA_SUPPORT //
6628 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6632 ==========================================================================
6635 BEACON frame in shared memory should be built ok before this routine
6636 can be called. Otherwise, a garbage frame maybe transmitted out every
6639 IRQL = DISPATCH_LEVEL
6641 ==========================================================================
6643 VOID AsicEnableIbssSync(
6644 IN PRTMP_ADAPTER pAd)
6646 BCN_TIME_CFG_STRUC csr9;
6650 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6652 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6653 csr9.field.bBeaconGen = 0;
6654 csr9.field.bTBTTEnable = 0;
6655 csr9.field.bTsfTicking = 0;
6656 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6660 // move BEACON TXD and frame content to on-chip memory
6661 ptr = (PUCHAR)&pAd->BeaconTxWI;
6662 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6664 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6665 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6666 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6670 // start right after the 16-byte TXWI field
6671 ptr = pAd->BeaconBuf;
6672 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6674 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6675 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6676 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6682 // For Wi-Fi faily generated beacons between participating stations.
6683 // Set TBTT phase adaptive adjustment step to 8us (default 16us)
6684 // don't change settings 2006-5- by Jerry
6685 //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);
6687 // start sending BEACON
6688 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6689 csr9.field.bTsfTicking = 1;
6690 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6691 csr9.field.bTBTTEnable = 1;
6692 csr9.field.bBeaconGen = 1;
6693 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6697 ==========================================================================
6700 IRQL = PASSIVE_LEVEL
6701 IRQL = DISPATCH_LEVEL
6703 ==========================================================================
6705 VOID AsicSetEdcaParm(
6706 IN PRTMP_ADAPTER pAd,
6707 IN PEDCA_PARM pEdcaParm)
6709 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6710 AC_TXOP_CSR0_STRUC csr0;
6711 AC_TXOP_CSR1_STRUC csr1;
6712 AIFSN_CSR_STRUC AifsnCsr;
6713 CWMIN_CSR_STRUC CwminCsr;
6714 CWMAX_CSR_STRUC CwmaxCsr;
6721 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6723 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6724 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6725 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6727 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6728 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6731 //========================================================
6732 // MAC Register has a copy .
6733 //========================================================
6735 if( pAd->CommonCfg.bEnableTxBurst )
6737 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6738 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6741 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6743 // Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6745 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6746 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6747 Ac0Cfg.field.Aifsn = 2;
6748 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6750 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6751 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6752 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6753 Ac1Cfg.field.Aifsn = 2;
6754 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6756 if (pAd->CommonCfg.PhyMode == PHY_11B)
6758 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6759 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6763 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6764 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6766 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6767 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6768 Ac2Cfg.field.Aifsn = 2;
6769 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6770 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6771 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6772 Ac3Cfg.field.Aifsn = 2;
6773 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6775 //========================================================
6776 // DMA Register has a copy too.
6777 //========================================================
6778 csr0.field.Ac0Txop = 0; // QID_AC_BE
6779 csr0.field.Ac1Txop = 0; // QID_AC_BK
6780 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6781 if (pAd->CommonCfg.PhyMode == PHY_11B)
6783 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6784 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6788 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6789 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6791 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6794 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6795 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6796 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6797 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6798 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6801 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6802 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6803 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6804 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6805 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6807 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6809 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6813 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6814 //========================================================
6815 // MAC Register has a copy.
6816 //========================================================
6818 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6819 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6821 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6823 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6824 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6825 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6826 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6828 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6829 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6830 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6831 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6833 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6834 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6835 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6836 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6837 #ifdef CONFIG_STA_SUPPORT
6838 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6840 // Tuning for Wi-Fi WMM S06
6841 if (pAd->CommonCfg.bWiFiTest &&
6842 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6843 Ac2Cfg.field.Aifsn -= 1;
6845 // Tuning for TGn Wi-Fi 5.2.32
6846 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6847 if (STA_TGN_WIFI_ON(pAd) &&
6848 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6850 Ac0Cfg.field.Aifsn = 3;
6851 Ac2Cfg.field.AcTxop = 5;
6854 #endif // CONFIG_STA_SUPPORT //
6856 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6857 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6858 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6859 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6862 if (pAd->CommonCfg.bWiFiTest)
6864 if (Ac3Cfg.field.AcTxop == 102)
6866 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6867 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6868 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6869 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6870 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6873 //#endif // WIFI_TEST //
6875 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6876 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6877 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6878 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6881 //========================================================
6882 // DMA Register has a copy too.
6883 //========================================================
6884 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6885 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6886 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6888 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6889 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6890 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6893 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6894 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6895 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6896 #ifdef CONFIG_STA_SUPPORT
6897 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6898 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6899 #endif // CONFIG_STA_SUPPORT //
6900 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6903 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6904 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6905 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6906 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6907 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6910 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6911 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6912 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6913 #ifdef CONFIG_STA_SUPPORT
6914 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6916 // Tuning for Wi-Fi WMM S06
6917 if (pAd->CommonCfg.bWiFiTest &&
6918 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6919 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6921 // Tuning for TGn Wi-Fi 5.2.32
6922 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6923 if (STA_TGN_WIFI_ON(pAd) &&
6924 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6926 AifsnCsr.field.Aifsn0 = 3;
6927 AifsnCsr.field.Aifsn2 = 7;
6931 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
6933 #endif // CONFIG_STA_SUPPORT //
6935 #ifdef CONFIG_STA_SUPPORT
6936 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6937 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6938 #endif // CONFIG_STA_SUPPORT //
6939 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6941 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6944 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6945 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6946 pEdcaParm->Aifsn[0],
6947 pEdcaParm->Cwmin[0],
6948 pEdcaParm->Cwmax[0],
6949 pEdcaParm->Txop[0]<<5,
6950 pEdcaParm->bACM[0]));
6951 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6952 pEdcaParm->Aifsn[1],
6953 pEdcaParm->Cwmin[1],
6954 pEdcaParm->Cwmax[1],
6955 pEdcaParm->Txop[1]<<5,
6956 pEdcaParm->bACM[1]));
6957 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6958 pEdcaParm->Aifsn[2],
6959 pEdcaParm->Cwmin[2],
6960 pEdcaParm->Cwmax[2],
6961 pEdcaParm->Txop[2]<<5,
6962 pEdcaParm->bACM[2]));
6963 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6964 pEdcaParm->Aifsn[3],
6965 pEdcaParm->Cwmin[3],
6966 pEdcaParm->Cwmax[3],
6967 pEdcaParm->Txop[3]<<5,
6968 pEdcaParm->bACM[3]));
6974 ==========================================================================
6977 IRQL = PASSIVE_LEVEL
6978 IRQL = DISPATCH_LEVEL
6980 ==========================================================================
6982 VOID AsicSetSlotTime(
6983 IN PRTMP_ADAPTER pAd,
6984 IN BOOLEAN bUseShortSlotTime)
6987 UINT32 RegValue = 0;
6989 #ifdef CONFIG_STA_SUPPORT
6990 if (pAd->CommonCfg.Channel > 14)
6991 bUseShortSlotTime = TRUE;
6992 #endif // CONFIG_STA_SUPPORT //
6994 if (bUseShortSlotTime)
6995 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6997 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6999 SlotTime = (bUseShortSlotTime)? 9 : 20;
7001 #ifdef CONFIG_STA_SUPPORT
7002 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7004 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7005 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7006 #ifdef DOT11_N_SUPPORT
7007 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7008 #endif // DOT11_N_SUPPORT //
7011 // In this case, we will think it is doing Wi-Fi test
7012 // And we will not set to short slot when bEnableTxBurst is TRUE.
7014 else if (pAd->CommonCfg.bEnableTxBurst)
7017 #endif // CONFIG_STA_SUPPORT //
7020 // For some reasons, always set it to short slot time.
7022 // ToDo: Should consider capability with 11B
7024 #ifdef CONFIG_STA_SUPPORT
7025 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7027 if (pAd->StaCfg.BssType == BSS_ADHOC)
7030 #endif // CONFIG_STA_SUPPORT //
7032 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7033 RegValue = RegValue & 0xFFFFFF00;
7035 RegValue |= SlotTime;
7037 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7041 ========================================================================
7043 Add Shared key information into ASIC.
7044 Update shared key, TxMic and RxMic to Asic Shared key table
7045 Update its cipherAlg to Asic Shared key Mode.
7048 ========================================================================
7050 VOID AsicAddSharedKeyEntry(
7051 IN PRTMP_ADAPTER pAd,
7059 ULONG offset; //, csr0;
7060 SHAREDKEY_MODE_STRUC csr1;
7062 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7063 //============================================================================================
7065 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7066 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7067 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]));
7070 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7071 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7075 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7076 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7078 //============================================================================================
7080 // fill key material - key + TX MIC + RX MIC
7085 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7086 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7088 offset += MAX_LEN_OF_SHARE_KEY;
7091 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7097 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7103 // Update cipher algorithm. WSTA always use BSS0
7105 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7106 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7107 if ((BssIndex%2) == 0)
7110 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7111 else if (KeyIdx == 1)
7112 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7113 else if (KeyIdx == 2)
7114 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7116 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7121 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7122 else if (KeyIdx == 1)
7123 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7124 else if (KeyIdx == 2)
7125 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7127 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7129 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7130 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7134 // IRQL = DISPATCH_LEVEL
7135 VOID AsicRemoveSharedKeyEntry(
7136 IN PRTMP_ADAPTER pAd,
7141 SHAREDKEY_MODE_STRUC csr1;
7143 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7145 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7146 if ((BssIndex%2) == 0)
7149 csr1.field.Bss0Key0CipherAlg = 0;
7150 else if (KeyIdx == 1)
7151 csr1.field.Bss0Key1CipherAlg = 0;
7152 else if (KeyIdx == 2)
7153 csr1.field.Bss0Key2CipherAlg = 0;
7155 csr1.field.Bss0Key3CipherAlg = 0;
7160 csr1.field.Bss1Key0CipherAlg = 0;
7161 else if (KeyIdx == 1)
7162 csr1.field.Bss1Key1CipherAlg = 0;
7163 else if (KeyIdx == 2)
7164 csr1.field.Bss1Key2CipherAlg = 0;
7166 csr1.field.Bss1Key3CipherAlg = 0;
7168 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7169 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7170 ASSERT(BssIndex < 4);
7176 VOID AsicUpdateWCIDAttribute(
7177 IN PRTMP_ADAPTER pAd,
7181 IN BOOLEAN bUsePairewiseKeyTable)
7183 ULONG WCIDAttri = 0, offset;
7186 // Update WCID attribute.
7187 // Only TxKey could update WCID attribute.
7189 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7190 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7191 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7194 VOID AsicUpdateWCIDIVEIV(
7195 IN PRTMP_ADAPTER pAd,
7202 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7204 RTMP_IO_WRITE32(pAd, offset, uIV);
7205 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7208 VOID AsicUpdateRxWCIDTable(
7209 IN PRTMP_ADAPTER pAd,
7216 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7217 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7218 RTMP_IO_WRITE32(pAd, offset, Addr);
7219 Addr = pAddr[4] + (pAddr[5] << 8);
7220 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7225 ========================================================================
7227 Routine Description:
7228 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7231 pAd Pointer to our adapter
7232 WCID WCID Entry number.
7233 BssIndex BSSID index, station or none multiple BSSID support
7234 this value should be 0.
7235 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7236 pCipherKey Pointer to Cipher Key.
7237 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7238 otherwise PairewiseKey table
7239 bTxKey This is the transmit key if enabled.
7245 This routine will set the relative key stuff to Asic including WCID attribute,
7246 Cipher Key, Cipher algorithm and IV/EIV.
7248 IV/EIV will be update if this CipherKey is the transmission key because
7249 ASIC will base on IV's KeyID value to select Cipher Key.
7251 If bTxKey sets to FALSE, this is not the TX key, but it could be
7254 For AP mode bTxKey must be always set to TRUE.
7255 ========================================================================
7257 VOID AsicAddKeyEntry(
7258 IN PRTMP_ADAPTER pAd,
7262 IN PCIPHER_KEY pCipherKey,
7263 IN BOOLEAN bUsePairewiseKeyTable,
7267 // ULONG WCIDAttri = 0;
7269 PUCHAR pKey = pCipherKey->Key;
7270 // ULONG KeyLen = pCipherKey->KeyLen;
7271 PUCHAR pTxMic = pCipherKey->TxMic;
7272 PUCHAR pRxMic = pCipherKey->RxMic;
7273 PUCHAR pTxtsc = pCipherKey->TxTsc;
7274 UCHAR CipherAlg = pCipherKey->CipherAlg;
7275 SHAREDKEY_MODE_STRUC csr1;
7277 // ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY);
7279 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7281 // 1.) decide key table offset
7283 if (bUsePairewiseKeyTable)
7284 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7286 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7289 // 2.) Set Key to Asic
7291 //for (i = 0; i < KeyLen; i++)
7294 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7295 offset += MAX_LEN_OF_PEER_KEY;
7298 // 3.) Set MIC key if available
7302 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7304 offset += LEN_TKIP_TXMICK;
7308 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7313 // 4.) Modify IV/EIV if needs
7314 // This will force Asic to use this key ID by setting IV.
7325 IV4 = (KeyIdx << 6);
7326 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7327 IV4 |= 0x20; // turn on extension bit means EIV existence
7329 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7330 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7336 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7338 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7341 if (!bUsePairewiseKeyTable)
7344 // Only update the shared key security mode
7346 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7347 if ((BssIndex % 2) == 0)
7350 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7351 else if (KeyIdx == 1)
7352 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7353 else if (KeyIdx == 2)
7354 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7356 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7361 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7362 else if (KeyIdx == 1)
7363 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7364 else if (KeyIdx == 2)
7365 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7367 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7369 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7372 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7377 ========================================================================
7379 Add Pair-wise key material into ASIC.
7380 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7383 ========================================================================
7385 VOID AsicAddPairwiseKeyEntry(
7386 IN PRTMP_ADAPTER pAd,
7389 IN CIPHER_KEY *pCipherKey)
7393 PUCHAR pKey = pCipherKey->Key;
7394 PUCHAR pTxMic = pCipherKey->TxMic;
7395 PUCHAR pRxMic = pCipherKey->RxMic;
7397 UCHAR CipherAlg = pCipherKey->CipherAlg;
7401 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7403 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7405 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7408 RTMP_IO_READ32(pAd, offset + i, &Value);
7411 offset += MAX_LEN_OF_PEER_KEY;
7417 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7424 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7428 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7429 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7430 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]));
7433 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7434 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7438 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7439 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7443 ========================================================================
7445 Remove Pair-wise key material from ASIC.
7448 ========================================================================
7450 VOID AsicRemovePairwiseKeyEntry(
7451 IN PRTMP_ADAPTER pAd,
7458 // re-set the entry's WCID attribute as OPEN-NONE.
7459 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7460 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7461 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7464 BOOLEAN AsicSendCommandToMcu(
7465 IN PRTMP_ADAPTER pAd,
7471 HOST_CMD_CSR_STRUC H2MCmd;
7472 H2M_MAILBOX_STRUC H2MMailbox;
7476 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7477 if (H2MMailbox.field.Owner == 0)
7486 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7492 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7493 H2MMailbox.field.CmdToken = Token;
7494 H2MMailbox.field.HighByte = Arg1;
7495 H2MMailbox.field.LowByte = Arg0;
7496 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7499 H2MCmd.field.HostCommand = Command;
7500 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7502 if (Command != 0x80)
7511 ========================================================================
7513 Routine Description:
7514 Verify the support rate for different PHY type
7517 pAd Pointer to our adapter
7522 IRQL = PASSIVE_LEVEL
7524 ========================================================================
7526 VOID RTMPCheckRates(
7527 IN PRTMP_ADAPTER pAd,
7528 IN OUT UCHAR SupRate[],
7529 IN OUT UCHAR *SupRateLen)
7531 UCHAR RateIdx, i, j;
7532 UCHAR NewRate[12], NewRateLen;
7536 if (pAd->CommonCfg.PhyMode == PHY_11B)
7541 // Check for support rates exclude basic rate bit
7542 for (i = 0; i < *SupRateLen; i++)
7543 for (j = 0; j < RateIdx; j++)
7544 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7545 NewRate[NewRateLen++] = SupRate[i];
7547 *SupRateLen = NewRateLen;
7548 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7551 #ifdef CONFIG_STA_SUPPORT
7552 #ifdef DOT11_N_SUPPORT
7553 BOOLEAN RTMPCheckChannel(
7554 IN PRTMP_ADAPTER pAd,
7555 IN UCHAR CentralChannel,
7559 UCHAR UpperChannel = 0, LowerChannel = 0;
7560 UCHAR NoEffectChannelinList = 0;
7562 // Find upper and lower channel according to 40MHz current operation.
7563 if (CentralChannel < Channel)
7565 UpperChannel = Channel;
7566 if (CentralChannel > 2)
7567 LowerChannel = CentralChannel - 2;
7571 else if (CentralChannel > Channel)
7573 UpperChannel = CentralChannel + 2;
7574 LowerChannel = Channel;
7577 for (k = 0;k < pAd->ChannelListNum;k++)
7579 if (pAd->ChannelList[k].Channel == UpperChannel)
7581 NoEffectChannelinList ++;
7583 if (pAd->ChannelList[k].Channel == LowerChannel)
7585 NoEffectChannelinList ++;
7589 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7590 if (NoEffectChannelinList == 2)
7597 ========================================================================
7599 Routine Description:
7600 Verify the support rate for HT phy type
7603 pAd Pointer to our adapter
7606 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7608 IRQL = PASSIVE_LEVEL
7610 ========================================================================
7612 BOOLEAN RTMPCheckHt(
7613 IN PRTMP_ADAPTER pAd,
7615 IN HT_CAPABILITY_IE *pHtCapability,
7616 IN ADD_HT_INFO_IE *pAddHtInfo)
7618 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7621 // If use AMSDU, set flag.
7622 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7623 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7624 // Save Peer Capability
7625 if (pHtCapability->HtCapInfo.ShortGIfor20)
7626 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7627 if (pHtCapability->HtCapInfo.ShortGIfor40)
7628 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7629 if (pHtCapability->HtCapInfo.TxSTBC)
7630 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7631 if (pHtCapability->HtCapInfo.RxSTBC)
7632 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7633 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7635 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7638 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7640 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7643 // Will check ChannelWidth for MCSSet[4] below
7644 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7645 switch (pAd->CommonCfg.RxStream)
7648 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7649 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7650 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7651 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7654 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7655 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7656 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7657 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7660 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7661 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7662 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7663 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7667 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7669 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7670 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7671 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7673 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7675 // Send Assoc Req with my HT capability.
7676 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7677 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7678 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7679 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7680 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7681 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7682 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7683 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7684 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7685 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7686 if (pAd->CommonCfg.bRdg)
7688 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7689 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7692 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7693 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7695 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7698 #endif // DOT11_N_SUPPORT //
7699 #endif // CONFIG_STA_SUPPORT //
7702 ========================================================================
7704 Routine Description:
7705 Verify the support rate for different PHY type
7708 pAd Pointer to our adapter
7713 IRQL = PASSIVE_LEVEL
7715 ========================================================================
7717 VOID RTMPUpdateMlmeRate(
7718 IN PRTMP_ADAPTER pAd)
7721 UCHAR ProperMlmeRate; //= RATE_54;
7722 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7723 BOOLEAN bMatch = FALSE;
7725 switch (pAd->CommonCfg.PhyMode)
7728 ProperMlmeRate = RATE_11;
7729 MinimumRate = RATE_1;
7731 case PHY_11BG_MIXED:
7732 #ifdef DOT11_N_SUPPORT
7733 case PHY_11ABGN_MIXED:
7734 case PHY_11BGN_MIXED:
7735 #endif // DOT11_N_SUPPORT //
7736 if ((pAd->MlmeAux.SupRateLen == 4) &&
7737 (pAd->MlmeAux.ExtRateLen == 0))
7739 ProperMlmeRate = RATE_11;
7741 ProperMlmeRate = RATE_24;
7743 if (pAd->MlmeAux.Channel <= 14)
7744 MinimumRate = RATE_1;
7746 MinimumRate = RATE_6;
7749 #ifdef DOT11_N_SUPPORT
7750 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7751 case PHY_11GN_MIXED:
7752 case PHY_11AGN_MIXED:
7753 case PHY_11AN_MIXED:
7755 #endif // DOT11_N_SUPPORT //
7756 ProperMlmeRate = RATE_24;
7757 MinimumRate = RATE_6;
7759 case PHY_11ABG_MIXED:
7760 ProperMlmeRate = RATE_24;
7761 if (pAd->MlmeAux.Channel <= 14)
7762 MinimumRate = RATE_1;
7764 MinimumRate = RATE_6;
7767 ProperMlmeRate = RATE_1;
7768 MinimumRate = RATE_1;
7772 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7774 for (j = 0; j < RateIdx; j++)
7776 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7778 if (j == ProperMlmeRate)
7790 if (bMatch == FALSE)
7792 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7794 for (j = 0; j < RateIdx; j++)
7796 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7798 if (j == ProperMlmeRate)
7811 if (bMatch == FALSE)
7813 ProperMlmeRate = MinimumRate;
7816 pAd->CommonCfg.MlmeRate = MinimumRate;
7817 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7818 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7820 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7821 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7822 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7823 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7827 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7828 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7829 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7830 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7833 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7837 IN PRTMP_ADAPTER pAd,
7844 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7849 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7851 larger = max(Rssi0, Rssi1);
7854 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7856 larger = max(larger, Rssi2);
7866 ========================================================================
7867 Routine Description:
7868 Periodic evaluate antenna link status
7871 pAd - Adapter pointer
7876 ========================================================================
7878 VOID AsicEvaluateRxAnt(
7879 IN PRTMP_ADAPTER pAd)
7883 #ifdef CONFIG_STA_SUPPORT
7884 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7886 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7887 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7888 fRTMP_ADAPTER_RADIO_OFF |
7889 fRTMP_ADAPTER_NIC_NOT_EXIST |
7890 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7893 if (pAd->StaCfg.Psm == PWR_SAVE)
7896 #endif // CONFIG_STA_SUPPORT //
7898 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7900 if(pAd->Antenna.field.RxPath == 3)
7904 else if(pAd->Antenna.field.RxPath == 2)
7908 else if(pAd->Antenna.field.RxPath == 1)
7912 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7913 #ifdef CONFIG_STA_SUPPORT
7914 #endif // CONFIG_STA_SUPPORT //
7915 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7918 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7919 pAd->RalinkCounters.OneSecTxRetryOkCount +
7920 pAd->RalinkCounters.OneSecTxFailCount;
7922 if (TxTotalCnt > 50)
7924 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7925 pAd->Mlme.bLowThroughput = FALSE;
7929 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7930 pAd->Mlme.bLowThroughput = TRUE;
7936 ========================================================================
7937 Routine Description:
7938 After evaluation, check antenna link status
7941 pAd - Adapter pointer
7946 ========================================================================
7948 VOID AsicRxAntEvalTimeout(
7949 IN PVOID SystemSpecific1,
7950 IN PVOID FunctionContext,
7951 IN PVOID SystemSpecific2,
7952 IN PVOID SystemSpecific3)
7954 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7955 #ifdef CONFIG_STA_SUPPORT
7957 CHAR larger = -127, rssi0, rssi1, rssi2;
7958 #endif // CONFIG_STA_SUPPORT //
7960 #ifdef CONFIG_STA_SUPPORT
7961 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7963 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7964 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7965 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7966 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7969 if (pAd->StaCfg.Psm == PWR_SAVE)
7973 // if the traffic is low, use average rssi as the criteria
7974 if (pAd->Mlme.bLowThroughput == TRUE)
7976 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7977 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7978 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7982 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7983 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7984 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7987 if(pAd->Antenna.field.RxPath == 3)
7989 larger = max(rssi0, rssi1);
7991 if (larger > (rssi2 + 20))
7992 pAd->Mlme.RealRxPath = 2;
7994 pAd->Mlme.RealRxPath = 3;
7996 else if(pAd->Antenna.field.RxPath == 2)
7998 if (rssi0 > (rssi1 + 20))
7999 pAd->Mlme.RealRxPath = 1;
8001 pAd->Mlme.RealRxPath = 2;
8004 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8006 if(pAd->Mlme.RealRxPath == 3)
8010 else if(pAd->Mlme.RealRxPath == 2)
8014 else if(pAd->Mlme.RealRxPath == 1)
8018 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8021 #endif // CONFIG_STA_SUPPORT //
8027 VOID APSDPeriodicExec(
8028 IN PVOID SystemSpecific1,
8029 IN PVOID FunctionContext,
8030 IN PVOID SystemSpecific2,
8031 IN PVOID SystemSpecific3)
8033 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8035 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8038 pAd->CommonCfg.TriggerTimerCount++;
8040 // Driver should not send trigger frame, it should be send by application layer
8042 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
8043 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
8044 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
8046 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
8047 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
8048 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
8049 pAd->CommonCfg.TriggerTimerCount = 0;
8050 pAd->CommonCfg.bInServicePeriod = TRUE;
8055 ========================================================================
8056 Routine Description:
8057 Set/reset MAC registers according to bPiggyBack parameter
8060 pAd - Adapter pointer
8061 bPiggyBack - Enable / Disable Piggy-Back
8066 ========================================================================
8068 VOID RTMPSetPiggyBack(
8069 IN PRTMP_ADAPTER pAd,
8070 IN BOOLEAN bPiggyBack)
8072 TX_LINK_CFG_STRUC TxLinkCfg;
8074 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8076 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8077 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8081 ========================================================================
8082 Routine Description:
8083 check if this entry need to switch rate automatically
8093 ========================================================================
8095 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8096 IN PRTMP_ADAPTER pAd,
8097 IN PMAC_TABLE_ENTRY pEntry)
8099 BOOLEAN result = TRUE;
8102 #ifdef CONFIG_STA_SUPPORT
8103 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8105 // only associated STA counts
8106 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8108 result = pAd->StaCfg.bAutoTxRateSwitch;
8113 #ifdef QOS_DLS_SUPPORT
8114 if (pEntry && (pEntry->ValidAsDls))
8115 result = pAd->StaCfg.bAutoTxRateSwitch;
8116 #endif // QOS_DLS_SUPPORT //
8118 #endif // CONFIG_STA_SUPPORT //
8126 BOOLEAN RTMPAutoRateSwitchCheck(
8127 IN PRTMP_ADAPTER pAd)
8130 #ifdef CONFIG_STA_SUPPORT
8131 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8133 if (pAd->StaCfg.bAutoTxRateSwitch)
8136 #endif // CONFIG_STA_SUPPORT //
8142 ========================================================================
8143 Routine Description:
8144 check if this entry need to fix tx legacy rate
8154 ========================================================================
8156 UCHAR RTMPStaFixedTxMode(
8157 IN PRTMP_ADAPTER pAd,
8158 IN PMAC_TABLE_ENTRY pEntry)
8160 UCHAR tx_mode = FIXED_TXMODE_HT;
8163 #ifdef CONFIG_STA_SUPPORT
8164 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8166 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8168 #endif // CONFIG_STA_SUPPORT //
8174 ========================================================================
8175 Routine Description:
8176 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8186 ========================================================================
8188 VOID RTMPUpdateLegacyTxSetting(
8189 UCHAR fixed_tx_mode,
8190 PMAC_TABLE_ENTRY pEntry)
8192 HTTRANSMIT_SETTING TransmitSetting;
8194 if (fixed_tx_mode == FIXED_TXMODE_HT)
8197 TransmitSetting.word = 0;
8199 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8200 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8202 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8204 TransmitSetting.field.MODE = MODE_CCK;
8205 // CCK mode allow MCS 0~3
8206 if (TransmitSetting.field.MCS > MCS_3)
8207 TransmitSetting.field.MCS = MCS_3;
8211 TransmitSetting.field.MODE = MODE_OFDM;
8212 // OFDM mode allow MCS 0~7
8213 if (TransmitSetting.field.MCS > MCS_7)
8214 TransmitSetting.field.MCS = MCS_7;
8217 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8219 pEntry->HTPhyMode.word = TransmitSetting.word;
8220 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8221 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8225 #ifdef CONFIG_STA_SUPPORT
8227 ==========================================================================
8229 dynamic tune BBP R66 to find a balance between sensibility and
8232 IRQL = DISPATCH_LEVEL
8234 ==========================================================================
8236 VOID AsicStaBbpTuning(
8237 IN PRTMP_ADAPTER pAd)
8239 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8242 // 2860C did not support Fase CCA, therefore can't tune
8243 if (pAd->MACVersion == 0x28600100)
8249 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8252 if ((pAd->OpMode == OPMODE_STA)
8253 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8255 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8258 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8261 if (pAd->Antenna.field.RxPath > 1)
8262 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8264 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8266 if (pAd->LatchRfRegs.Channel <= 14)
8269 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8270 // Otherwise, it will have some throughput side effect when low RSSI
8273 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8275 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8276 if (OrigR66Value != R66)
8278 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8283 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8284 if (OrigR66Value != R66)
8286 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8293 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8295 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8296 if (OrigR66Value != R66)
8298 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8303 R66 = 0x2E + GET_LNA_GAIN(pAd);
8304 if (OrigR66Value != R66)
8306 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8313 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8315 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8317 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8318 if (OrigR66Value != R66)
8320 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8325 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8326 if (OrigR66Value != R66)
8328 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8334 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8336 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8337 if (OrigR66Value != R66)
8339 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8344 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8345 if (OrigR66Value != R66)
8347 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8356 #endif // CONFIG_STA_SUPPORT //
8358 VOID RTMPSetAGCInitValue(
8359 IN PRTMP_ADAPTER pAd,
8364 if (pAd->LatchRfRegs.Channel <= 14)
8366 R66 = 0x2E + GET_LNA_GAIN(pAd);
8367 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8371 if (BandWidth == BW_20)
8373 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8374 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8376 #ifdef DOT11_N_SUPPORT
8379 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8380 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8382 #endif // DOT11_N_SUPPORT //
8387 VOID AsicTurnOffRFClk(
8388 IN PRTMP_ADAPTER pAd,
8393 UINT32 R1 = 0, R2 = 0, R3 = 0;
8395 RTMP_RF_REGS *RFRegTable;
8397 RFRegTable = RF2850RegTable;
8399 switch (pAd->RfIcType)
8406 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8408 if (Channel == RFRegTable[index].Channel)
8410 R1 = RFRegTable[index].R1 & 0xffffdfff;
8411 R2 = RFRegTable[index].R2 & 0xfffbffff;
8412 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8414 RTMP_RF_IO_WRITE32(pAd, R1);
8415 RTMP_RF_IO_WRITE32(pAd, R2);
8417 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8418 // Set RF R2 bit18=0, R3 bit[18:19]=0
8419 //if (pAd->StaCfg.bRadio == FALSE)
8422 RTMP_RF_IO_WRITE32(pAd, R3);
8424 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8425 Channel, pAd->RfIcType, R2, R3));
8428 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8429 Channel, pAd->RfIcType, R2));
8441 VOID AsicTurnOnRFClk(
8442 IN PRTMP_ADAPTER pAd,
8447 UINT32 R1 = 0, R2 = 0, R3 = 0;
8449 RTMP_RF_REGS *RFRegTable;
8451 RFRegTable = RF2850RegTable;
8453 switch (pAd->RfIcType)
8460 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8462 if (Channel == RFRegTable[index].Channel)
8464 R3 = pAd->LatchRfRegs.R3;
8467 RTMP_RF_IO_WRITE32(pAd, R3);
8469 R1 = RFRegTable[index].R1;
8470 RTMP_RF_IO_WRITE32(pAd, R1);
8472 R2 = RFRegTable[index].R2;
8473 if (pAd->Antenna.field.TxPath == 1)
8475 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8478 if (pAd->Antenna.field.RxPath == 2)
8480 R2 |= 0x40; // write 1 to off Rxpath.
8482 else if (pAd->Antenna.field.RxPath == 1)
8484 R2 |= 0x20040; // write 1 to off RxPath
8486 RTMP_RF_IO_WRITE32(pAd, R2);
8497 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",