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,
251 0x05, 0x20, 20, 15, 30,
252 0x06, 0x20, 21, 8, 20,
253 0x07, 0x20, 22, 8, 20,
254 0x08, 0x20, 23, 8, 25,
255 0x09, 0x22, 23, 8, 25,
258 UCHAR RateSwitchTable11BGN2SForABand[] = {
259 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
260 0x0b, 0x09, 0, 0, 0, // Initial used item after association
261 0x00, 0x21, 0, 30,101, //50
262 0x01, 0x21, 1, 20, 50,
263 0x02, 0x21, 2, 20, 50,
264 0x03, 0x21, 3, 15, 50,
265 0x04, 0x21, 4, 15, 30,
266 0x05, 0x21, 5, 15, 30,
267 0x06, 0x20, 12, 15, 30,
268 0x07, 0x20, 13, 8, 20,
269 0x08, 0x20, 14, 8, 20,
270 0x09, 0x20, 15, 8, 25,
271 0x0a, 0x22, 15, 8, 25,
274 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
275 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
276 0x0c, 0x09, 0, 0, 0, // Initial used item after association
277 0x00, 0x21, 0, 30,101, //50
278 0x01, 0x21, 1, 20, 50,
279 0x02, 0x21, 2, 20, 50,
280 0x03, 0x21, 3, 15, 50,
281 0x04, 0x21, 4, 15, 30,
282 0x05, 0x21, 5, 15, 30,
283 0x06, 0x21, 12, 15, 30,
284 0x07, 0x20, 20, 15, 30,
285 0x08, 0x20, 21, 8, 20,
286 0x09, 0x20, 22, 8, 20,
287 0x0a, 0x20, 23, 8, 25,
288 0x0b, 0x22, 23, 8, 25,
290 #endif // DOT11_N_SUPPORT //
292 PUCHAR ReasonString[] = {
294 /* 1 */ "Unspecified Reason",
295 /* 2 */ "Previous Auth no longer valid",
296 /* 3 */ "STA is leaving / has left",
297 /* 4 */ "DIS-ASSOC due to inactivity",
298 /* 5 */ "AP unable to hanle all associations",
299 /* 6 */ "class 2 error",
300 /* 7 */ "class 3 error",
301 /* 8 */ "STA is leaving / has left",
302 /* 9 */ "require auth before assoc/re-assoc",
306 /* 13 */ "invalid IE",
307 /* 14 */ "MIC error",
308 /* 15 */ "4-way handshake timeout",
309 /* 16 */ "2-way (group key) handshake timeout",
310 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
314 extern UCHAR OfdmRateToRxwiMCS[];
315 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
316 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
317 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
318 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
319 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
321 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
322 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
323 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
325 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
326 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
327 // clean environment.
328 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
329 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
331 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
332 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
334 UCHAR SsidIe = IE_SSID;
335 UCHAR SupRateIe = IE_SUPP_RATES;
336 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
337 #ifdef DOT11_N_SUPPORT
338 UCHAR HtCapIe = IE_HT_CAP;
339 UCHAR AddHtInfoIe = IE_ADD_HT;
340 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
342 UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
343 #endif // DOT11N_DRAFT3 //
344 #endif // DOT11_N_SUPPORT //
345 UCHAR ErpIe = IE_ERP;
346 UCHAR DsIe = IE_DS_PARM;
347 UCHAR TimIe = IE_TIM;
348 UCHAR WpaIe = IE_WPA;
349 UCHAR Wpa2Ie = IE_WPA2;
350 UCHAR IbssIe = IE_IBSS_PARM;
351 UCHAR Ccx2Ie = IE_CCX_V2;
353 extern UCHAR WPA_OUI[];
355 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
357 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
358 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
360 // Reset the RFIC setting to new series
361 RTMP_RF_REGS RF2850RegTable[] = {
362 // ch R1 R2 R3(TX0~4=0) R4
363 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
364 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
365 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
366 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
367 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
368 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
369 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
370 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
371 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
372 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
373 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
374 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
375 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
376 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
378 // 802.11 UNI / HyperLan 2
379 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
380 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
381 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
382 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
383 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
384 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
385 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
386 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
387 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
388 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
389 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
390 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
393 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
395 // 2008.04.30 modified
396 // The system team has AN to improve the EVM value
397 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
398 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
399 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
400 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
402 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
403 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
404 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
405 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
406 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
407 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
408 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
409 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
410 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
411 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
412 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
413 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
416 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
417 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
418 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
419 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
420 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
421 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
422 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
425 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
426 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
427 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
428 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
429 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
430 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
431 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
433 // still lack of MMAC(Japan) ch 34,38,42,46
435 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
437 FREQUENCY_ITEM FreqItems3020[] =
439 /**************************************************/
440 // ISM : 2.4 to 2.483 GHz //
441 /**************************************************/
443 /**************************************************/
444 //-CH---N-------R---K-----------
460 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
463 ==========================================================================
465 initialize the MLME task and its data structure (queue, spinlock,
466 timer, state machines).
471 always return NDIS_STATUS_SUCCESS
473 ==========================================================================
475 NDIS_STATUS MlmeInit(
476 IN PRTMP_ADAPTER pAd)
478 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
480 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
484 Status = MlmeQueueInit(&pAd->Mlme.Queue);
485 if(Status != NDIS_STATUS_SUCCESS)
488 pAd->Mlme.bRunning = FALSE;
489 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
491 #ifdef CONFIG_STA_SUPPORT
492 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
494 BssTableInit(&pAd->ScanTab);
496 // init STA state machines
497 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
498 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
499 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
500 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
501 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
502 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
504 // Since we are using switch/case to implement it, the init is different from the above
505 // state machine init
506 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
508 #endif // CONFIG_STA_SUPPORT //
512 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
514 // Init mlme periodic timer
515 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
517 // Set mlme periodic timer
518 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
520 // software-based RX Antenna diversity
521 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
524 #ifdef CONFIG_STA_SUPPORT
525 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
527 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
529 // only PCIe cards need these two timers
530 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
531 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
534 #endif // CONFIG_STA_SUPPORT //
538 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
544 ==========================================================================
546 main loop of the MLME
548 Mlme has to be initialized, and there are something inside the queue
550 This function is invoked from MPSetInformation and MPReceive;
551 This task guarantee only one MlmeHandler will run.
553 IRQL = DISPATCH_LEVEL
555 ==========================================================================
558 IN PRTMP_ADAPTER pAd)
560 MLME_QUEUE_ELEM *Elem = NULL;
562 // Only accept MLME and Frame from peer side, no other (control/data) frame should
563 // get into this state machine
565 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
566 if(pAd->Mlme.bRunning)
568 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
573 pAd->Mlme.bRunning = TRUE;
575 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
577 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
579 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
580 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
581 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
583 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
587 //From message type, determine which state machine I should drive
588 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
591 // if dequeue success
592 switch (Elem->Machine)
594 // STA state machines
595 #ifdef CONFIG_STA_SUPPORT
596 case ASSOC_STATE_MACHINE:
597 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
599 case AUTH_STATE_MACHINE:
600 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
602 case AUTH_RSP_STATE_MACHINE:
603 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
605 case SYNC_STATE_MACHINE:
606 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
608 case MLME_CNTL_STATE_MACHINE:
609 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
611 case WPA_PSK_STATE_MACHINE:
612 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
615 case LEAP_STATE_MACHINE:
616 LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
619 case AIRONET_STATE_MACHINE:
620 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
622 #endif // CONFIG_STA_SUPPORT //
624 case ACTION_STATE_MACHINE:
625 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
632 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
637 Elem->Occupied = FALSE;
642 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
646 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
647 pAd->Mlme.bRunning = FALSE;
648 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
652 ==========================================================================
654 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
656 Adapter - NIC Adapter pointer
658 The MLME task will no longer work properly
662 ==========================================================================
665 IN PRTMP_ADAPTER pAd)
669 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
671 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
673 // disable BEACON generation and other BEACON related hardware timers
674 AsicDisableSync(pAd);
677 #ifdef CONFIG_STA_SUPPORT
678 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
680 // Cancel pending timers
681 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
682 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
683 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
684 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
685 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
686 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
687 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
689 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
690 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
693 #endif // CONFIG_STA_SUPPORT //
695 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
696 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
700 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
703 RTMPSetLED(pAd, LED_HALT);
704 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
707 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
709 MlmeQueueDestroy(&pAd->Mlme.Queue);
710 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
712 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
715 VOID MlmeResetRalinkCounters(
716 IN PRTMP_ADAPTER pAd)
718 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
719 // clear all OneSecxxx counters.
720 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
721 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
722 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
723 pAd->RalinkCounters.OneSecRxOkCnt = 0;
724 pAd->RalinkCounters.OneSecTxFailCount = 0;
725 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
726 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
727 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
729 // TODO: for debug only. to be removed
730 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
731 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
732 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
733 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
734 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
735 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
736 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
737 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
738 pAd->RalinkCounters.OneSecTxDoneCount = 0;
739 pAd->RalinkCounters.OneSecRxCount = 0;
740 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
741 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
746 unsigned long rx_AMSDU;
747 unsigned long rx_Total;
750 ==========================================================================
752 This routine is executed periodically to -
753 1. Decide if it's a right time to turn on PwrMgmt bit of all
755 2. Calculate ChannelQuality based on statistics of the last
756 period, so that TX rate won't toggling very frequently between a
757 successful TX and a failed TX.
758 3. If the calculated ChannelQuality indicated current connection not
759 healthy, then a ROAMing attempt is tried here.
761 IRQL = DISPATCH_LEVEL
763 ==========================================================================
765 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
766 VOID MlmePeriodicExec(
767 IN PVOID SystemSpecific1,
768 IN PVOID FunctionContext,
769 IN PVOID SystemSpecific2,
770 IN PVOID SystemSpecific3)
773 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
776 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
777 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
778 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
779 if(pAd->StaCfg.WepStatus<2)
781 pAd->StaCfg.WpaSupplicantUP = 0;
785 pAd->StaCfg.WpaSupplicantUP = 1;
788 #ifdef CONFIG_STA_SUPPORT
789 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
791 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
792 // Move code to here, because following code will return when radio is off
793 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
794 (pAd->StaCfg.bHardwareRadio == TRUE) &&
795 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
796 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
797 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
801 // Read GPIO pin2 as Hardware controlled radio state
802 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
805 pAd->StaCfg.bHwRadio = TRUE;
809 pAd->StaCfg.bHwRadio = FALSE;
811 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
813 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
814 if (pAd->StaCfg.bRadio == TRUE)
817 // Update extra information
818 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
823 // Update extra information
824 pAd->ExtraInfo = HW_RADIO_OFF;
829 #endif // CONFIG_STA_SUPPORT //
831 // Do nothing if the driver is starting halt state.
832 // This might happen when timer already been fired before cancel timer with mlmehalt
833 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
834 fRTMP_ADAPTER_RADIO_OFF |
835 fRTMP_ADAPTER_RADIO_MEASUREMENT |
836 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
839 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
841 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
843 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
844 pAd->SameRxByteCount++;
847 pAd->SameRxByteCount = 0;
849 // If after BBP, still not work...need to check to reset PBF&MAC.
850 if (pAd->SameRxByteCount == 702)
852 pAd->SameRxByteCount = 0;
857 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
858 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
860 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
862 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
863 pAd->SameRxByteCount = 700;
868 // Update lastReceiveByteCount.
869 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
871 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
873 pAd->CheckDmaBusyCount = 0;
874 AsicResetFromDMABusy(pAd);
878 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
880 #ifdef CONFIG_STA_SUPPORT
881 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
883 // Do nothing if monitor mode is on
887 if (pAd->Mlme.PeriodicRound & 0x1)
889 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
890 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
891 (STA_TGN_WIFI_ON(pAd)) &&
892 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
895 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
896 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
898 else if ((STA_TGN_WIFI_ON(pAd)) &&
899 ((pAd->MACVersion & 0xffff) == 0x0101))
901 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
902 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
906 #endif // CONFIG_STA_SUPPORT //
908 pAd->bUpdateBcnCntDone = FALSE;
910 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
911 pAd->Mlme.PeriodicRound ++;
913 // execute every 500ms
914 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
916 #ifdef CONFIG_STA_SUPPORT
917 // perform dynamic tx rate switching based on past TX history
918 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
920 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
922 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
923 MlmeDynamicTxRateSwitching(pAd);
925 #endif // CONFIG_STA_SUPPORT //
928 // Normal 1 second Mlme PeriodicExec.
929 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
931 pAd->Mlme.OneSecPeriodicRound ++;
941 // Media status changed, report to NDIS
942 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
944 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
945 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
947 pAd->IndicateMediaState = NdisMediaStateConnected;
948 RTMP_IndicateMediaState(pAd);
953 pAd->IndicateMediaState = NdisMediaStateDisconnected;
954 RTMP_IndicateMediaState(pAd);
958 NdisGetSystemUpTime(&pAd->Mlme.Now32);
960 // add the most up-to-date h/w raw counters into software variable, so that
961 // the dynamic tuning mechanism below are based on most up-to-date information
962 NICUpdateRawCounters(pAd);
965 #ifdef DOT11_N_SUPPORT
966 // Need statistics after read counter. So put after NICUpdateRawCounters
967 ORIBATimerTimeout(pAd);
968 #endif // DOT11_N_SUPPORT //
971 // The time period for checking antenna is according to traffic
972 if (pAd->Mlme.bEnableAutoAntennaCheck)
974 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
975 pAd->RalinkCounters.OneSecTxRetryOkCount +
976 pAd->RalinkCounters.OneSecTxFailCount;
980 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
982 AsicEvaluateRxAnt(pAd);
987 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
989 AsicEvaluateRxAnt(pAd);
994 #ifdef CONFIG_STA_SUPPORT
995 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
996 STAMlmePeriodicExec(pAd);
997 #endif // CONFIG_STA_SUPPORT //
999 MlmeResetRalinkCounters(pAd);
1001 #ifdef CONFIG_STA_SUPPORT
1002 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1004 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1006 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1007 // and sending CTS-to-self over and over.
1008 // Software Patch Solution:
1009 // 1. Polling debug state register 0x10F4 every one second.
1010 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1011 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1015 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1016 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1018 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1020 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1022 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1026 #endif // CONFIG_STA_SUPPORT //
1028 RT28XX_MLME_HANDLER(pAd);
1032 pAd->bUpdateBcnCntDone = FALSE;
1035 #ifdef CONFIG_STA_SUPPORT
1036 VOID STAMlmePeriodicExec(
1041 #ifdef WPA_SUPPLICANT_SUPPORT
1042 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1043 #endif // WPA_SUPPLICANT_SUPPORT //
1045 // WPA MIC error should block association attempt for 60 seconds
1046 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1047 pAd->StaCfg.bBlockAssoc = FALSE;
1051 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1052 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1053 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1054 if(pAd->StaCfg.WepStatus<2)
1056 pAd->StaCfg.WpaSupplicantUP = 0;
1060 pAd->StaCfg.WpaSupplicantUP = 1;
1063 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1065 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1067 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1069 pAd->PreMediaState = pAd->IndicateMediaState;
1072 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1073 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1074 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1075 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1076 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1077 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1079 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1084 AsicStaBbpTuning(pAd);
1086 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1087 pAd->RalinkCounters.OneSecTxRetryOkCount +
1088 pAd->RalinkCounters.OneSecTxFailCount;
1090 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1092 // update channel quality for Roaming and UI LinkQuality display
1093 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1096 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1097 // Radio is currently in noisy environment
1098 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1099 AsicAdjustTxPower(pAd);
1103 // Is PSM bit consistent with user power management policy?
1104 // This is the only place that will set PSM bit ON.
1105 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1106 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1108 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1110 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1111 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1112 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1114 RTMPSetAGCInitValue(pAd, BW_20);
1115 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1119 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1121 // When APSD is enabled, the period changes as 20 sec
1122 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1123 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1127 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1128 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1130 if (pAd->CommonCfg.bWmmCapable)
1131 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1133 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1138 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1140 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1141 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1142 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1144 // Lost AP, send disconnect & link down event
1145 LinkDown(pAd, FALSE);
1147 #ifdef WPA_SUPPLICANT_SUPPORT
1148 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1149 if (pAd->StaCfg.WpaSupplicantUP)
1151 union iwreq_data wrqu;
1152 //send disassociate event to wpa_supplicant
1153 memset(&wrqu, 0, sizeof(wrqu));
1154 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1155 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1157 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1158 #endif // WPA_SUPPLICANT_SUPPORT //
1160 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1162 union iwreq_data wrqu;
1163 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1164 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1166 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1168 MlmeAutoReconnectLastSSID(pAd);
1170 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1172 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1173 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1174 MlmeAutoReconnectLastSSID(pAd);
1177 // Add auto seamless roaming
1178 if (pAd->StaCfg.bFastRoaming)
1180 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1182 DBGPRINT(RT_DEBUG_TRACE, ("Rssi=%d, dBmToRoam=%d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), (CHAR)dBmToRoam));
1184 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1186 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1190 else if (ADHOC_ON(pAd))
1192 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1193 // the "TX BEACON competition" for the entire past 1 sec.
1194 // So that even when ASIC's BEACONgen engine been blocked
1195 // by peer's BEACON due to slower system clock, this STA still can send out
1196 // minimum BEACON to tell the peer I'm alive.
1197 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1198 // EnqueueBeaconFrame(pAd); // software send BEACON
1200 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1201 // restore outgoing BEACON to support B/G-mixed mode
1202 if ((pAd->CommonCfg.Channel <= 14) &&
1203 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1204 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1205 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1207 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1208 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1209 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1210 MlmeUpdateTxRates(pAd, FALSE, 0);
1211 MakeIbssBeacon(pAd); // re-build BEACON frame
1212 AsicEnableIbssSync(pAd); // copy to on-chip memory
1213 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1216 #ifdef DOT11_N_SUPPORT
1217 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1219 if ((pAd->StaCfg.AdhocBGJoined) &&
1220 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1222 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1223 pAd->StaCfg.AdhocBGJoined = FALSE;
1226 if ((pAd->StaCfg.Adhoc20NJoined) &&
1227 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1229 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1230 pAd->StaCfg.Adhoc20NJoined = FALSE;
1233 #endif // DOT11_N_SUPPORT //
1236 if ((pAd->CommonCfg.Channel > 14)
1237 && (pAd->CommonCfg.bIEEE80211H == 1)
1238 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1240 RadarDetectPeriodic(pAd);
1243 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1244 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1246 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1247 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1249 MLME_START_REQ_STRUCT StartReq;
1251 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1252 LinkDown(pAd, FALSE);
1254 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1255 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1256 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1259 else // no INFRA nor ADHOC connection
1262 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1263 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1264 goto SKIP_AUTO_SCAN_CONN;
1266 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1268 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1269 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1270 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1272 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1274 MLME_SCAN_REQ_STRUCT ScanReq;
1276 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1278 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1279 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1280 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1281 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1282 // Reset Missed scan number
1283 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1285 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1286 MlmeAutoReconnectLastSSID(pAd);
1288 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1290 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1293 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1297 MlmeAutoReconnectLastSSID(pAd);
1303 SKIP_AUTO_SCAN_CONN:
1305 #ifdef DOT11_N_SUPPORT
1306 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1308 pAd->MacTab.fAnyBASession = TRUE;
1309 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1311 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1313 pAd->MacTab.fAnyBASession = FALSE;
1314 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1316 #endif // DOT11_N_SUPPORT //
1319 #ifdef DOT11_N_SUPPORT
1320 #ifdef DOT11N_DRAFT3
1321 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1322 TriEventCounterMaintenance(pAd);
1323 #endif // DOT11N_DRAFT3 //
1324 #endif // DOT11_N_SUPPORT //
1331 IN PVOID SystemSpecific1,
1332 IN PVOID FunctionContext,
1333 IN PVOID SystemSpecific2,
1334 IN PVOID SystemSpecific3)
1337 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1339 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1340 RTMP_IndicateMediaState(pAd);
1341 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1344 // IRQL = DISPATCH_LEVEL
1346 IN PRTMP_ADAPTER pAd)
1348 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1349 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1351 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1353 MLME_CNTL_STATE_MACHINE,
1354 OID_802_11_BSSID_LIST_SCAN,
1357 RT28XX_MLME_HANDLER(pAd);
1361 // IRQL = DISPATCH_LEVEL
1362 VOID MlmeAutoReconnectLastSSID(
1363 IN PRTMP_ADAPTER pAd)
1367 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1368 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1369 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1371 NDIS_802_11_SSID OidSsid;
1372 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1373 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1375 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1377 MLME_CNTL_STATE_MACHINE,
1379 sizeof(NDIS_802_11_SSID),
1381 RT28XX_MLME_HANDLER(pAd);
1384 #endif // CONFIG_STA_SUPPORT //
1387 ==========================================================================
1388 Validate SSID for connection try and rescan purpose
1389 Valid SSID will have visible chars only.
1390 The valid length is from 0 to 32.
1391 IRQL = DISPATCH_LEVEL
1392 ==========================================================================
1394 BOOLEAN MlmeValidateSSID(
1400 if (SsidLen > MAX_LEN_OF_SSID)
1403 // Check each character value
1404 for (index = 0; index < SsidLen; index++)
1406 if (pSsid[index] < 0x20)
1414 VOID MlmeSelectTxRateTable(
1415 IN PRTMP_ADAPTER pAd,
1416 IN PMAC_TABLE_ENTRY pEntry,
1418 IN PUCHAR pTableSize,
1419 IN PUCHAR pInitTxRateIdx)
1423 // decide the rate table for tuning
1424 if (pAd->CommonCfg.TxRateTableSize > 0)
1426 *ppTable = RateSwitchTable;
1427 *pTableSize = RateSwitchTable[0];
1428 *pInitTxRateIdx = RateSwitchTable[1];
1433 #ifdef CONFIG_STA_SUPPORT
1434 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1436 #ifdef DOT11_N_SUPPORT
1437 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1438 !pAd->StaCfg.AdhocBOnlyJoined &&
1439 !pAd->StaCfg.AdhocBGJoined &&
1440 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1441 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1443 *ppTable = RateSwitchTable11N1S;
1444 *pTableSize = RateSwitchTable11N1S[0];
1445 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1448 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1449 !pAd->StaCfg.AdhocBOnlyJoined &&
1450 !pAd->StaCfg.AdhocBGJoined &&
1451 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1452 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1453 (pAd->Antenna.field.TxPath == 2))
1455 if (pAd->LatchRfRegs.Channel <= 14)
1457 *ppTable = RateSwitchTable11N2S;
1458 *pTableSize = RateSwitchTable11N2S[0];
1459 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1463 *ppTable = RateSwitchTable11N2SForABand;
1464 *pTableSize = RateSwitchTable11N2SForABand[0];
1465 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1470 #endif // DOT11_N_SUPPORT //
1471 if (pAd->CommonCfg.PhyMode == PHY_11B)
1473 *ppTable = RateSwitchTable11B;
1474 *pTableSize = RateSwitchTable11B[0];
1475 *pInitTxRateIdx = RateSwitchTable11B[1];
1478 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1480 // USe B Table when Only b-only Station in my IBSS .
1481 *ppTable = RateSwitchTable11B;
1482 *pTableSize = RateSwitchTable11B[0];
1483 *pInitTxRateIdx = RateSwitchTable11B[1];
1486 else if (pAd->LatchRfRegs.Channel <= 14)
1488 *ppTable = RateSwitchTable11BG;
1489 *pTableSize = RateSwitchTable11BG[0];
1490 *pInitTxRateIdx = RateSwitchTable11BG[1];
1495 *ppTable = RateSwitchTable11G;
1496 *pTableSize = RateSwitchTable11G[0];
1497 *pInitTxRateIdx = RateSwitchTable11G[1];
1502 #endif // CONFIG_STA_SUPPORT //
1504 #ifdef DOT11_N_SUPPORT
1505 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1506 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1508 *ppTable = RateSwitchTable11BGN1S;
1509 *pTableSize = RateSwitchTable11BGN1S[0];
1510 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1515 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1516 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1518 if (pAd->LatchRfRegs.Channel <= 14)
1520 *ppTable = RateSwitchTable11BGN2S;
1521 *pTableSize = RateSwitchTable11BGN2S[0];
1522 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1527 *ppTable = RateSwitchTable11BGN2SForABand;
1528 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1529 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1535 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1537 *ppTable = RateSwitchTable11N1S;
1538 *pTableSize = RateSwitchTable11N1S[0];
1539 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1544 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1546 if (pAd->LatchRfRegs.Channel <= 14)
1548 *ppTable = RateSwitchTable11N2S;
1549 *pTableSize = RateSwitchTable11N2S[0];
1550 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1554 *ppTable = RateSwitchTable11N2SForABand;
1555 *pTableSize = RateSwitchTable11N2SForABand[0];
1556 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1561 #endif // DOT11_N_SUPPORT //
1562 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1563 if ((pEntry->RateLen == 4)
1564 #ifdef DOT11_N_SUPPORT
1565 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1566 #endif // DOT11_N_SUPPORT //
1569 *ppTable = RateSwitchTable11B;
1570 *pTableSize = RateSwitchTable11B[0];
1571 *pInitTxRateIdx = RateSwitchTable11B[1];
1576 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1577 if ((pEntry->RateLen > 8)
1578 #ifdef DOT11_N_SUPPORT
1579 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1580 #endif // DOT11_N_SUPPORT //
1583 *ppTable = RateSwitchTable11BG;
1584 *pTableSize = RateSwitchTable11BG[0];
1585 *pInitTxRateIdx = RateSwitchTable11BG[1];
1590 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1591 if ((pEntry->RateLen == 8)
1592 #ifdef DOT11_N_SUPPORT
1593 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1594 #endif // DOT11_N_SUPPORT //
1597 *ppTable = RateSwitchTable11G;
1598 *pTableSize = RateSwitchTable11G[0];
1599 *pInitTxRateIdx = RateSwitchTable11G[1];
1603 #ifdef DOT11_N_SUPPORT
1604 #endif // DOT11_N_SUPPORT //
1606 #ifdef CONFIG_STA_SUPPORT
1607 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1609 #ifdef DOT11_N_SUPPORT
1610 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1611 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1612 #endif // DOT11_N_SUPPORT //
1614 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1616 *ppTable = RateSwitchTable11B;
1617 *pTableSize = RateSwitchTable11B[0];
1618 *pInitTxRateIdx = RateSwitchTable11B[1];
1620 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1622 *ppTable = RateSwitchTable11G;
1623 *pTableSize = RateSwitchTable11G[0];
1624 *pInitTxRateIdx = RateSwitchTable11G[1];
1629 *ppTable = RateSwitchTable11BG;
1630 *pTableSize = RateSwitchTable11BG[0];
1631 *pInitTxRateIdx = RateSwitchTable11BG[1];
1635 #ifdef DOT11_N_SUPPORT
1636 if (pAd->LatchRfRegs.Channel <= 14)
1638 if (pAd->CommonCfg.TxStream == 1)
1640 *ppTable = RateSwitchTable11N1S;
1641 *pTableSize = RateSwitchTable11N1S[0];
1642 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1643 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1647 *ppTable = RateSwitchTable11N2S;
1648 *pTableSize = RateSwitchTable11N2S[0];
1649 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1650 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1655 if (pAd->CommonCfg.TxStream == 1)
1657 *ppTable = RateSwitchTable11N1S;
1658 *pTableSize = RateSwitchTable11N1S[0];
1659 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1660 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1664 *ppTable = RateSwitchTable11N2SForABand;
1665 *pTableSize = RateSwitchTable11N2SForABand[0];
1666 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1667 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1670 #endif // DOT11_N_SUPPORT //
1671 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1672 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1674 #endif // CONFIG_STA_SUPPORT //
1678 #ifdef CONFIG_STA_SUPPORT
1680 ==========================================================================
1682 This routine checks if there're other APs out there capable for
1683 roaming. Caller should call this routine only when Link up in INFRA mode
1684 and channel quality is below CQI_GOOD_THRESHOLD.
1686 IRQL = DISPATCH_LEVEL
1689 ==========================================================================
1691 VOID MlmeCheckForRoaming(
1692 IN PRTMP_ADAPTER pAd,
1696 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1699 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1700 // put all roaming candidates into RoamTab, and sort in RSSI order
1701 BssTableInit(pRoamTab);
1702 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1704 pBss = &pAd->ScanTab.BssEntry[i];
1706 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1707 continue; // AP disappear
1708 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1709 continue; // RSSI too weak. forget it.
1710 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1711 continue; // skip current AP
1712 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1713 continue; // only AP with stronger RSSI is eligible for roaming
1715 // AP passing all above rules is put into roaming candidate table
1716 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1717 pRoamTab->BssNr += 1;
1720 if (pRoamTab->BssNr > 0)
1722 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1723 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1725 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1726 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1727 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1728 RT28XX_MLME_HANDLER(pAd);
1731 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1735 ==========================================================================
1737 This routine checks if there're other APs out there capable for
1738 roaming. Caller should call this routine only when link up in INFRA mode
1739 and channel quality is below CQI_GOOD_THRESHOLD.
1741 IRQL = DISPATCH_LEVEL
1744 ==========================================================================
1746 VOID MlmeCheckForFastRoaming(
1747 IN PRTMP_ADAPTER pAd,
1751 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1754 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1755 // put all roaming candidates into RoamTab, and sort in RSSI order
1756 BssTableInit(pRoamTab);
1757 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1759 pBss = &pAd->ScanTab.BssEntry[i];
1761 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1762 continue; // RSSI too weak. forget it.
1763 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1764 continue; // skip current AP
1765 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1766 continue; // skip different SSID
1767 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1768 continue; // skip AP without better RSSI
1770 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));
1771 // AP passing all above rules is put into roaming candidate table
1772 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1773 pRoamTab->BssNr += 1;
1776 if (pRoamTab->BssNr > 0)
1778 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1779 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1781 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1782 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1783 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1784 RT28XX_MLME_HANDLER(pAd);
1787 // Maybe site survey required
1790 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1792 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1793 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1794 pAd->StaCfg.ScanCnt = 2;
1795 pAd->StaCfg.LastScanTime = Now;
1800 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1804 ==========================================================================
1806 This routine calculates TxPER, RxPER of the past N-sec period. And
1807 according to the calculation result, ChannelQuality is calculated here
1808 to decide if current AP is still doing the job.
1810 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1812 StaCfg.ChannelQuality - 0..100
1814 IRQL = DISPATCH_LEVEL
1816 NOTE: This routine decide channle quality based on RX CRC error ratio.
1817 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1818 is performed right before this routine, so that this routine can decide
1819 channel quality based on the most up-to-date information
1820 ==========================================================================
1822 VOID MlmeCalculateChannelQuality(
1823 IN PRTMP_ADAPTER pAd,
1826 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1830 ULONG BeaconLostTime = BEACON_LOST_TIME;
1832 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1835 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1837 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1838 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1846 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1847 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1851 // calculate RX PER - don't take RxPER into consideration if too few sample
1853 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1857 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1860 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1862 if (INFRA_ON(pAd) &&
1863 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1864 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1866 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1867 pAd->Mlme.ChannelQuality = 0;
1874 else if (MaxRssi < -90)
1877 NorRssi = (MaxRssi + 90) * 2;
1879 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1880 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1881 TX_WEIGHTING * (100 - TxPRR) +
1882 RX_WEIGHTING* (100 - RxPER)) / 100;
1883 if (pAd->Mlme.ChannelQuality >= 100)
1884 pAd->Mlme.ChannelQuality = 100;
1890 IN PRTMP_ADAPTER pAd,
1891 IN PMAC_TABLE_ENTRY pEntry,
1892 IN PRTMP_TX_RATE_SWITCH pTxRate)
1894 UCHAR MaxMode = MODE_OFDM;
1896 #ifdef DOT11_N_SUPPORT
1897 MaxMode = MODE_HTGREENFIELD;
1899 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1900 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1902 #endif // DOT11_N_SUPPORT //
1903 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1905 if (pTxRate->CurrMCS < MCS_AUTO)
1906 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1908 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1909 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1913 // If peer adhoc is b-only mode, we can't send 11g rate.
1914 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1915 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1918 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1920 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1921 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1922 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1924 // Patch speed error in status page
1925 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1929 if (pTxRate->Mode <= MaxMode)
1930 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1932 #ifdef DOT11_N_SUPPORT
1933 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1934 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1936 #endif // DOT11_N_SUPPORT //
1937 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1939 #ifdef DOT11_N_SUPPORT
1940 // Reexam each bandwidth's SGI support.
1941 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1943 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1944 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1945 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1946 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1949 // Turn RTS/CTS rate to 6Mbps.
1950 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1952 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1953 if (pAd->MacTab.fAnyBASession)
1955 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1959 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1962 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1964 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1965 if (pAd->MacTab.fAnyBASession)
1967 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1971 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1974 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1976 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1979 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1981 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1983 #endif // DOT11_N_SUPPORT //
1985 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1986 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1987 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1988 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1989 #ifdef DOT11_N_SUPPORT
1990 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1991 pAd->WIFItestbed.bGreenField)
1992 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1993 #endif // DOT11_N_SUPPORT //
1996 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
2000 ==========================================================================
2002 This routine calculates the acumulated TxPER of eaxh TxRate. And
2003 according to the calculation result, change CommonCfg.TxRate which
2004 is the stable TX Rate we expect the Radio situation could sustained.
2006 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
2010 IRQL = DISPATCH_LEVEL
2013 call this routine every second
2014 ==========================================================================
2016 VOID MlmeDynamicTxRateSwitching(
2017 IN PRTMP_ADAPTER pAd)
2019 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2020 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2021 ULONG TxErrorRatio = 0;
2022 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2023 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2025 UCHAR TableSize = 0;
2026 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2027 CHAR Rssi, RssiOffset = 0;
2028 TX_STA_CNT1_STRUC StaTx1;
2029 TX_STA_CNT0_STRUC TxStaCnt0;
2030 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2031 MAC_TABLE_ENTRY *pEntry;
2033 /*if (pAd->Antenna.field.RxPath > 1)
2034 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2036 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
2039 // walk through MAC table, see if need to change AP's TX rate toward each entry
2041 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2043 pEntry = &pAd->MacTab.Content[i];
2045 // check if this entry need to switch rate automatically
2046 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2049 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2051 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2053 // Update statistic counter
2054 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2055 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2056 pAd->bUpdateBcnCntDone = TRUE;
2057 TxRetransmit = StaTx1.field.TxRetransmit;
2058 TxSuccess = StaTx1.field.TxSuccess;
2059 TxFailCount = TxStaCnt0.field.TxFailCount;
2060 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2062 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2063 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2064 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2065 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2066 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2067 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2069 // if no traffic in the past 1-sec period, don't change TX rate,
2070 // but clear all bad history. because the bad history may affect the next
2071 // Chariot throughput test
2072 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2073 pAd->RalinkCounters.OneSecTxRetryOkCount +
2074 pAd->RalinkCounters.OneSecTxFailCount;
2077 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2081 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2083 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2084 pEntry->OneSecTxRetryOkCount +
2085 pEntry->OneSecTxFailCount;
2088 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2091 CurrRateIdx = pEntry->CurrTxRateIndex;
2093 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2095 if (CurrRateIdx >= TableSize)
2097 CurrRateIdx = TableSize - 1;
2100 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2101 // So need to sync here.
2102 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2103 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2104 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2108 // Need to sync Real Tx rate and our record.
2109 // Then return for next DRS.
2110 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2111 pEntry->CurrTxRateIndex = InitTxRateIdx;
2112 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2114 // reset all OneSecTx counters
2115 RESET_ONE_SEC_TX_CNT(pEntry);
2119 // decide the next upgrade rate and downgrade rate, if any
2120 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2122 UpRateIdx = CurrRateIdx + 1;
2123 DownRateIdx = CurrRateIdx -1;
2125 else if (CurrRateIdx == 0)
2127 UpRateIdx = CurrRateIdx + 1;
2128 DownRateIdx = CurrRateIdx;
2130 else if (CurrRateIdx == (TableSize - 1))
2132 UpRateIdx = CurrRateIdx;
2133 DownRateIdx = CurrRateIdx - 1;
2136 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2138 #ifdef DOT11_N_SUPPORT
2139 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2141 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2142 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2145 #endif // DOT11_N_SUPPORT //
2147 TrainUp = pCurrTxRate->TrainUp;
2148 TrainDown = pCurrTxRate->TrainDown;
2151 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2154 // Keep the last time TxRateChangeAction status.
2156 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2161 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2162 // (criteria copied from RT2500 for Netopia case)
2164 if (TxTotalCnt <= 15)
2168 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2169 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2170 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2171 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2173 // check the existence and index of each needed MCS
2174 while (idx < pTable[0])
2176 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2178 if (pCurrTxRate->CurrMCS == MCS_0)
2182 else if (pCurrTxRate->CurrMCS == MCS_1)
2186 else if (pCurrTxRate->CurrMCS == MCS_2)
2190 else if (pCurrTxRate->CurrMCS == MCS_3)
2194 else if (pCurrTxRate->CurrMCS == MCS_4)
2198 else if (pCurrTxRate->CurrMCS == MCS_5)
2202 else if (pCurrTxRate->CurrMCS == MCS_6)
2206 //else if (pCurrTxRate->CurrMCS == MCS_7)
2207 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2211 else if (pCurrTxRate->CurrMCS == MCS_12)
2215 else if (pCurrTxRate->CurrMCS == MCS_13)
2219 else if (pCurrTxRate->CurrMCS == MCS_14)
2223 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2224 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
2228 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2232 else if (pCurrTxRate->CurrMCS == MCS_21)
2236 else if (pCurrTxRate->CurrMCS == MCS_22)
2240 else if (pCurrTxRate->CurrMCS == MCS_23)
2247 if (pAd->LatchRfRegs.Channel <= 14)
2249 if (pAd->NicConfig2.field.ExternalLNAForG)
2260 if (pAd->NicConfig2.field.ExternalLNAForA)
2269 #ifdef DOT11_N_SUPPORT
2271 if ((pTable == RateSwitchTable11BGN3S) ||
2272 (pTable == RateSwitchTable11N3S) ||
2273 (pTable == RateSwitchTable))
2274 {// N mode with 3 stream // 3*3
2275 if (MCS23 && (Rssi >= -70))
2277 else if (MCS22 && (Rssi >= -72))
2279 else if (MCS21 && (Rssi >= -76))
2281 else if (MCS20 && (Rssi >= -78))
2283 else if (MCS4 && (Rssi >= -82))
2285 else if (MCS3 && (Rssi >= -84))
2287 else if (MCS2 && (Rssi >= -86))
2289 else if (MCS1 && (Rssi >= -88))
2294 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2295 {// N mode with 2 stream
2296 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2298 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2300 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2302 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2304 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2306 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2308 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2310 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2315 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2316 {// N mode with 1 stream
2317 if (MCS7 && (Rssi > (-72+RssiOffset)))
2319 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2321 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2323 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2325 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2327 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2329 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2335 #endif // DOT11_N_SUPPORT //
2337 if (MCS7 && (Rssi > -70))
2339 else if (MCS6 && (Rssi > -74))
2341 else if (MCS5 && (Rssi > -78))
2343 else if (MCS4 && (Rssi > -82))
2345 else if (MCS4 == 0) // for B-only mode
2347 else if (MCS3 && (Rssi > -85))
2349 else if (MCS2 && (Rssi > -87))
2351 else if (MCS1 && (Rssi > -90))
2358 pEntry->CurrTxRateIndex = TxRateIdx;
2359 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2360 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2363 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2364 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2365 pEntry->fLastSecAccordingRSSI = TRUE;
2366 // reset all OneSecTx counters
2367 RESET_ONE_SEC_TX_CNT(pEntry);
2372 if (pEntry->fLastSecAccordingRSSI == TRUE)
2374 pEntry->fLastSecAccordingRSSI = FALSE;
2375 pEntry->LastSecTxRateChangeAction = 0;
2376 // reset all OneSecTx counters
2377 RESET_ONE_SEC_TX_CNT(pEntry);
2384 BOOLEAN bTrainUpDown = FALSE;
2386 pEntry->CurrTxRateStableTime ++;
2388 // downgrade TX quality if PER >= Rate-Down threshold
2389 if (TxErrorRatio >= TrainDown)
2391 bTrainUpDown = TRUE;
2392 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2394 // upgrade TX quality if PER <= Rate-Up threshold
2395 else if (TxErrorRatio <= TrainUp)
2397 bTrainUpDown = TRUE;
2398 bUpgradeQuality = TRUE;
2399 if (pEntry->TxQuality[CurrRateIdx])
2400 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2402 if (pEntry->TxRateUpPenalty)
2403 pEntry->TxRateUpPenalty --;
2404 else if (pEntry->TxQuality[UpRateIdx])
2405 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2408 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2412 // perform DRS - consider TxRate Down first, then rate up.
2413 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2415 pEntry->CurrTxRateIndex = DownRateIdx;
2417 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2419 pEntry->CurrTxRateIndex = UpRateIdx;
2424 // if rate-up happen, clear all bad history of all TX rates
2425 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2427 pEntry->CurrTxRateStableTime = 0;
2428 pEntry->TxRateUpPenalty = 0;
2429 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2430 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2431 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2434 // For TxRate fast train up
2436 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2438 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2440 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2442 bTxRateChanged = TRUE;
2444 // if rate-down happen, only clear DownRate's bad history
2445 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2447 pEntry->CurrTxRateStableTime = 0;
2448 pEntry->TxRateUpPenalty = 0; // no penalty
2449 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2450 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2451 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2454 // For TxRate fast train down
2456 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2458 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2460 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2462 bTxRateChanged = TRUE;
2466 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2467 bTxRateChanged = FALSE;
2470 pEntry->LastTxOkCount = TxSuccess;
2472 // reset all OneSecTx counters
2473 RESET_ONE_SEC_TX_CNT(pEntry);
2475 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2476 if (bTxRateChanged && pNextTxRate)
2478 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2484 ========================================================================
2485 Routine Description:
2486 Station side, Auto TxRate faster train up timer call back function.
2489 SystemSpecific1 - Not used.
2490 FunctionContext - Pointer to our Adapter context.
2491 SystemSpecific2 - Not used.
2492 SystemSpecific3 - Not used.
2497 ========================================================================
2499 VOID StaQuickResponeForRateUpExec(
2500 IN PVOID SystemSpecific1,
2501 IN PVOID FunctionContext,
2502 IN PVOID SystemSpecific2,
2503 IN PVOID SystemSpecific3)
2505 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2506 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2508 ULONG TxErrorRatio = 0;
2509 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2510 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2512 UCHAR TableSize = 0;
2513 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2514 TX_STA_CNT1_STRUC StaTx1;
2515 TX_STA_CNT0_STRUC TxStaCnt0;
2517 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2518 MAC_TABLE_ENTRY *pEntry;
2521 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2524 // walk through MAC table, see if need to change AP's TX rate toward each entry
2526 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2528 pEntry = &pAd->MacTab.Content[i];
2530 // check if this entry need to switch rate automatically
2531 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2534 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2535 if (pAd->Antenna.field.TxPath > 1)
2536 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2538 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2540 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2542 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2544 // decide the next upgrade rate and downgrade rate, if any
2545 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2547 UpRateIdx = CurrRateIdx + 1;
2548 DownRateIdx = CurrRateIdx -1;
2550 else if (CurrRateIdx == 0)
2552 UpRateIdx = CurrRateIdx + 1;
2553 DownRateIdx = CurrRateIdx;
2555 else if (CurrRateIdx == (TableSize - 1))
2557 UpRateIdx = CurrRateIdx;
2558 DownRateIdx = CurrRateIdx - 1;
2561 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2563 #ifdef DOT11_N_SUPPORT
2564 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2566 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2567 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2570 #endif // DOT11_N_SUPPORT //
2572 TrainUp = pCurrTxRate->TrainUp;
2573 TrainDown = pCurrTxRate->TrainDown;
2576 if (pAd->MacTab.Size == 1)
2578 // Update statistic counter
2579 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2580 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2582 TxRetransmit = StaTx1.field.TxRetransmit;
2583 TxSuccess = StaTx1.field.TxSuccess;
2584 TxFailCount = TxStaCnt0.field.TxFailCount;
2585 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2587 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2588 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2589 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2590 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2591 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2592 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2595 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2599 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2600 pEntry->OneSecTxRetryOkCount +
2601 pEntry->OneSecTxFailCount;
2604 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2609 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2610 // (criteria copied from RT2500 for Netopia case)
2612 if (TxTotalCnt <= 12)
2614 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2615 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2617 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2619 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2620 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2622 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2624 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2627 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2633 ULONG OneSecTxNoRetryOKRationCount;
2635 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2640 // downgrade TX quality if PER >= Rate-Down threshold
2641 if (TxErrorRatio >= TrainDown)
2643 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2646 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2648 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2650 // perform DRS - consider TxRate Down first, then rate up.
2651 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2653 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2655 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2656 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2661 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2663 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2667 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2669 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2674 // if rate-up happen, clear all bad history of all TX rates
2675 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2677 pAd->DrsCounters.TxRateUpPenalty = 0;
2678 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2679 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2681 // if rate-down happen, only clear DownRate's bad history
2682 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2684 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2686 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2687 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2688 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2692 bTxRateChanged = FALSE;
2695 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2696 if (bTxRateChanged && pNextTxRate)
2698 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2704 ==========================================================================
2706 This routine is executed periodically inside MlmePeriodicExec() after
2707 association with an AP.
2708 It checks if StaCfg.Psm is consistent with user policy (recorded in
2709 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2710 there're some conditions to consider:
2711 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2712 the time when Mibss==TRUE
2713 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2714 if outgoing traffic available in TxRing or MgmtRing.
2716 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2718 IRQL = DISPATCH_LEVEL
2720 ==========================================================================
2722 VOID MlmeCheckPsmChange(
2723 IN PRTMP_ADAPTER pAd,
2729 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2730 // 2. user wants either MAX_PSP or FAST_PSP
2731 // 3. but current psm is not in PWR_SAVE
2732 // 4. CNTL state machine is not doing SCANning
2733 // 5. no TX SUCCESS event for the past 1-sec period
2734 #ifdef NDIS51_MINIPORT
2735 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2736 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2739 PowerMode = pAd->StaCfg.WindowsPowerMode;
2741 if (INFRA_ON(pAd) &&
2742 (PowerMode != Ndis802_11PowerModeCAM) &&
2743 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2744 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2746 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2747 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2748 MlmeSetPsmBit(pAd, PWR_SAVE);
2749 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2751 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2755 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2760 // IRQL = PASSIVE_LEVEL
2761 // IRQL = DISPATCH_LEVEL
2763 IN PRTMP_ADAPTER pAd,
2766 AUTO_RSP_CFG_STRUC csr4;
2768 pAd->StaCfg.Psm = psm;
2769 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2770 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2771 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2772 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2774 #endif // CONFIG_STA_SUPPORT //
2777 // IRQL = DISPATCH_LEVEL
2778 VOID MlmeSetTxPreamble(
2779 IN PRTMP_ADAPTER pAd,
2780 IN USHORT TxPreamble)
2782 AUTO_RSP_CFG_STRUC csr4;
2785 // Always use Long preamble before verifiation short preamble functionality works well.
2786 // Todo: remove the following line if short preamble functionality works
2788 //TxPreamble = Rt802_11PreambleLong;
2790 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2791 if (TxPreamble == Rt802_11PreambleLong)
2793 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2794 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2795 csr4.field.AutoResponderPreamble = 0;
2799 // NOTE: 1Mbps should always use long preamble
2800 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2801 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2802 csr4.field.AutoResponderPreamble = 1;
2805 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2809 ==========================================================================
2811 Update basic rate bitmap
2812 ==========================================================================
2815 VOID UpdateBasicRateBitmap(
2816 IN PRTMP_ADAPTER pAdapter)
2819 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2820 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2821 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2822 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2823 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2826 /* if A mode, always use fix BasicRateBitMap */
2827 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2828 if (pAdapter->CommonCfg.Channel > 14)
2829 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2832 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2834 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2838 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2844 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2846 if (bitmap & (1 << i))
2848 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2850 if (sup_p[j] == rate[i])
2855 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2857 if (ext_p[j] == rate[i])
2863 } /* End of UpdateBasicRateBitmap */
2865 // IRQL = PASSIVE_LEVEL
2866 // IRQL = DISPATCH_LEVEL
2867 // bLinkUp is to identify the inital link speed.
2868 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2869 VOID MlmeUpdateTxRates(
2870 IN PRTMP_ADAPTER pAd,
2875 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2876 UCHAR MinSupport = RATE_54;
2877 ULONG BasicRateBitmap = 0;
2878 UCHAR CurrBasicRate = RATE_1;
2879 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2880 PHTTRANSMIT_SETTING pHtPhy = NULL;
2881 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2882 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2883 BOOLEAN *auto_rate_cur_p;
2884 UCHAR HtMcs = MCS_AUTO;
2886 // find max desired rate
2887 UpdateBasicRateBitmap(pAd);
2890 auto_rate_cur_p = NULL;
2891 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2893 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2895 case 2: Rate = RATE_1; num++; break;
2896 case 4: Rate = RATE_2; num++; break;
2897 case 11: Rate = RATE_5_5; num++; break;
2898 case 22: Rate = RATE_11; num++; break;
2899 case 12: Rate = RATE_6; num++; break;
2900 case 18: Rate = RATE_9; num++; break;
2901 case 24: Rate = RATE_12; num++; break;
2902 case 36: Rate = RATE_18; num++; break;
2903 case 48: Rate = RATE_24; num++; break;
2904 case 72: Rate = RATE_36; num++; break;
2905 case 96: Rate = RATE_48; num++; break;
2906 case 108: Rate = RATE_54; num++; break;
2907 //default: Rate = RATE_1; break;
2909 if (MaxDesire < Rate) MaxDesire = Rate;
2912 //===========================================================================
2913 //===========================================================================
2915 #ifdef CONFIG_STA_SUPPORT
2916 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2918 pHtPhy = &pAd->StaCfg.HTPhyMode;
2919 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2920 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2922 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2923 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2925 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2926 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2927 (MaxDesire > RATE_11))
2929 MaxDesire = RATE_11;
2932 #endif // CONFIG_STA_SUPPORT //
2934 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2935 pMinHtPhy->word = 0;
2936 pMaxHtPhy->word = 0;
2939 // Auto rate switching is enabled only if more than one DESIRED RATES are
2940 // specified; otherwise disabled
2943 *auto_rate_cur_p = FALSE;
2947 *auto_rate_cur_p = TRUE;
2951 if (HtMcs != MCS_AUTO)
2953 *auto_rate_cur_p = FALSE;
2957 *auto_rate_cur_p = TRUE;
2961 #ifdef CONFIG_STA_SUPPORT
2962 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2964 pSupRate = &pAd->StaActive.SupRate[0];
2965 pExtRate = &pAd->StaActive.ExtRate[0];
2966 SupRateLen = pAd->StaActive.SupRateLen;
2967 ExtRateLen = pAd->StaActive.ExtRateLen;
2970 #endif // CONFIG_STA_SUPPORT //
2972 pSupRate = &pAd->CommonCfg.SupRate[0];
2973 pExtRate = &pAd->CommonCfg.ExtRate[0];
2974 SupRateLen = pAd->CommonCfg.SupRateLen;
2975 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2978 // find max supported rate
2979 for (i=0; i<SupRateLen; i++)
2981 switch (pSupRate[i] & 0x7f)
2983 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2984 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2985 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2986 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2987 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2988 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2989 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2990 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2991 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2992 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2993 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2994 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2995 default: Rate = RATE_1; break;
2997 if (MaxSupport < Rate) MaxSupport = Rate;
2999 if (MinSupport > Rate) MinSupport = Rate;
3002 for (i=0; i<ExtRateLen; i++)
3004 switch (pExtRate[i] & 0x7f)
3006 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3007 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3008 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3009 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3010 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3011 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3012 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3013 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3014 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3015 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3016 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3017 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3018 default: Rate = RATE_1; break;
3020 if (MaxSupport < Rate) MaxSupport = Rate;
3022 if (MinSupport > Rate) MinSupport = Rate;
3025 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3027 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3028 // the DURATION field of outgoing uniicast DATA/MGMT frame
3029 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3031 if (BasicRateBitmap & (0x01 << i))
3032 CurrBasicRate = (UCHAR)i;
3033 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3036 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3037 // max tx rate = min {max desire rate, max supported rate}
3038 if (MaxSupport < MaxDesire)
3039 pAd->CommonCfg.MaxTxRate = MaxSupport;
3041 pAd->CommonCfg.MaxTxRate = MaxDesire;
3043 pAd->CommonCfg.MinTxRate = MinSupport;
3044 if (*auto_rate_cur_p)
3047 #ifdef CONFIG_STA_SUPPORT
3048 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3049 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3050 #endif // CONFIG_STA_SUPPORT //
3051 if (bLinkUp == TRUE)
3052 pAd->CommonCfg.TxRate = RATE_24;
3054 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3057 pAd->CommonCfg.TxRate = RATE_11;
3059 pAd->CommonCfg.TxRate = RATE_24;
3061 // should never exceed MaxTxRate (consider 11B-only mode)
3062 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3063 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3065 pAd->CommonCfg.TxRateIndex = 0;
3069 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3070 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3071 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3073 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3074 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3075 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3076 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3079 if (pAd->CommonCfg.TxRate <= RATE_11)
3081 pMaxHtPhy->field.MODE = MODE_CCK;
3082 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3083 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3087 pMaxHtPhy->field.MODE = MODE_OFDM;
3088 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3089 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3090 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3092 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3095 pHtPhy->word = (pMaxHtPhy->word);
3096 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3098 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3099 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3100 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3104 switch (pAd->CommonCfg.PhyMode)
3106 case PHY_11BG_MIXED:
3108 #ifdef DOT11_N_SUPPORT
3109 case PHY_11BGN_MIXED:
3110 #endif // DOT11_N_SUPPORT //
3111 pAd->CommonCfg.MlmeRate = RATE_1;
3112 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3113 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3114 pAd->CommonCfg.RtsRate = RATE_11;
3118 #ifdef DOT11_N_SUPPORT
3119 case PHY_11AGN_MIXED:
3120 case PHY_11GN_MIXED:
3122 case PHY_11AN_MIXED:
3124 #endif // DOT11_N_SUPPORT //
3125 pAd->CommonCfg.MlmeRate = RATE_6;
3126 pAd->CommonCfg.RtsRate = RATE_6;
3127 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3128 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3130 case PHY_11ABG_MIXED:
3131 #ifdef DOT11_N_SUPPORT
3132 case PHY_11ABGN_MIXED:
3133 #endif // DOT11_N_SUPPORT //
3134 if (pAd->CommonCfg.Channel <= 14)
3136 pAd->CommonCfg.MlmeRate = RATE_1;
3137 pAd->CommonCfg.RtsRate = RATE_1;
3138 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3139 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3143 pAd->CommonCfg.MlmeRate = RATE_6;
3144 pAd->CommonCfg.RtsRate = RATE_6;
3145 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3146 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3150 pAd->CommonCfg.MlmeRate = RATE_6;
3151 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3152 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3153 pAd->CommonCfg.RtsRate = RATE_1;
3157 // Keep Basic Mlme Rate.
3159 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3160 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3161 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3163 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3164 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3167 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3168 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3169 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3170 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3171 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3172 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3173 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 ));
3176 #ifdef DOT11_N_SUPPORT
3178 ==========================================================================
3180 This function update HT Rate setting.
3181 Input Wcid value is valid for 2 case :
3182 1. it's used for Station in infra mode that copy AP rate to Mactable.
3183 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3185 IRQL = DISPATCH_LEVEL
3187 ==========================================================================
3189 VOID MlmeUpdateHtTxRates(
3190 IN PRTMP_ADAPTER pAd,
3193 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3195 RT_HT_CAPABILITY *pRtHtCap = NULL;
3196 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3199 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3200 PHTTRANSMIT_SETTING pHtPhy = NULL;
3201 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3202 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3203 BOOLEAN *auto_rate_cur_p;
3205 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3207 auto_rate_cur_p = NULL;
3209 #ifdef CONFIG_STA_SUPPORT
3210 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3212 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3213 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3214 pHtPhy = &pAd->StaCfg.HTPhyMode;
3215 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3216 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3218 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3220 #endif // CONFIG_STA_SUPPORT //
3222 #ifdef CONFIG_STA_SUPPORT
3223 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3225 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3228 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3229 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3230 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3231 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3232 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3233 pMaxHtPhy->field.STBC = STBC_USE;
3235 pMaxHtPhy->field.STBC = STBC_NONE;
3238 #endif // CONFIG_STA_SUPPORT //
3240 if (pDesireHtPhy->bHtEnable == FALSE)
3243 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3244 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3245 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3246 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3247 pMaxHtPhy->field.STBC = STBC_USE;
3249 pMaxHtPhy->field.STBC = STBC_NONE;
3252 // Decide MAX ht rate.
3253 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3254 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3256 pMaxHtPhy->field.MODE = MODE_HTMIX;
3258 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3259 pMaxHtPhy->field.BW = BW_40;
3261 pMaxHtPhy->field.BW = BW_20;
3263 if (pMaxHtPhy->field.BW == BW_20)
3264 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3266 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3268 for (i=23; i>=0; i--) // 3*3
3271 bitmask = (1<<(i-(j*8)));
3273 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3275 pMaxHtPhy->field.MCS = i;
3283 // Copy MIN ht rate. rt2860???
3284 pMinHtPhy->field.BW = BW_20;
3285 pMinHtPhy->field.MCS = 0;
3286 pMinHtPhy->field.STBC = 0;
3287 pMinHtPhy->field.ShortGI = 0;
3288 //If STA assigns fixed rate. update to fixed here.
3289 #ifdef CONFIG_STA_SUPPORT
3290 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3292 if (pDesireHtPhy->MCSSet[4] != 0)
3294 pMaxHtPhy->field.MCS = 32;
3295 pMinHtPhy->field.MCS = 32;
3296 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3299 for (i=23; (CHAR)i >= 0; i--) // 3*3
3302 bitmask = (1<<(i-(j*8)));
3303 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3305 pMaxHtPhy->field.MCS = i;
3306 pMinHtPhy->field.MCS = i;
3313 #endif // CONFIG_STA_SUPPORT //
3317 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3318 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3319 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3320 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3321 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3323 // use default now. rt2860
3324 if (pDesireHtPhy->MCSSet[0] != 0xff)
3325 *auto_rate_cur_p = FALSE;
3327 *auto_rate_cur_p = TRUE;
3329 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3330 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3331 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3332 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3334 #endif // DOT11_N_SUPPORT //
3336 // IRQL = DISPATCH_LEVEL
3338 IN PRTMP_ADAPTER pAd)
3340 RT28XX_MLME_RADIO_OFF(pAd);
3343 // IRQL = DISPATCH_LEVEL
3345 IN PRTMP_ADAPTER pAd)
3347 RT28XX_MLME_RADIO_ON(pAd);
3350 // ===========================================================================================
3352 // ===========================================================================================
3355 /*! \brief initialize BSS table
3356 * \param p_tab pointer to the table
3361 IRQL = PASSIVE_LEVEL
3362 IRQL = DISPATCH_LEVEL
3371 Tab->BssOverlapNr = 0;
3372 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3374 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3375 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3379 #ifdef DOT11_N_SUPPORT
3381 IN PRTMP_ADAPTER pAd,
3386 Tab->numAsOriginator = 0;
3387 Tab->numAsRecipient = 0;
3388 NdisAllocateSpinLock(&pAd->BATabLock);
3389 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3391 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3392 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3394 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3396 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3399 #endif // DOT11_N_SUPPORT //
3401 /*! \brief search the BSS table by SSID
3402 * \param p_tab pointer to the bss table
3403 * \param ssid SSID string
3404 * \return index of the table, BSS_NOT_FOUND if not in the table
3407 * \note search by sequential search
3409 IRQL = DISPATCH_LEVEL
3412 ULONG BssTableSearch(
3419 for (i = 0; i < Tab->BssNr; i++)
3422 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3423 // We should distinguish this case.
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, pBssid))
3432 return (ULONG)BSS_NOT_FOUND;
3435 ULONG BssSsidTableSearch(
3444 for (i = 0; i < Tab->BssNr; i++)
3447 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3448 // We should distinguish this case.
3450 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3451 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3452 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3453 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3458 return (ULONG)BSS_NOT_FOUND;
3461 ULONG BssTableSearchWithSSID(
3470 for (i = 0; i < Tab->BssNr; i++)
3472 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3473 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3474 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3475 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3476 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3477 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3482 return (ULONG)BSS_NOT_FOUND;
3485 // IRQL = DISPATCH_LEVEL
3486 VOID BssTableDeleteEntry(
3487 IN OUT BSS_TABLE *Tab,
3493 for (i = 0; i < Tab->BssNr; i++)
3495 if ((Tab->BssEntry[i].Channel == Channel) &&
3496 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3498 for (j = i; j < Tab->BssNr - 1; j++)
3500 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3502 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3509 #ifdef DOT11_N_SUPPORT
3511 ========================================================================
3512 Routine Description:
3513 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3516 // IRQL = DISPATCH_LEVEL
3517 ========================================================================
3519 VOID BATableDeleteORIEntry(
3520 IN OUT PRTMP_ADAPTER pAd,
3521 IN BA_ORI_ENTRY *pBAORIEntry)
3524 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3526 NdisAcquireSpinLock(&pAd->BATabLock);
3527 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3529 pAd->BATable.numAsOriginator -= 1;
3530 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3531 // Erase Bitmap flag.
3533 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3534 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3535 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3536 pBAORIEntry->Token = 1;
3537 // Not clear Sequence here.
3538 NdisReleaseSpinLock(&pAd->BATabLock);
3541 #endif // DOT11_N_SUPPORT //
3549 IRQL = DISPATCH_LEVEL
3553 IN PRTMP_ADAPTER pAd,
3554 OUT BSS_ENTRY *pBss,
3559 IN USHORT BeaconPeriod,
3560 IN PCF_PARM pCfParm,
3562 IN USHORT CapabilityInfo,
3564 IN UCHAR SupRateLen,
3566 IN UCHAR ExtRateLen,
3567 IN HT_CAPABILITY_IE *pHtCapability,
3568 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3569 IN UCHAR HtCapabilityLen,
3570 IN UCHAR AddHtInfoLen,
3571 IN UCHAR NewExtChanOffset,
3574 IN LARGE_INTEGER TimeStamp,
3576 IN PEDCA_PARM pEdcaParm,
3577 IN PQOS_CAPABILITY_PARM pQosCapability,
3578 IN PQBSS_LOAD_PARM pQbssLoad,
3579 IN USHORT LengthVIE,
3580 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3582 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3583 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3587 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3588 // Or send beacon /probe response with SSID len matching real SSID length,
3589 // but SSID is all zero. such as "00-00-00-00" with length 4.
3590 // We have to prevent this case overwrite correct table
3591 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3593 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3594 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3595 pBss->SsidLen = SsidLen;
3601 pBss->BssType = BssType;
3602 pBss->BeaconPeriod = BeaconPeriod;
3603 if (BssType == BSS_INFRA)
3605 if (pCfParm->bValid)
3607 pBss->CfpCount = pCfParm->CfpCount;
3608 pBss->CfpPeriod = pCfParm->CfpPeriod;
3609 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3610 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3615 pBss->AtimWin = AtimWin;
3618 pBss->CapabilityInfo = CapabilityInfo;
3619 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3620 // Combine with AuthMode, they will decide the connection methods.
3621 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3622 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3623 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3624 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3626 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3627 pBss->SupRateLen = SupRateLen;
3628 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3629 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3630 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3631 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3632 pBss->NewExtChanOffset = NewExtChanOffset;
3633 pBss->ExtRateLen = ExtRateLen;
3634 pBss->Channel = Channel;
3635 pBss->CentralChannel = Channel;
3637 // Update CkipFlag. if not exists, the value is 0x0
3638 pBss->CkipFlag = CkipFlag;
3640 // New for microsoft Fixed IEs
3641 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3642 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3643 pBss->FixIEs.Capabilities = CapabilityInfo;
3645 // New for microsoft Variable IEs
3648 pBss->VarIELen = LengthVIE;
3649 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3656 pBss->AddHtInfoLen = 0;
3657 pBss->HtCapabilityLen = 0;
3658 #ifdef DOT11_N_SUPPORT
3659 if (HtCapabilityLen> 0)
3661 pBss->HtCapabilityLen = HtCapabilityLen;
3662 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3663 if (AddHtInfoLen > 0)
3665 pBss->AddHtInfoLen = AddHtInfoLen;
3666 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3668 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3670 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3672 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3674 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3678 #endif // DOT11_N_SUPPORT //
3680 BssCipherParse(pBss);
3684 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3686 pBss->EdcaParm.bValid = FALSE;
3688 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3690 pBss->QosCapability.bValid = FALSE;
3692 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3694 pBss->QbssLoad.bValid = FALSE;
3696 #ifdef CONFIG_STA_SUPPORT
3697 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3703 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3704 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3706 pEid = (PEID_STRUCT) pVIE;
3708 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3713 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3715 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3717 pBss->WpaIE.IELen = 0;
3720 pBss->WpaIE.IELen = pEid->Len + 2;
3721 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3725 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3727 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3729 pBss->RsnIE.IELen = 0;
3732 pBss->RsnIE.IELen = pEid->Len + 2;
3733 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3737 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3738 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3741 #endif // CONFIG_STA_SUPPORT //
3745 * \brief insert an entry into the bss table
3746 * \param p_tab The BSS table
3747 * \param Bssid BSSID
3749 * \param ssid_len Length of SSID
3751 * \param beacon_period
3758 * \param channel_idx
3762 * \note If SSID is identical, the old entry will be replaced by the new one
3764 IRQL = DISPATCH_LEVEL
3767 ULONG BssTableSetEntry(
3768 IN PRTMP_ADAPTER pAd,
3774 IN USHORT BeaconPeriod,
3777 IN USHORT CapabilityInfo,
3779 IN UCHAR SupRateLen,
3781 IN UCHAR ExtRateLen,
3782 IN HT_CAPABILITY_IE *pHtCapability,
3783 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3784 IN UCHAR HtCapabilityLen,
3785 IN UCHAR AddHtInfoLen,
3786 IN UCHAR NewExtChanOffset,
3789 IN LARGE_INTEGER TimeStamp,
3791 IN PEDCA_PARM pEdcaParm,
3792 IN PQOS_CAPABILITY_PARM pQosCapability,
3793 IN PQBSS_LOAD_PARM pQbssLoad,
3794 IN USHORT LengthVIE,
3795 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3799 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3800 if (Idx == BSS_NOT_FOUND)
3802 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3805 // It may happen when BSS Table was full.
3806 // The desired AP will not be added into BSS Table
3807 // In this case, if we found the desired AP then overwrite BSS Table.
3809 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3811 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3812 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3814 Idx = Tab->BssOverlapNr;
3815 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3816 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3817 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3818 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3824 return BSS_NOT_FOUND;
3828 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3829 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3830 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3835 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3836 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3837 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3843 #ifdef CONFIG_STA_SUPPORT
3844 #ifdef DOT11_N_SUPPORT
3845 #ifdef DOT11N_DRAFT3
3847 IN PRTMP_ADAPTER pAd)
3851 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3852 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3854 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3855 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3858 ULONG TriEventTableSetEntry(
3859 IN PRTMP_ADAPTER pAd,
3860 OUT TRIGGER_EVENT_TAB *Tab,
3862 IN HT_CAPABILITY_IE *pHtCapability,
3863 IN UCHAR HtCapabilityLen,
3868 if (HtCapabilityLen == 0)
3870 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3872 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3873 Tab->EventA[Tab->EventANo].bValid = TRUE;
3874 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3875 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3878 // Beacon has Regulatory class IE. So use beacon's
3879 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3883 // Use Station's Regulatory class instead.
3884 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3886 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3888 Tab->EventA[Tab->EventANo].RegClass = 32;
3890 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3891 Tab->EventA[Tab->EventANo].RegClass = 33;
3894 Tab->EventA[Tab->EventANo].RegClass = ??;
3901 else if (pHtCapability->HtCapInfo.Intolerant40)
3903 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3909 ========================================================================
3910 Routine Description:
3911 Trigger Event table Maintainence called once every second.
3914 // IRQL = DISPATCH_LEVEL
3915 ========================================================================
3917 VOID TriEventCounterMaintenance(
3918 IN PRTMP_ADAPTER pAd)
3921 BOOLEAN bNotify = FALSE;
3922 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3924 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3926 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3927 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3929 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3930 pAd->CommonCfg.TriggerEventTab.EventANo --;
3931 // Need to send 20/40 Coexistence Notify frame if has status change.
3936 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
3938 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
3939 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
3943 if (bNotify == TRUE)
3944 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
3946 #endif // DOT11N_DRAFT3 //
3947 #endif // DOT11_N_SUPPORT //
3949 // IRQL = DISPATCH_LEVEL
3950 VOID BssTableSsidSort(
3951 IN PRTMP_ADAPTER pAd,
3952 OUT BSS_TABLE *OutTab,
3957 BssTableInit(OutTab);
3959 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3961 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3962 BOOLEAN bIsHiddenApIncluded = FALSE;
3964 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3965 (pAd->MlmeAux.Channel > 14) &&
3966 RadarChannelCheck(pAd, pInBss->Channel))
3970 bIsHiddenApIncluded = TRUE;
3973 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3974 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3976 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3977 #ifdef DOT11_N_SUPPORT
3978 // 2.4G/5G N only mode
3979 if ((pInBss->HtCapabilityLen == 0) &&
3980 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3982 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3985 #endif // DOT11_N_SUPPORT //
3988 // Check the Authmode first
3989 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3991 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3992 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3996 // Check cipher suite, AP must have more secured cipher than station setting
3997 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3999 // If it's not mixed mode, we should only let BSS pass with the same encryption
4000 if (pInBss->WPA.bMixMode == FALSE)
4001 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4004 // check group cipher
4005 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4006 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4007 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
4010 // check pairwise cipher, skip if none matched
4011 // If profile set to AES, let it pass without question.
4012 // If profile set to TKIP, we must find one mateched
4013 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4014 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4015 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4018 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4020 // If it's not mixed mode, we should only let BSS pass with the same encryption
4021 if (pInBss->WPA2.bMixMode == FALSE)
4022 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4025 // check group cipher
4026 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4027 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4028 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
4031 // check pairwise cipher, skip if none matched
4032 // If profile set to AES, let it pass without question.
4033 // If profile set to TKIP, we must find one mateched
4034 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4035 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4036 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4040 // Bss Type matched, SSID matched.
4041 // We will check wepstatus for qualification Bss
4042 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4044 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4046 // For the SESv2 case, we will not qualify WepStatus.
4052 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4053 // It definitely will fail. So, skip it.
4054 // CCX also require not even try to connect it!!
4058 #ifdef DOT11_N_SUPPORT
4059 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4060 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4061 if ((pInBss->CentralChannel != pInBss->Channel) &&
4062 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4064 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4066 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4068 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4072 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4078 #endif // DOT11_N_SUPPORT //
4080 // copy matching BSS from InTab to OutTab
4081 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4085 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4087 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4090 #ifdef DOT11_N_SUPPORT
4091 // 2.4G/5G N only mode
4092 if ((pInBss->HtCapabilityLen == 0) &&
4093 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4095 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4098 #endif // DOT11_N_SUPPORT //
4101 // Check the Authmode first
4102 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4104 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4105 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4109 // Check cipher suite, AP must have more secured cipher than station setting
4110 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4112 // If it's not mixed mode, we should only let BSS pass with the same encryption
4113 if (pInBss->WPA.bMixMode == FALSE)
4114 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4117 // check group cipher
4118 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4121 // check pairwise cipher, skip if none matched
4122 // If profile set to AES, let it pass without question.
4123 // If profile set to TKIP, we must find one mateched
4124 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4125 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4126 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4129 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4131 // If it's not mixed mode, we should only let BSS pass with the same encryption
4132 if (pInBss->WPA2.bMixMode == FALSE)
4133 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4136 // check group cipher
4137 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4140 // check pairwise cipher, skip if none matched
4141 // If profile set to AES, let it pass without question.
4142 // If profile set to TKIP, we must find one mateched
4143 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4144 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4145 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4149 // Bss Type matched, SSID matched.
4150 // We will check wepstatus for qualification Bss
4151 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4154 #ifdef DOT11_N_SUPPORT
4155 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4156 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4157 if ((pInBss->CentralChannel != pInBss->Channel) &&
4158 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4160 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4162 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4164 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4167 #endif // DOT11_N_SUPPORT //
4169 // copy matching BSS from InTab to OutTab
4170 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4175 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4179 BssTableSortByRssi(OutTab);
4183 // IRQL = DISPATCH_LEVEL
4184 VOID BssTableSortByRssi(
4185 IN OUT BSS_TABLE *OutTab)
4190 for (i = 0; i < OutTab->BssNr - 1; i++)
4192 for (j = i+1; j < OutTab->BssNr; j++)
4194 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4196 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4197 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4198 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4203 #endif // CONFIG_STA_SUPPORT //
4206 VOID BssCipherParse(
4207 IN OUT PBSS_ENTRY pBss)
4211 PRSN_IE_HEADER_STRUCT pRsnHeader;
4212 PCIPHER_SUITE_STRUCT pCipher;
4213 PAKM_SUITE_STRUCT pAKM;
4216 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4219 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4223 pBss->WepStatus = Ndis802_11WEPEnabled;
4227 pBss->WepStatus = Ndis802_11WEPDisabled;
4229 // Set default to disable & open authentication before parsing variable IE
4230 pBss->AuthMode = Ndis802_11AuthModeOpen;
4231 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4234 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4235 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4236 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4237 pBss->WPA.RsnCapability = 0;
4238 pBss->WPA.bMixMode = FALSE;
4240 // Init WPA2 setting
4241 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4242 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4243 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4244 pBss->WPA2.RsnCapability = 0;
4245 pBss->WPA2.bMixMode = FALSE;
4248 Length = (INT) pBss->VarIELen;
4252 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4253 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4254 pEid = (PEID_STRUCT) pTmp;
4258 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4259 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4265 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4266 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4267 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4268 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4271 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4272 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4273 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4276 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4277 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4278 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4284 // if Cisco IE_WPA, break
4287 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4292 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4294 // if unsupported vendor specific IE
4297 // Skip OUI, version, and multicast suite
4298 // This part should be improved in the future when AP supported multiple cipher suite.
4299 // For now, it's OK since almost all APs have fixed cipher suite supported.
4300 // pTmp = (PUCHAR) pEid->Octet;
4303 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4311 // Parse group cipher
4315 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4318 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4321 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4324 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4329 // number of unicast suite
4332 // skip all unicast cipher suites
4333 //Count = *(PUSHORT) pTmp;
4334 Count = (pTmp[1]<<8) + pTmp[0];
4335 pTmp += sizeof(USHORT);
4337 // Parsing all unicast cipher suite
4342 TmpCipher = Ndis802_11WEPDisabled;
4346 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4347 TmpCipher = Ndis802_11Encryption1Enabled;
4350 TmpCipher = Ndis802_11Encryption2Enabled;
4353 TmpCipher = Ndis802_11Encryption3Enabled;
4358 if (TmpCipher > pBss->WPA.PairCipher)
4360 // Move the lower cipher suite to PairCipherAux
4361 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4362 pBss->WPA.PairCipher = TmpCipher;
4366 pBss->WPA.PairCipherAux = TmpCipher;
4372 // 4. get AKM suite counts
4373 //Count = *(PUSHORT) pTmp;
4374 Count = (pTmp[1]<<8) + pTmp[0];
4375 pTmp += sizeof(USHORT);
4381 // Set AP support WPA mode
4382 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4383 pBss->AuthMode = Ndis802_11AuthModeWPA;
4385 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4388 // Set AP support WPA mode
4389 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4390 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4392 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4399 // Fixed for WPA-None
4400 if (pBss->BssType == BSS_ADHOC)
4402 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4403 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4404 pBss->WepStatus = pBss->WPA.GroupCipher;
4405 // Patched bugs for old driver
4406 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4407 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4410 pBss->WepStatus = pBss->WPA.PairCipher;
4412 // Check the Pair & Group, if different, turn on mixed mode flag
4413 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4414 pBss->WPA.bMixMode = TRUE;
4419 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4421 // 0. Version must be 1
4422 if (le2cpu16(pRsnHeader->Version) != 1)
4424 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4426 // 1. Check group cipher
4427 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4428 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4431 // Parse group cipher
4432 switch (pCipher->Type)
4435 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4438 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4441 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4444 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4449 // set to correct offset for next parsing
4450 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4452 // 2. Get pairwise cipher counts
4453 //Count = *(PUSHORT) pTmp;
4454 Count = (pTmp[1]<<8) + pTmp[0];
4455 pTmp += sizeof(USHORT);
4457 // 3. Get pairwise cipher
4458 // Parsing all unicast cipher suite
4462 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4463 TmpCipher = Ndis802_11WEPDisabled;
4464 switch (pCipher->Type)
4467 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4468 TmpCipher = Ndis802_11Encryption1Enabled;
4471 TmpCipher = Ndis802_11Encryption2Enabled;
4474 TmpCipher = Ndis802_11Encryption3Enabled;
4479 if (TmpCipher > pBss->WPA2.PairCipher)
4481 // Move the lower cipher suite to PairCipherAux
4482 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4483 pBss->WPA2.PairCipher = TmpCipher;
4487 pBss->WPA2.PairCipherAux = TmpCipher;
4489 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4493 // 4. get AKM suite counts
4494 //Count = *(PUSHORT) pTmp;
4495 Count = (pTmp[1]<<8) + pTmp[0];
4496 pTmp += sizeof(USHORT);
4498 // 5. Get AKM ciphers
4499 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4500 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4506 // Set AP support WPA mode
4507 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4508 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4510 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4513 // Set AP support WPA mode
4514 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4515 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4517 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4522 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4524 // Fixed for WPA-None
4525 if (pBss->BssType == BSS_ADHOC)
4527 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4528 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4529 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4530 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4531 pBss->WepStatus = pBss->WPA.GroupCipher;
4532 // Patched bugs for old driver
4533 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4534 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4536 pBss->WepStatus = pBss->WPA2.PairCipher;
4538 // 6. Get RSN capability
4539 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4540 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4541 pTmp += sizeof(USHORT);
4543 // Check the Pair & Group, if different, turn on mixed mode flag
4544 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4545 pBss->WPA2.bMixMode = TRUE;
4551 Length -= (pEid->Len + 2);
4555 // ===========================================================================================
4557 // ===========================================================================================
4559 /*! \brief generates a random mac address value for IBSS BSSID
4560 * \param Addr the bssid location
4565 VOID MacAddrRandomBssid(
4566 IN PRTMP_ADAPTER pAd,
4571 for (i = 0; i < MAC_ADDR_LEN; i++)
4573 pAddr[i] = RandomByte(pAd);
4576 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4579 /*! \brief init the management mac frame header
4580 * \param p_hdr mac header
4581 * \param subtype subtype of the frame
4582 * \param p_ds destination address, don't care if it is a broadcast address
4584 * \pre the station has the following information in the pAd->StaCfg
4588 * \note this function initializes the following field
4590 IRQL = PASSIVE_LEVEL
4591 IRQL = DISPATCH_LEVEL
4594 VOID MgtMacHeaderInit(
4595 IN PRTMP_ADAPTER pAd,
4596 IN OUT PHEADER_802_11 pHdr80211,
4602 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4604 pHdr80211->FC.Type = BTYPE_MGMT;
4605 pHdr80211->FC.SubType = SubType;
4606 pHdr80211->FC.ToDs = ToDs;
4607 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4608 #ifdef CONFIG_STA_SUPPORT
4609 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4610 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4611 #endif // CONFIG_STA_SUPPORT //
4612 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4615 // ===========================================================================================
4617 // ===========================================================================================
4619 /*!***************************************************************************
4620 * This routine build an outgoing frame, and fill all information specified
4621 * in argument list to the frame body. The actual frame size is the summation
4624 * Buffer - pointer to a pre-allocated memory segment
4625 * args - a list of <int arg_size, arg> pairs.
4626 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4627 * function will FAIL!!!
4629 * Size of the buffer
4631 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4633 IRQL = PASSIVE_LEVEL
4634 IRQL = DISPATCH_LEVEL
4636 ****************************************************************************/
4637 ULONG MakeOutgoingFrame(
4639 OUT ULONG *FrameLen, ...)
4646 // calculates the total length
4648 va_start(Args, FrameLen);
4651 leng = va_arg(Args, int);
4652 if (leng == END_OF_ARGS)
4656 p = va_arg(Args, PVOID);
4657 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4658 TotLeng = TotLeng + leng;
4661 va_end(Args); /* clean up */
4662 *FrameLen = TotLeng;
4666 // ===========================================================================================
4668 // ===========================================================================================
4670 /*! \brief Initialize The MLME Queue, used by MLME Functions
4671 * \param *Queue The MLME Queue
4672 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4675 * \note Because this is done only once (at the init stage), no need to be locked
4677 IRQL = PASSIVE_LEVEL
4680 NDIS_STATUS MlmeQueueInit(
4681 IN MLME_QUEUE *Queue)
4685 NdisAllocateSpinLock(&Queue->Lock);
4691 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4693 Queue->Entry[i].Occupied = FALSE;
4694 Queue->Entry[i].MsgLen = 0;
4695 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4698 return NDIS_STATUS_SUCCESS;
4701 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4702 * \param *Queue The MLME Queue
4703 * \param Machine The State Machine Id
4704 * \param MsgType The Message Type
4705 * \param MsgLen The Message length
4706 * \param *Msg The message pointer
4707 * \return TRUE if enqueue is successful, FALSE if the queue is full
4710 * \note The message has to be initialized
4712 IRQL = PASSIVE_LEVEL
4713 IRQL = DISPATCH_LEVEL
4716 BOOLEAN MlmeEnqueue(
4717 IN PRTMP_ADAPTER pAd,
4724 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4726 // Do nothing if the driver is starting halt state.
4727 // This might happen when timer already been fired before cancel timer with mlmehalt
4728 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4731 // First check the size, it MUST not exceed the mlme queue size
4732 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4734 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4738 if (MlmeQueueFull(Queue))
4743 NdisAcquireSpinLock(&(Queue->Lock));
4747 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4752 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4753 Queue->Entry[Tail].Occupied = TRUE;
4754 Queue->Entry[Tail].Machine = Machine;
4755 Queue->Entry[Tail].MsgType = MsgType;
4756 Queue->Entry[Tail].MsgLen = MsgLen;
4760 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4763 NdisReleaseSpinLock(&(Queue->Lock));
4767 /*! \brief This function is used when Recv gets a MLME message
4768 * \param *Queue The MLME Queue
4769 * \param TimeStampHigh The upper 32 bit of timestamp
4770 * \param TimeStampLow The lower 32 bit of timestamp
4771 * \param Rssi The receiving RSSI strength
4772 * \param MsgLen The length of the message
4773 * \param *Msg The message pointer
4774 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4778 IRQL = DISPATCH_LEVEL
4781 BOOLEAN MlmeEnqueueForRecv(
4782 IN PRTMP_ADAPTER pAd,
4784 IN ULONG TimeStampHigh,
4785 IN ULONG TimeStampLow,
4794 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4796 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4798 // Do nothing if the driver is starting halt state.
4799 // This might happen when timer already been fired before cancel timer with mlmehalt
4800 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4802 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4806 // First check the size, it MUST not exceed the mlme queue size
4807 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4809 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4813 if (MlmeQueueFull(Queue))
4818 #ifdef CONFIG_STA_SUPPORT
4819 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4821 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4823 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4827 #endif // CONFIG_STA_SUPPORT //
4829 // OK, we got all the informations, it is time to put things into queue
4830 NdisAcquireSpinLock(&(Queue->Lock));
4834 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4838 Queue->Entry[Tail].Occupied = TRUE;
4839 Queue->Entry[Tail].Machine = Machine;
4840 Queue->Entry[Tail].MsgType = MsgType;
4841 Queue->Entry[Tail].MsgLen = MsgLen;
4842 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4843 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4844 Queue->Entry[Tail].Rssi0 = Rssi0;
4845 Queue->Entry[Tail].Rssi1 = Rssi1;
4846 Queue->Entry[Tail].Rssi2 = Rssi2;
4847 Queue->Entry[Tail].Signal = Signal;
4848 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4850 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4854 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4857 NdisReleaseSpinLock(&(Queue->Lock));
4859 RT28XX_MLME_HANDLER(pAd);
4865 /*! \brief Dequeue a message from the MLME Queue
4866 * \param *Queue The MLME Queue
4867 * \param *Elem The message dequeued from MLME Queue
4868 * \return TRUE if the Elem contains something, FALSE otherwise
4872 IRQL = DISPATCH_LEVEL
4875 BOOLEAN MlmeDequeue(
4876 IN MLME_QUEUE *Queue,
4877 OUT MLME_QUEUE_ELEM **Elem)
4879 NdisAcquireSpinLock(&(Queue->Lock));
4880 *Elem = &(Queue->Entry[Queue->Head]);
4883 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4887 NdisReleaseSpinLock(&(Queue->Lock));
4891 // IRQL = DISPATCH_LEVEL
4892 VOID MlmeRestartStateMachine(
4893 IN PRTMP_ADAPTER pAd)
4895 MLME_QUEUE_ELEM *Elem = NULL;
4896 #ifdef CONFIG_STA_SUPPORT
4898 #endif // CONFIG_STA_SUPPORT //
4900 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4902 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4903 if(pAd->Mlme.bRunning)
4905 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4910 pAd->Mlme.bRunning = TRUE;
4912 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4914 // Remove all Mlme queues elements
4915 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4917 //From message type, determine which state machine I should drive
4918 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4920 // free MLME element
4921 Elem->Occupied = FALSE;
4926 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4930 #ifdef CONFIG_STA_SUPPORT
4931 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4933 // Cancel all timer events
4934 // Be careful to cancel new added timer
4935 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4936 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4937 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4938 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4939 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4940 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4942 #endif // CONFIG_STA_SUPPORT //
4944 // Change back to original channel in case of doing scan
4945 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4946 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4948 // Resume MSDU which is turned off durning scan
4949 RTMPResumeMsduTransmission(pAd);
4951 #ifdef CONFIG_STA_SUPPORT
4952 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4954 // Set all state machines back IDLE
4955 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4956 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4957 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4958 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4959 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4960 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4962 #endif // CONFIG_STA_SUPPORT //
4964 // Remove running state
4965 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4966 pAd->Mlme.bRunning = FALSE;
4967 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4970 /*! \brief test if the MLME Queue is empty
4971 * \param *Queue The MLME Queue
4972 * \return TRUE if the Queue is empty, FALSE otherwise
4976 IRQL = DISPATCH_LEVEL
4979 BOOLEAN MlmeQueueEmpty(
4980 IN MLME_QUEUE *Queue)
4984 NdisAcquireSpinLock(&(Queue->Lock));
4985 Ans = (Queue->Num == 0);
4986 NdisReleaseSpinLock(&(Queue->Lock));
4991 /*! \brief test if the MLME Queue is full
4992 * \param *Queue The MLME Queue
4993 * \return TRUE if the Queue is empty, FALSE otherwise
4997 IRQL = PASSIVE_LEVEL
4998 IRQL = DISPATCH_LEVEL
5001 BOOLEAN MlmeQueueFull(
5002 IN MLME_QUEUE *Queue)
5006 NdisAcquireSpinLock(&(Queue->Lock));
5007 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5008 NdisReleaseSpinLock(&(Queue->Lock));
5013 /*! \brief The destructor of MLME Queue
5018 * \note Clear Mlme Queue, Set Queue->Num to Zero.
5020 IRQL = PASSIVE_LEVEL
5023 VOID MlmeQueueDestroy(
5024 IN MLME_QUEUE *pQueue)
5026 NdisAcquireSpinLock(&(pQueue->Lock));
5030 NdisReleaseSpinLock(&(pQueue->Lock));
5031 NdisFreeSpinLock(&(pQueue->Lock));
5034 /*! \brief To substitute the message type if the message is coming from external
5035 * \param pFrame The frame received
5036 * \param *Machine The state machine
5037 * \param *MsgType the message type for the state machine
5038 * \return TRUE if the substitution is successful, FALSE otherwise
5042 IRQL = DISPATCH_LEVEL
5045 #ifdef CONFIG_STA_SUPPORT
5046 BOOLEAN MsgTypeSubst(
5047 IN PRTMP_ADAPTER pAd,
5048 IN PFRAME_802_11 pFrame,
5056 // Pointer to start of data frames including SNAP header
5057 pData = (PUCHAR) pFrame + LENGTH_802_11;
5059 // The only data type will pass to this function is EAPOL frame
5060 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5062 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5064 // Cisco Aironet SNAP header
5065 *Machine = AIRONET_STATE_MACHINE;
5066 *MsgType = MT2_AIRONET_MSG;
5070 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5073 *Machine = LEAP_STATE_MACHINE;
5074 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5075 return (LeapMsgTypeSubst(EAPType, MsgType));
5078 #endif // LEAP_SUPPORT //
5080 *Machine = WPA_PSK_STATE_MACHINE;
5081 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5082 return(WpaMsgTypeSubst(EAPType, MsgType));
5086 switch (pFrame->Hdr.FC.SubType)
5088 case SUBTYPE_ASSOC_REQ:
5089 *Machine = ASSOC_STATE_MACHINE;
5090 *MsgType = MT2_PEER_ASSOC_REQ;
5092 case SUBTYPE_ASSOC_RSP:
5093 *Machine = ASSOC_STATE_MACHINE;
5094 *MsgType = MT2_PEER_ASSOC_RSP;
5096 case SUBTYPE_REASSOC_REQ:
5097 *Machine = ASSOC_STATE_MACHINE;
5098 *MsgType = MT2_PEER_REASSOC_REQ;
5100 case SUBTYPE_REASSOC_RSP:
5101 *Machine = ASSOC_STATE_MACHINE;
5102 *MsgType = MT2_PEER_REASSOC_RSP;
5104 case SUBTYPE_PROBE_REQ:
5105 *Machine = SYNC_STATE_MACHINE;
5106 *MsgType = MT2_PEER_PROBE_REQ;
5108 case SUBTYPE_PROBE_RSP:
5109 *Machine = SYNC_STATE_MACHINE;
5110 *MsgType = MT2_PEER_PROBE_RSP;
5112 case SUBTYPE_BEACON:
5113 *Machine = SYNC_STATE_MACHINE;
5114 *MsgType = MT2_PEER_BEACON;
5117 *Machine = SYNC_STATE_MACHINE;
5118 *MsgType = MT2_PEER_ATIM;
5120 case SUBTYPE_DISASSOC:
5121 *Machine = ASSOC_STATE_MACHINE;
5122 *MsgType = MT2_PEER_DISASSOC_REQ;
5125 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5126 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5127 if (Seq == 1 || Seq == 3)
5129 *Machine = AUTH_RSP_STATE_MACHINE;
5130 *MsgType = MT2_PEER_AUTH_ODD;
5132 else if (Seq == 2 || Seq == 4)
5134 *Machine = AUTH_STATE_MACHINE;
5135 *MsgType = MT2_PEER_AUTH_EVEN;
5142 case SUBTYPE_DEAUTH:
5143 *Machine = AUTH_RSP_STATE_MACHINE;
5144 *MsgType = MT2_PEER_DEAUTH;
5146 case SUBTYPE_ACTION:
5147 *Machine = ACTION_STATE_MACHINE;
5148 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5149 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5151 *MsgType = MT2_ACT_INVALID;
5155 *MsgType = (pFrame->Octet[0]&0x7F);
5165 #endif // CONFIG_STA_SUPPORT //
5167 // ===========================================================================================
5169 // ===========================================================================================
5171 /*! \brief Initialize the state machine.
5172 * \param *S pointer to the state machine
5173 * \param Trans State machine transition function
5174 * \param StNr number of states
5175 * \param MsgNr number of messages
5176 * \param DefFunc default function, when there is invalid state/message combination
5177 * \param InitState initial state of the state machine
5178 * \param Base StateMachine base, internal use only
5179 * \pre p_sm should be a legal pointer
5182 IRQL = PASSIVE_LEVEL
5185 VOID StateMachineInit(
5186 IN STATE_MACHINE *S,
5187 IN STATE_MACHINE_FUNC Trans[],
5190 IN STATE_MACHINE_FUNC DefFunc,
5196 // set number of states and messages
5201 S->TransFunc = Trans;
5203 // init all state transition to default function
5204 for (i = 0; i < StNr; i++)
5206 for (j = 0; j < MsgNr; j++)
5208 S->TransFunc[i * MsgNr + j] = DefFunc;
5212 // set the starting state
5213 S->CurrState = InitState;
5216 /*! \brief This function fills in the function pointer into the cell in the state machine
5217 * \param *S pointer to the state machine
5219 * \param Msg incoming message
5220 * \param f the function to be executed when (state, message) combination occurs at the state machine
5221 * \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
5224 IRQL = PASSIVE_LEVEL
5227 VOID StateMachineSetAction(
5228 IN STATE_MACHINE *S,
5231 IN STATE_MACHINE_FUNC Func)
5235 MsgIdx = Msg - S->Base;
5237 if (St < S->NrState && MsgIdx < S->NrMsg)
5239 // boundary checking before setting the action
5240 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5244 /*! \brief This function does the state transition
5245 * \param *Adapter the NIC adapter pointer
5246 * \param *S the state machine
5247 * \param *Elem the message to be executed
5250 IRQL = DISPATCH_LEVEL
5253 VOID StateMachinePerformAction(
5254 IN PRTMP_ADAPTER pAd,
5255 IN STATE_MACHINE *S,
5256 IN MLME_QUEUE_ELEM *Elem)
5258 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5262 ==========================================================================
5264 The drop function, when machine executes this, the message is simply
5265 ignored. This function does nothing, the message is freed in
5266 StateMachinePerformAction()
5267 ==========================================================================
5270 IN PRTMP_ADAPTER pAd,
5271 IN MLME_QUEUE_ELEM *Elem)
5275 // ===========================================================================================
5277 // ===========================================================================================
5280 ==========================================================================
5283 IRQL = PASSIVE_LEVEL
5285 ==========================================================================
5288 IN PRTMP_ADAPTER pAd,
5292 pAd->Mlme.ShiftReg = 1;
5294 pAd->Mlme.ShiftReg = Seed;
5298 ==========================================================================
5300 ==========================================================================
5303 IN PRTMP_ADAPTER pAd)
5310 if (pAd->Mlme.ShiftReg == 0)
5311 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5313 for (i = 0; i < 8; i++)
5315 if (pAd->Mlme.ShiftReg & 0x00000001)
5317 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5322 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5325 R = (R << 1) | Result;
5331 VOID AsicUpdateAutoFallBackTable(
5332 IN PRTMP_ADAPTER pAd,
5333 IN PUCHAR pRateTable)
5336 HT_FBK_CFG0_STRUC HtCfg0;
5337 HT_FBK_CFG1_STRUC HtCfg1;
5338 LG_FBK_CFG0_STRUC LgCfg0;
5339 LG_FBK_CFG1_STRUC LgCfg1;
5340 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5342 // set to initial value
5343 HtCfg0.word = 0x65432100;
5344 HtCfg1.word = 0xedcba988;
5345 LgCfg0.word = 0xedcba988;
5346 LgCfg1.word = 0x00002100;
5348 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5349 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5351 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5352 switch (pCurrTxRate->Mode)
5358 switch(pCurrTxRate->CurrMCS)
5361 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5364 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5367 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5370 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5373 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5376 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5379 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5382 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5387 #ifdef DOT11_N_SUPPORT
5391 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5393 switch(pCurrTxRate->CurrMCS)
5396 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5399 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5402 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5405 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5408 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5411 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5414 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5417 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5420 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5423 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5426 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5429 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5432 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5435 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5438 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5441 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5444 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5449 #endif // DOT11_N_SUPPORT //
5452 pNextTxRate = pCurrTxRate;
5455 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5456 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5457 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5458 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5462 ========================================================================
5464 Routine Description:
5465 Set MAC register value according operation mode.
5466 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5467 If MM or GF mask is not set, those passing argument doesn't not take effect.
5469 Operation mode meaning:
5470 = 0 : Pure HT, no preotection.
5471 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5472 = 0x10: No Transmission in 40M is protected.
5473 = 0x11: Transmission in both 40M and 20M shall be protected
5475 we should choose not to use GF. But still set correct ASIC registers.
5476 ========================================================================
5478 VOID AsicUpdateProtect(
5479 IN PRTMP_ADAPTER pAd,
5480 IN USHORT OperationMode,
5482 IN BOOLEAN bDisableBGProtect,
5483 IN BOOLEAN bNonGFExist)
5485 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5491 #ifdef DOT11_N_SUPPORT
5492 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5497 if (pAd->BATable.numAsOriginator)
5500 // enable the RTS/CTS to avoid channel collision
5502 SetMask = ALLN_SETPROTECT;
5505 #endif // DOT11_N_SUPPORT //
5507 // Config ASIC RTS threshold register
5508 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5509 MacReg &= 0xFF0000FF;
5511 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5513 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5515 #ifdef DOT11_N_SUPPORT
5516 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5517 #endif // DOT11_N_SUPPORT //
5518 (pAd->CommonCfg.bAggregationCapable == TRUE))
5519 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5521 MacReg |= (0x1000 << 8);
5525 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5529 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5531 // Initial common protection settings
5532 RTMPZeroMemory(Protect, sizeof(Protect));
5535 ProtCfg.field.TxopAllowGF40 = 1;
5536 ProtCfg.field.TxopAllowGF20 = 1;
5537 ProtCfg.field.TxopAllowMM40 = 1;
5538 ProtCfg.field.TxopAllowMM20 = 1;
5539 ProtCfg.field.TxopAllowOfdm = 1;
5540 ProtCfg.field.TxopAllowCck = 1;
5541 ProtCfg.field.RTSThEn = 1;
5542 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5544 // update PHY mode and rate
5545 if (pAd->CommonCfg.Channel > 14)
5546 ProtCfg.field.ProtectRate = 0x4000;
5547 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5549 // Handle legacy(B/G) protection
5550 if (bDisableBGProtect)
5552 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5553 ProtCfg.field.ProtectCtrl = 0;
5554 Protect[0] = ProtCfg.word;
5555 Protect[1] = ProtCfg.word;
5559 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5560 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5561 Protect[0] = ProtCfg.word;
5562 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5563 Protect[1] = ProtCfg.word;
5566 #ifdef DOT11_N_SUPPORT
5567 // Decide HT frame protection.
5568 if ((SetMask & ALLN_SETPROTECT) != 0)
5570 switch(OperationMode)
5574 // 1.All STAs in the BSS are 20/40 MHz HT
5575 // 2. in ai 20/40MHz BSS
5576 // 3. all STAs are 20MHz in a 20MHz BSS
5577 // Pure HT. no protection.
5581 // PROT_TXOP(25:20) -- 010111
5582 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5583 // PROT_CTRL(17:16) -- 00 (None)
5584 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5585 Protect[2] = 0x01744004;
5589 // PROT_TXOP(25:20) -- 111111
5590 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5591 // PROT_CTRL(17:16) -- 00 (None)
5592 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5593 Protect[3] = 0x03f44084;
5597 // PROT_TXOP(25:20) -- 010111
5598 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5599 // PROT_CTRL(17:16) -- 00 (None)
5600 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5601 Protect[4] = 0x01744004;
5605 // PROT_TXOP(25:20) -- 111111
5606 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5607 // PROT_CTRL(17:16) -- 00 (None)
5608 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5609 Protect[5] = 0x03f44084;
5613 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5614 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5615 Protect[4] = 0x01754004;
5616 Protect[5] = 0x03f54084;
5618 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5622 // This is "HT non-member protection mode."
5623 // If there may be non-HT STAs my BSS
5624 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5625 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
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 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5645 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5646 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5648 //Assign Protection method for 40MHz packets
5649 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5650 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5651 Protect[2] = ProtCfg.word;
5652 Protect[3] = ProtCfg4.word;
5655 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5656 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5658 Protect[4] = ProtCfg.word;
5659 Protect[5] = ProtCfg4.word;
5661 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5665 // HT mixed mode. PROTECT ALL!
5667 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5668 ProtCfg4.word = 0x03f44084;
5669 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5670 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5672 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5673 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5675 //Assign Protection method for 20&40 MHz packets
5676 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5677 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5678 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5679 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5680 Protect[2] = ProtCfg.word;
5681 Protect[3] = ProtCfg4.word;
5682 Protect[4] = ProtCfg.word;
5683 Protect[5] = ProtCfg4.word;
5684 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5688 // Special on for Atheros problem n chip.
5689 Protect[2] = 0x01754004;
5690 Protect[3] = 0x03f54084;
5691 Protect[4] = 0x01754004;
5692 Protect[5] = 0x03f54084;
5693 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5697 #endif // DOT11_N_SUPPORT //
5699 offset = CCK_PROT_CFG;
5700 for (i = 0;i < 6;i++)
5702 if ((SetMask & (1<< i)))
5704 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5710 ==========================================================================
5713 IRQL = PASSIVE_LEVEL
5714 IRQL = DISPATCH_LEVEL
5716 ==========================================================================
5718 VOID AsicSwitchChannel(
5719 IN PRTMP_ADAPTER pAd,
5723 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5724 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5726 UINT32 Value = 0; //BbpReg, Value;
5727 RTMP_RF_REGS *RFRegTable;
5729 // Search Tx power value
5730 for (index = 0; index < pAd->ChannelListNum; index++)
5732 if (Channel == pAd->ChannelList[index].Channel)
5734 TxPwer = pAd->ChannelList[index].Power;
5735 TxPwer2 = pAd->ChannelList[index].Power2;
5740 if (index == MAX_NUM_OF_CHANNELS)
5742 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5746 RFRegTable = RF2850RegTable;
5748 switch (pAd->RfIcType)
5755 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5757 if (Channel == RFRegTable[index].Channel)
5759 R2 = RFRegTable[index].R2;
5760 if (pAd->Antenna.field.TxPath == 1)
5762 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5765 if (pAd->Antenna.field.RxPath == 2)
5767 R2 |= 0x40; // write 1 to off Rxpath.
5769 else if (pAd->Antenna.field.RxPath == 1)
5771 R2 |= 0x20040; // write 1 to off RxPath
5776 // initialize R3, R4
5777 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5778 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5780 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5782 if ((TxPwer >= -7) && (TxPwer < 0))
5784 TxPwer = (7+TxPwer);
5785 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5786 R3 |= (TxPwer << 10);
5787 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5791 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5792 R3 |= (TxPwer << 10) | (1 << 9);
5796 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5798 TxPwer2 = (7+TxPwer2);
5799 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5800 R4 |= (TxPwer2 << 7);
5801 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5805 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5806 R4 |= (TxPwer2 << 7) | (1 << 6);
5811 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5812 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5815 // Based on BBP current mode before changing RF channel.
5816 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5822 pAd->LatchRfRegs.Channel = Channel;
5823 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5824 pAd->LatchRfRegs.R2 = R2;
5825 pAd->LatchRfRegs.R3 = R3;
5826 pAd->LatchRfRegs.R4 = R4;
5828 // Set RF value 1's set R3[bit2] = [0]
5829 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5830 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5831 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5832 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5836 // Set RF value 2's set R3[bit2] = [1]
5837 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5838 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5839 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5840 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5844 // Set RF value 3's set R3[bit2] = [0]
5845 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5846 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5847 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5848 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5860 // Change BBP setting during siwtch from a->g, g->a
5863 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5865 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5866 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5867 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5868 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.
5869 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5871 // Rx High power VGA offset for LNA select
5872 if (pAd->NicConfig2.field.ExternalLNAForG)
5874 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5875 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5879 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5880 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5883 // 5G band selection PIN, bit1 and bit2 are complement
5884 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5887 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5889 // Turn off unused PA or LNA when only 1T or 1R
5890 if (pAd->Antenna.field.TxPath == 1)
5892 TxPinCfg &= 0xFFFFFFF3;
5894 if (pAd->Antenna.field.RxPath == 1)
5896 TxPinCfg &= 0xFFFFF3FF;
5899 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5903 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5905 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5906 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5907 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5908 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.
5909 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5911 // Rx High power VGA offset for LNA select
5912 if (pAd->NicConfig2.field.ExternalLNAForA)
5914 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5918 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5921 // 5G band selection PIN, bit1 and bit2 are complement
5922 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5925 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5927 // Turn off unused PA or LNA when only 1T or 1R
5928 if (pAd->Antenna.field.TxPath == 1)
5930 TxPinCfg &= 0xFFFFFFF3;
5932 if (pAd->Antenna.field.RxPath == 1)
5934 TxPinCfg &= 0xFFFFF3FF;
5937 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5940 // R66 should be set according to Channel and use 20MHz when scanning
5941 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5943 RTMPSetAGCInitValue(pAd, BW_20);
5945 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5948 // On 11A, We should delay and wait RF/BBP to be stable
5949 // and the appropriate time should be 1000 micro seconds
5950 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5952 RTMPusecDelay(1000);
5954 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",
5957 (R3 & 0x00003e00) >> 9,
5958 (R4 & 0x000007c0) >> 6,
5959 pAd->Antenna.field.TxPath,
5960 pAd->LatchRfRegs.R1,
5961 pAd->LatchRfRegs.R2,
5962 pAd->LatchRfRegs.R3,
5963 pAd->LatchRfRegs.R4));
5967 ==========================================================================
5969 This function is required for 2421 only, and should not be used during
5970 site survey. It's only required after NIC decided to stay at a channel
5971 for a longer period.
5972 When this function is called, it's always after AsicSwitchChannel().
5974 IRQL = PASSIVE_LEVEL
5975 IRQL = DISPATCH_LEVEL
5977 ==========================================================================
5979 VOID AsicLockChannel(
5980 IN PRTMP_ADAPTER pAd,
5986 ==========================================================================
5989 IRQL = PASSIVE_LEVEL
5990 IRQL = DISPATCH_LEVEL
5992 ==========================================================================
5994 VOID AsicAntennaSelect(
5995 IN PRTMP_ADAPTER pAd,
6001 ========================================================================
6003 Routine Description:
6004 Antenna miscellaneous setting.
6007 pAd Pointer to our adapter
6008 BandState Indicate current Band State.
6013 IRQL <= DISPATCH_LEVEL
6016 1.) Frame End type control
6017 only valid for G only (RF_2527 & RF_2529)
6018 0: means DPDT, set BBP R4 bit 5 to 1
6019 1: means SPDT, set BBP R4 bit 5 to 0
6022 ========================================================================
6024 VOID AsicAntennaSetting(
6025 IN PRTMP_ADAPTER pAd,
6026 IN ABGBAND_STATE BandState)
6030 VOID AsicRfTuningExec(
6031 IN PVOID SystemSpecific1,
6032 IN PVOID FunctionContext,
6033 IN PVOID SystemSpecific2,
6034 IN PVOID SystemSpecific3)
6039 ==========================================================================
6041 Gives CCK TX rate 2 more dB TX power.
6042 This routine works only in LINK UP in INFRASTRUCTURE mode.
6044 calculate desired Tx power in RF R3.Tx0~5, should consider -
6045 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6046 1. TxPowerPercentage
6047 2. auto calibration based on TSSI feedback
6048 3. extra 2 db for CCK
6049 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6051 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6052 it should be called AFTER MlmeDynamicTxRatSwitching()
6053 ==========================================================================
6055 VOID AsicAdjustTxPower(
6056 IN PRTMP_ADAPTER pAd)
6060 BOOLEAN bAutoTxAgc = FALSE;
6061 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6062 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6063 PCHAR pTxAgcCompensate;
6067 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6068 || (pAd->bPCIclkOff == TRUE)
6069 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6070 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6073 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6075 if (pAd->CommonCfg.CentralChannel > 14)
6077 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6078 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6079 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6080 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6081 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6085 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6086 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6087 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6088 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6089 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6094 if (pAd->CommonCfg.Channel > 14)
6096 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6097 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6098 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6099 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6100 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6104 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6105 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6106 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6107 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6108 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6112 // TX power compensation for temperature variation based on TSSI. try every 4 second
6113 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6115 if (pAd->CommonCfg.Channel <= 14)
6118 bAutoTxAgc = pAd->bAutoTxAgcG;
6119 TssiRef = pAd->TssiRefG;
6120 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6121 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6122 TxAgcStep = pAd->TxAgcStepG;
6123 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6128 bAutoTxAgc = pAd->bAutoTxAgcA;
6129 TssiRef = pAd->TssiRefA;
6130 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6131 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6132 TxAgcStep = pAd->TxAgcStepA;
6133 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6138 /* BbpR1 is unsigned char */
6139 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6141 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6142 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6143 /* step value is defined in pAd->TxAgcStepG for tx power value */
6145 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6146 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6147 above value are examined in mass factory production */
6148 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6150 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6151 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6152 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6154 if (BbpR49 > pTssiMinusBoundary[1])
6156 // Reading is larger than the reference value
6157 // check for how large we need to decrease the Tx power
6158 for (idx = 1; idx < 5; idx++)
6160 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6163 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6164 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6166 DeltaPwr += (*pTxAgcCompensate);
6167 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6168 BbpR49, TssiRef, TxAgcStep, idx-1));
6170 else if (BbpR49 < pTssiPlusBoundary[1])
6172 // Reading is smaller than the reference value
6173 // check for how large we need to increase the Tx power
6174 for (idx = 1; idx < 5; idx++)
6176 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6179 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6180 *pTxAgcCompensate = TxAgcStep * (idx-1);
6181 DeltaPwr += (*pTxAgcCompensate);
6182 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6183 BbpR49, TssiRef, TxAgcStep, idx-1));
6187 *pTxAgcCompensate = 0;
6188 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6189 BbpR49, TssiRef, TxAgcStep, 0));
6195 if (pAd->CommonCfg.Channel <= 14)
6197 bAutoTxAgc = pAd->bAutoTxAgcG;
6198 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6202 bAutoTxAgc = pAd->bAutoTxAgcA;
6203 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6207 DeltaPwr += (*pTxAgcCompensate);
6210 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6213 /* calculate delta power based on the percentage specified from UI */
6214 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6215 // We lower TX power here according to the percentage specified from UI
6216 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6218 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6220 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6224 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6228 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6232 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6237 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6242 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6244 /* reset different new tx power for different TX rate */
6247 if (TxPwr[i] != 0xffffffff)
6251 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6253 if ((Value + DeltaPwr) < 0)
6255 Value = 0; /* min */
6257 else if ((Value + DeltaPwr) > 0xF)
6259 Value = 0xF; /* max */
6263 Value += DeltaPwr; /* temperature compensation */
6266 /* fill new value to CSR offset */
6267 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6270 /* write tx power value to CSR */
6271 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6272 TX power for OFDM 6M/9M
6273 TX power for CCK5.5M/11M
6274 TX power for CCK1M/2M */
6275 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6276 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6282 #ifdef CONFIG_STA_SUPPORT
6284 ==========================================================================
6286 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6287 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6288 the wakeup timer timeout. Driver has to issue a separate command to wake
6291 IRQL = DISPATCH_LEVEL
6293 ==========================================================================
6295 VOID AsicSleepThenAutoWakeup(
6296 IN PRTMP_ADAPTER pAd,
6297 IN USHORT TbttNumToNextWakeUp)
6299 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6303 ==========================================================================
6305 AsicForceWakeup() is used whenever manual wakeup is required
6306 AsicForceSleep() should only be used when not in INFRA BSS. When
6307 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6308 ==========================================================================
6310 VOID AsicForceSleep(
6311 IN PRTMP_ADAPTER pAd)
6317 ==========================================================================
6319 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6322 IRQL = PASSIVE_LEVEL
6323 IRQL = DISPATCH_LEVEL
6324 ==========================================================================
6326 VOID AsicForceWakeup(
6327 IN PRTMP_ADAPTER pAd,
6330 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6331 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6333 #endif // CONFIG_STA_SUPPORT //
6335 ==========================================================================
6339 IRQL = DISPATCH_LEVEL
6341 ==========================================================================
6344 IN PRTMP_ADAPTER pAd,
6348 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6349 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6351 Addr4 = (ULONG)(pBssid[0]) |
6352 (ULONG)(pBssid[1] << 8) |
6353 (ULONG)(pBssid[2] << 16) |
6354 (ULONG)(pBssid[3] << 24);
6355 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6358 // always one BSSID in STA mode
6359 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6361 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6364 VOID AsicSetMcastWC(
6365 IN PRTMP_ADAPTER pAd)
6367 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6370 pEntry->Sst = SST_ASSOC;
6371 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6372 pEntry->PsMode = PWR_ACTIVE;
6373 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6374 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6378 ==========================================================================
6381 IRQL = DISPATCH_LEVEL
6383 ==========================================================================
6385 VOID AsicDelWcidTab(
6386 IN PRTMP_ADAPTER pAd,
6389 ULONG Addr0 = 0x0, Addr1 = 0x0;
6392 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6393 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6394 RTMP_IO_WRITE32(pAd, offset, Addr0);
6396 RTMP_IO_WRITE32(pAd, offset, Addr1);
6400 ==========================================================================
6403 IRQL = DISPATCH_LEVEL
6405 ==========================================================================
6408 IN PRTMP_ADAPTER pAd)
6410 TX_LINK_CFG_STRUC TxLinkCfg;
6413 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6414 TxLinkCfg.field.TxRDGEn = 1;
6415 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6417 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6420 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6422 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6426 ==========================================================================
6429 IRQL = DISPATCH_LEVEL
6431 ==========================================================================
6433 VOID AsicDisableRDG(
6434 IN PRTMP_ADAPTER pAd)
6436 TX_LINK_CFG_STRUC TxLinkCfg;
6440 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6441 TxLinkCfg.field.TxRDGEn = 0;
6442 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6444 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6447 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6448 #ifdef DOT11_N_SUPPORT
6449 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6450 #endif // DOT11_N_SUPPORT //
6453 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6454 if (pAd->CommonCfg.bEnableTxBurst)
6457 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6461 ==========================================================================
6464 IRQL = PASSIVE_LEVEL
6465 IRQL = DISPATCH_LEVEL
6467 ==========================================================================
6469 VOID AsicDisableSync(
6470 IN PRTMP_ADAPTER pAd)
6472 BCN_TIME_CFG_STRUC csr;
6474 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6476 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6477 // that NIC will never wakes up because TSF stops and no more
6479 pAd->TbttTickCount = 0;
6480 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6481 csr.field.bBeaconGen = 0;
6482 csr.field.bTBTTEnable = 0;
6483 csr.field.TsfSyncMode = 0;
6484 csr.field.bTsfTicking = 0;
6485 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6490 ==========================================================================
6493 IRQL = DISPATCH_LEVEL
6495 ==========================================================================
6497 VOID AsicEnableBssSync(
6498 IN PRTMP_ADAPTER pAd)
6500 BCN_TIME_CFG_STRUC csr;
6502 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6504 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6505 #ifdef CONFIG_STA_SUPPORT
6506 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6508 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6509 csr.field.bTsfTicking = 1;
6510 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6511 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6512 csr.field.bTBTTEnable = 1;
6514 #endif // CONFIG_STA_SUPPORT //
6515 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6519 ==========================================================================
6522 BEACON frame in shared memory should be built ok before this routine
6523 can be called. Otherwise, a garbage frame maybe transmitted out every
6526 IRQL = DISPATCH_LEVEL
6528 ==========================================================================
6530 VOID AsicEnableIbssSync(
6531 IN PRTMP_ADAPTER pAd)
6533 BCN_TIME_CFG_STRUC csr9;
6537 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6539 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6540 csr9.field.bBeaconGen = 0;
6541 csr9.field.bTBTTEnable = 0;
6542 csr9.field.bTsfTicking = 0;
6543 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6545 // move BEACON TXD and frame content to on-chip memory
6546 ptr = (PUCHAR)&pAd->BeaconTxWI;
6547 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6549 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6550 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6554 // start right after the 16-byte TXWI field
6555 ptr = pAd->BeaconBuf;
6556 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6558 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6559 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6563 // start sending BEACON
6564 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6565 csr9.field.bTsfTicking = 1;
6566 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6567 csr9.field.bTBTTEnable = 1;
6568 csr9.field.bBeaconGen = 1;
6569 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6573 ==========================================================================
6576 IRQL = PASSIVE_LEVEL
6577 IRQL = DISPATCH_LEVEL
6579 ==========================================================================
6581 VOID AsicSetEdcaParm(
6582 IN PRTMP_ADAPTER pAd,
6583 IN PEDCA_PARM pEdcaParm)
6585 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6586 AC_TXOP_CSR0_STRUC csr0;
6587 AC_TXOP_CSR1_STRUC csr1;
6588 AIFSN_CSR_STRUC AifsnCsr;
6589 CWMIN_CSR_STRUC CwminCsr;
6590 CWMAX_CSR_STRUC CwmaxCsr;
6597 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6599 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6600 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6601 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6603 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6604 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6607 //========================================================
6608 // MAC Register has a copy .
6609 //========================================================
6610 if( pAd->CommonCfg.bEnableTxBurst )
6612 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6613 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6616 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6617 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6618 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6619 Ac0Cfg.field.Aifsn = 2;
6620 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6622 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6623 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6624 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6625 Ac1Cfg.field.Aifsn = 2;
6626 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6628 if (pAd->CommonCfg.PhyMode == PHY_11B)
6630 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6631 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6635 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6636 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6638 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6639 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6640 Ac2Cfg.field.Aifsn = 2;
6641 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6642 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6643 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6644 Ac3Cfg.field.Aifsn = 2;
6645 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6647 //========================================================
6648 // DMA Register has a copy too.
6649 //========================================================
6650 csr0.field.Ac0Txop = 0; // QID_AC_BE
6651 csr0.field.Ac1Txop = 0; // QID_AC_BK
6652 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6653 if (pAd->CommonCfg.PhyMode == PHY_11B)
6655 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6656 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6660 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6661 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6663 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6666 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6667 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6668 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6669 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6670 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6673 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6674 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6675 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6676 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6677 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6679 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6681 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6685 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6686 //========================================================
6687 // MAC Register has a copy.
6688 //========================================================
6690 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6691 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6693 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6695 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6696 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6697 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6698 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6700 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6701 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6702 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6703 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6705 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6706 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6707 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6708 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6709 #ifdef CONFIG_STA_SUPPORT
6710 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6712 // Tuning for Wi-Fi WMM S06
6713 if (pAd->CommonCfg.bWiFiTest &&
6714 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6715 Ac2Cfg.field.Aifsn -= 1;
6717 // Tuning for TGn Wi-Fi 5.2.32
6718 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6719 if (STA_TGN_WIFI_ON(pAd) &&
6720 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6722 Ac0Cfg.field.Aifsn = 3;
6723 Ac2Cfg.field.AcTxop = 5;
6726 #endif // CONFIG_STA_SUPPORT //
6728 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6729 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6730 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6731 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6734 if (pAd->CommonCfg.bWiFiTest)
6736 if (Ac3Cfg.field.AcTxop == 102)
6738 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6739 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6740 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6741 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6742 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6745 //#endif // WIFI_TEST //
6747 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6748 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6749 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6750 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6753 //========================================================
6754 // DMA Register has a copy too.
6755 //========================================================
6756 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6757 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6758 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6760 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6761 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6762 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6765 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6766 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6767 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6768 #ifdef CONFIG_STA_SUPPORT
6769 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6770 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6771 #endif // CONFIG_STA_SUPPORT //
6772 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6775 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6776 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6777 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6778 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6779 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6782 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6783 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6784 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6785 #ifdef CONFIG_STA_SUPPORT
6786 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6788 // Tuning for Wi-Fi WMM S06
6789 if (pAd->CommonCfg.bWiFiTest &&
6790 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6791 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6793 // Tuning for TGn Wi-Fi 5.2.32
6794 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6795 if (STA_TGN_WIFI_ON(pAd) &&
6796 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6798 AifsnCsr.field.Aifsn0 = 3;
6799 AifsnCsr.field.Aifsn2 = 7;
6802 #endif // CONFIG_STA_SUPPORT //
6804 #ifdef CONFIG_STA_SUPPORT
6805 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6806 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6807 #endif // CONFIG_STA_SUPPORT //
6808 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6810 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6813 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6814 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6815 pEdcaParm->Aifsn[0],
6816 pEdcaParm->Cwmin[0],
6817 pEdcaParm->Cwmax[0],
6818 pEdcaParm->Txop[0]<<5,
6819 pEdcaParm->bACM[0]));
6820 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6821 pEdcaParm->Aifsn[1],
6822 pEdcaParm->Cwmin[1],
6823 pEdcaParm->Cwmax[1],
6824 pEdcaParm->Txop[1]<<5,
6825 pEdcaParm->bACM[1]));
6826 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6827 pEdcaParm->Aifsn[2],
6828 pEdcaParm->Cwmin[2],
6829 pEdcaParm->Cwmax[2],
6830 pEdcaParm->Txop[2]<<5,
6831 pEdcaParm->bACM[2]));
6832 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6833 pEdcaParm->Aifsn[3],
6834 pEdcaParm->Cwmin[3],
6835 pEdcaParm->Cwmax[3],
6836 pEdcaParm->Txop[3]<<5,
6837 pEdcaParm->bACM[3]));
6843 ==========================================================================
6846 IRQL = PASSIVE_LEVEL
6847 IRQL = DISPATCH_LEVEL
6849 ==========================================================================
6851 VOID AsicSetSlotTime(
6852 IN PRTMP_ADAPTER pAd,
6853 IN BOOLEAN bUseShortSlotTime)
6856 UINT32 RegValue = 0;
6858 #ifdef CONFIG_STA_SUPPORT
6859 if (pAd->CommonCfg.Channel > 14)
6860 bUseShortSlotTime = TRUE;
6861 #endif // CONFIG_STA_SUPPORT //
6863 if (bUseShortSlotTime)
6864 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6866 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6868 SlotTime = (bUseShortSlotTime)? 9 : 20;
6870 #ifdef CONFIG_STA_SUPPORT
6871 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6873 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6874 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6875 #ifdef DOT11_N_SUPPORT
6876 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6877 #endif // DOT11_N_SUPPORT //
6880 // In this case, we will think it is doing Wi-Fi test
6881 // And we will not set to short slot when bEnableTxBurst is TRUE.
6883 else if (pAd->CommonCfg.bEnableTxBurst)
6886 #endif // CONFIG_STA_SUPPORT //
6889 // For some reasons, always set it to short slot time.
6891 // ToDo: Should consider capability with 11B
6893 #ifdef CONFIG_STA_SUPPORT
6894 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6896 if (pAd->StaCfg.BssType == BSS_ADHOC)
6899 #endif // CONFIG_STA_SUPPORT //
6901 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6902 RegValue = RegValue & 0xFFFFFF00;
6904 RegValue |= SlotTime;
6906 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6910 ========================================================================
6912 Add Shared key information into ASIC.
6913 Update shared key, TxMic and RxMic to Asic Shared key table
6914 Update its cipherAlg to Asic Shared key Mode.
6917 ========================================================================
6919 VOID AsicAddSharedKeyEntry(
6920 IN PRTMP_ADAPTER pAd,
6928 ULONG offset; //, csr0;
6929 SHAREDKEY_MODE_STRUC csr1;
6932 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6933 //============================================================================================
6935 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6936 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6937 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]));
6940 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6941 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6945 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6946 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6948 //============================================================================================
6950 // fill key material - key + TX MIC + RX MIC
6952 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6953 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
6955 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6958 offset += MAX_LEN_OF_SHARE_KEY;
6963 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6972 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6978 // Update cipher algorithm. WSTA always use BSS0
6980 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6981 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6982 if ((BssIndex%2) == 0)
6985 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6986 else if (KeyIdx == 1)
6987 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6988 else if (KeyIdx == 2)
6989 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6991 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6996 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6997 else if (KeyIdx == 1)
6998 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6999 else if (KeyIdx == 2)
7000 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7002 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7004 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7005 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7009 // IRQL = DISPATCH_LEVEL
7010 VOID AsicRemoveSharedKeyEntry(
7011 IN PRTMP_ADAPTER pAd,
7016 SHAREDKEY_MODE_STRUC csr1;
7018 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7020 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7021 if ((BssIndex%2) == 0)
7024 csr1.field.Bss0Key0CipherAlg = 0;
7025 else if (KeyIdx == 1)
7026 csr1.field.Bss0Key1CipherAlg = 0;
7027 else if (KeyIdx == 2)
7028 csr1.field.Bss0Key2CipherAlg = 0;
7030 csr1.field.Bss0Key3CipherAlg = 0;
7035 csr1.field.Bss1Key0CipherAlg = 0;
7036 else if (KeyIdx == 1)
7037 csr1.field.Bss1Key1CipherAlg = 0;
7038 else if (KeyIdx == 2)
7039 csr1.field.Bss1Key2CipherAlg = 0;
7041 csr1.field.Bss1Key3CipherAlg = 0;
7043 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7044 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7045 ASSERT(BssIndex < 4);
7051 VOID AsicUpdateWCIDAttribute(
7052 IN PRTMP_ADAPTER pAd,
7056 IN BOOLEAN bUsePairewiseKeyTable)
7058 ULONG WCIDAttri = 0, offset;
7061 // Update WCID attribute.
7062 // Only TxKey could update WCID attribute.
7064 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7065 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7066 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7069 VOID AsicUpdateWCIDIVEIV(
7070 IN PRTMP_ADAPTER pAd,
7077 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7079 RTMP_IO_WRITE32(pAd, offset, uIV);
7080 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7083 VOID AsicUpdateRxWCIDTable(
7084 IN PRTMP_ADAPTER pAd,
7091 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7092 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7093 RTMP_IO_WRITE32(pAd, offset, Addr);
7094 Addr = pAddr[4] + (pAddr[5] << 8);
7095 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7100 ========================================================================
7102 Routine Description:
7103 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7106 pAd Pointer to our adapter
7107 WCID WCID Entry number.
7108 BssIndex BSSID index, station or none multiple BSSID support
7109 this value should be 0.
7110 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7111 pCipherKey Pointer to Cipher Key.
7112 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7113 otherwise PairewiseKey table
7114 bTxKey This is the transmit key if enabled.
7120 This routine will set the relative key stuff to Asic including WCID attribute,
7121 Cipher Key, Cipher algorithm and IV/EIV.
7123 IV/EIV will be update if this CipherKey is the transmission key because
7124 ASIC will base on IV's KeyID value to select Cipher Key.
7126 If bTxKey sets to FALSE, this is not the TX key, but it could be
7129 For AP mode bTxKey must be always set to TRUE.
7130 ========================================================================
7132 VOID AsicAddKeyEntry(
7133 IN PRTMP_ADAPTER pAd,
7137 IN PCIPHER_KEY pCipherKey,
7138 IN BOOLEAN bUsePairewiseKeyTable,
7143 PUCHAR pKey = pCipherKey->Key;
7144 PUCHAR pTxMic = pCipherKey->TxMic;
7145 PUCHAR pRxMic = pCipherKey->RxMic;
7146 PUCHAR pTxtsc = pCipherKey->TxTsc;
7147 UCHAR CipherAlg = pCipherKey->CipherAlg;
7148 SHAREDKEY_MODE_STRUC csr1;
7151 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7153 // 1.) decide key table offset
7155 if (bUsePairewiseKeyTable)
7156 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7158 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7161 // 2.) Set Key to Asic
7163 //for (i = 0; i < KeyLen; i++)
7164 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7166 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7168 offset += MAX_LEN_OF_PEER_KEY;
7171 // 3.) Set MIC key if available
7175 for (i = 0; i < 8; i++)
7177 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7180 offset += LEN_TKIP_TXMICK;
7184 for (i = 0; i < 8; i++)
7186 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7192 // 4.) Modify IV/EIV if needs
7193 // This will force Asic to use this key ID by setting IV.
7197 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7201 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7202 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7203 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7205 IV4 = (KeyIdx << 6);
7206 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7207 IV4 |= 0x20; // turn on extension bit means EIV existence
7209 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7215 for (i = 0; i < 4; i++)
7217 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7220 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7223 if (!bUsePairewiseKeyTable)
7226 // Only update the shared key security mode
7228 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7229 if ((BssIndex % 2) == 0)
7232 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7233 else if (KeyIdx == 1)
7234 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7235 else if (KeyIdx == 2)
7236 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7238 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7243 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7244 else if (KeyIdx == 1)
7245 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7246 else if (KeyIdx == 2)
7247 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7249 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7251 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7254 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7259 ========================================================================
7261 Add Pair-wise key material into ASIC.
7262 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7265 ========================================================================
7267 VOID AsicAddPairwiseKeyEntry(
7268 IN PRTMP_ADAPTER pAd,
7271 IN CIPHER_KEY *pCipherKey)
7275 PUCHAR pKey = pCipherKey->Key;
7276 PUCHAR pTxMic = pCipherKey->TxMic;
7277 PUCHAR pRxMic = pCipherKey->RxMic;
7279 UCHAR CipherAlg = pCipherKey->CipherAlg;
7283 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7284 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7286 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7288 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7291 RTMP_IO_READ32(pAd, offset + i, &Value);
7294 offset += MAX_LEN_OF_PEER_KEY;
7301 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7309 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7313 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7314 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7315 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]));
7318 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7319 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7323 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7324 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7328 ========================================================================
7330 Remove Pair-wise key material from ASIC.
7333 ========================================================================
7335 VOID AsicRemovePairwiseKeyEntry(
7336 IN PRTMP_ADAPTER pAd,
7343 // re-set the entry's WCID attribute as OPEN-NONE.
7344 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7345 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7346 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7349 BOOLEAN AsicSendCommandToMcu(
7350 IN PRTMP_ADAPTER pAd,
7356 HOST_CMD_CSR_STRUC H2MCmd;
7357 H2M_MAILBOX_STRUC H2MMailbox;
7362 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7363 if (H2MMailbox.field.Owner == 0)
7375 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7377 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7379 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7380 // Reset DMA/CPU ring index
7381 RTMPRingCleanUp(pAd, QID_AC_BK);
7382 RTMPRingCleanUp(pAd, QID_AC_BE);
7383 RTMPRingCleanUp(pAd, QID_AC_VI);
7384 RTMPRingCleanUp(pAd, QID_AC_VO);
7385 RTMPRingCleanUp(pAd, QID_HCCA);
7386 RTMPRingCleanUp(pAd, QID_MGMT);
7387 RTMPRingCleanUp(pAd, QID_RX);
7390 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7392 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7393 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7398 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7399 H2MMailbox.field.CmdToken = Token;
7400 H2MMailbox.field.HighByte = Arg1;
7401 H2MMailbox.field.LowByte = Arg0;
7402 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7405 H2MCmd.field.HostCommand = Command;
7406 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7408 if (Command != 0x80)
7415 BOOLEAN AsicCheckCommanOk(
7416 IN PRTMP_ADAPTER pAd,
7419 UINT32 CmdStatus = 0, CID = 0, i;
7420 UINT32 ThisCIDMask = 0;
7425 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7426 // Find where the command is. Because this is randomly specified by firmware.
7427 if ((CID & CID0MASK) == Command)
7429 ThisCIDMask = CID0MASK;
7432 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7434 ThisCIDMask = CID1MASK;
7437 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7439 ThisCIDMask = CID2MASK;
7442 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7444 ThisCIDMask = CID3MASK;
7452 // Get CommandStatus Value
7453 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7455 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7458 // If Status is 1, the comamnd is success.
7459 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7460 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7462 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7463 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7464 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7467 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7471 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7473 // Clear Command and Status.
7474 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7475 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7481 ========================================================================
7483 Routine Description:
7484 Verify the support rate for different PHY type
7487 pAd Pointer to our adapter
7492 IRQL = PASSIVE_LEVEL
7494 ========================================================================
7496 VOID RTMPCheckRates(
7497 IN PRTMP_ADAPTER pAd,
7498 IN OUT UCHAR SupRate[],
7499 IN OUT UCHAR *SupRateLen)
7501 UCHAR RateIdx, i, j;
7502 UCHAR NewRate[12], NewRateLen;
7506 if (pAd->CommonCfg.PhyMode == PHY_11B)
7511 // Check for support rates exclude basic rate bit
7512 for (i = 0; i < *SupRateLen; i++)
7513 for (j = 0; j < RateIdx; j++)
7514 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7515 NewRate[NewRateLen++] = SupRate[i];
7517 *SupRateLen = NewRateLen;
7518 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7521 #ifdef CONFIG_STA_SUPPORT
7522 #ifdef DOT11_N_SUPPORT
7523 BOOLEAN RTMPCheckChannel(
7524 IN PRTMP_ADAPTER pAd,
7525 IN UCHAR CentralChannel,
7529 UCHAR UpperChannel = 0, LowerChannel = 0;
7530 UCHAR NoEffectChannelinList = 0;
7532 // Find upper and lower channel according to 40MHz current operation.
7533 if (CentralChannel < Channel)
7535 UpperChannel = Channel;
7536 if (CentralChannel > 2)
7537 LowerChannel = CentralChannel - 2;
7541 else if (CentralChannel > Channel)
7543 UpperChannel = CentralChannel + 2;
7544 LowerChannel = Channel;
7547 for (k = 0;k < pAd->ChannelListNum;k++)
7549 if (pAd->ChannelList[k].Channel == UpperChannel)
7551 NoEffectChannelinList ++;
7553 if (pAd->ChannelList[k].Channel == LowerChannel)
7555 NoEffectChannelinList ++;
7559 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7560 if (NoEffectChannelinList == 2)
7567 ========================================================================
7569 Routine Description:
7570 Verify the support rate for HT phy type
7573 pAd Pointer to our adapter
7576 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7578 IRQL = PASSIVE_LEVEL
7580 ========================================================================
7582 BOOLEAN RTMPCheckHt(
7583 IN PRTMP_ADAPTER pAd,
7585 IN HT_CAPABILITY_IE *pHtCapability,
7586 IN ADD_HT_INFO_IE *pAddHtInfo)
7588 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7591 // If use AMSDU, set flag.
7592 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7593 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7594 // Save Peer Capability
7595 if (pHtCapability->HtCapInfo.ShortGIfor20)
7596 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7597 if (pHtCapability->HtCapInfo.ShortGIfor40)
7598 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7599 if (pHtCapability->HtCapInfo.TxSTBC)
7600 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7601 if (pHtCapability->HtCapInfo.RxSTBC)
7602 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7603 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7605 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7608 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7610 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7613 // Will check ChannelWidth for MCSSet[4] below
7614 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7615 switch (pAd->CommonCfg.RxStream)
7618 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7619 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7620 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7621 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7624 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7625 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7626 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7627 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7630 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7631 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7632 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7633 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7637 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7639 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7640 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7641 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7643 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7645 // Send Assoc Req with my HT capability.
7646 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7647 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7648 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7649 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7650 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7651 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7652 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7653 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7654 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7655 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7656 if (pAd->CommonCfg.bRdg)
7658 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7659 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7662 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7663 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7665 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7668 #endif // DOT11_N_SUPPORT //
7669 #endif // CONFIG_STA_SUPPORT //
7672 ========================================================================
7674 Routine Description:
7675 Verify the support rate for different PHY type
7678 pAd Pointer to our adapter
7683 IRQL = PASSIVE_LEVEL
7685 ========================================================================
7687 VOID RTMPUpdateMlmeRate(
7688 IN PRTMP_ADAPTER pAd)
7691 UCHAR ProperMlmeRate; //= RATE_54;
7692 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7693 BOOLEAN bMatch = FALSE;
7695 switch (pAd->CommonCfg.PhyMode)
7698 ProperMlmeRate = RATE_11;
7699 MinimumRate = RATE_1;
7701 case PHY_11BG_MIXED:
7702 #ifdef DOT11_N_SUPPORT
7703 case PHY_11ABGN_MIXED:
7704 case PHY_11BGN_MIXED:
7705 #endif // DOT11_N_SUPPORT //
7706 if ((pAd->MlmeAux.SupRateLen == 4) &&
7707 (pAd->MlmeAux.ExtRateLen == 0))
7709 ProperMlmeRate = RATE_11;
7711 ProperMlmeRate = RATE_24;
7713 if (pAd->MlmeAux.Channel <= 14)
7714 MinimumRate = RATE_1;
7716 MinimumRate = RATE_6;
7719 #ifdef DOT11_N_SUPPORT
7720 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7721 case PHY_11GN_MIXED:
7722 case PHY_11AGN_MIXED:
7723 case PHY_11AN_MIXED:
7725 #endif // DOT11_N_SUPPORT //
7726 ProperMlmeRate = RATE_24;
7727 MinimumRate = RATE_6;
7729 case PHY_11ABG_MIXED:
7730 ProperMlmeRate = RATE_24;
7731 if (pAd->MlmeAux.Channel <= 14)
7732 MinimumRate = RATE_1;
7734 MinimumRate = RATE_6;
7737 ProperMlmeRate = RATE_1;
7738 MinimumRate = RATE_1;
7742 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7744 for (j = 0; j < RateIdx; j++)
7746 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7748 if (j == ProperMlmeRate)
7760 if (bMatch == FALSE)
7762 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7764 for (j = 0; j < RateIdx; j++)
7766 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7768 if (j == ProperMlmeRate)
7781 if (bMatch == FALSE)
7783 ProperMlmeRate = MinimumRate;
7786 pAd->CommonCfg.MlmeRate = MinimumRate;
7787 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7788 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7790 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7791 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7792 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7793 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7797 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7798 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7799 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7800 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7803 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7807 IN PRTMP_ADAPTER pAd,
7814 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7819 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7821 larger = max(Rssi0, Rssi1);
7824 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7826 larger = max(larger, Rssi2);
7836 ========================================================================
7837 Routine Description:
7838 Periodic evaluate antenna link status
7841 pAd - Adapter pointer
7846 ========================================================================
7848 VOID AsicEvaluateRxAnt(
7849 IN PRTMP_ADAPTER pAd)
7853 #ifdef CONFIG_STA_SUPPORT
7854 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7856 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7857 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7858 fRTMP_ADAPTER_RADIO_OFF |
7859 fRTMP_ADAPTER_NIC_NOT_EXIST |
7860 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7863 if (pAd->StaCfg.Psm == PWR_SAVE)
7866 #endif // CONFIG_STA_SUPPORT //
7868 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7870 if(pAd->Antenna.field.RxPath == 3)
7874 else if(pAd->Antenna.field.RxPath == 2)
7878 else if(pAd->Antenna.field.RxPath == 1)
7882 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7883 #ifdef CONFIG_STA_SUPPORT
7884 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7885 pAd->StaCfg.BBPR3 = BBPR3;
7886 #endif // CONFIG_STA_SUPPORT //
7887 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7890 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7891 pAd->RalinkCounters.OneSecTxRetryOkCount +
7892 pAd->RalinkCounters.OneSecTxFailCount;
7894 if (TxTotalCnt > 50)
7896 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7897 pAd->Mlme.bLowThroughput = FALSE;
7901 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7902 pAd->Mlme.bLowThroughput = TRUE;
7908 ========================================================================
7909 Routine Description:
7910 After evaluation, check antenna link status
7913 pAd - Adapter pointer
7918 ========================================================================
7920 VOID AsicRxAntEvalTimeout(
7921 IN PVOID SystemSpecific1,
7922 IN PVOID FunctionContext,
7923 IN PVOID SystemSpecific2,
7924 IN PVOID SystemSpecific3)
7926 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7927 #ifdef CONFIG_STA_SUPPORT
7929 CHAR larger = -127, rssi0, rssi1, rssi2;
7930 #endif // CONFIG_STA_SUPPORT //
7932 #ifdef CONFIG_STA_SUPPORT
7933 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7935 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7936 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7937 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7938 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7941 if (pAd->StaCfg.Psm == PWR_SAVE)
7945 // if the traffic is low, use average rssi as the criteria
7946 if (pAd->Mlme.bLowThroughput == TRUE)
7948 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7949 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7950 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7954 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7955 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7956 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7959 if(pAd->Antenna.field.RxPath == 3)
7961 larger = max(rssi0, rssi1);
7963 if (larger > (rssi2 + 20))
7964 pAd->Mlme.RealRxPath = 2;
7966 pAd->Mlme.RealRxPath = 3;
7968 else if(pAd->Antenna.field.RxPath == 2)
7970 if (rssi0 > (rssi1 + 20))
7971 pAd->Mlme.RealRxPath = 1;
7973 pAd->Mlme.RealRxPath = 2;
7976 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7978 if(pAd->Mlme.RealRxPath == 3)
7982 else if(pAd->Mlme.RealRxPath == 2)
7986 else if(pAd->Mlme.RealRxPath == 1)
7990 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7991 pAd->StaCfg.BBPR3 = BBPR3;
7994 #endif // CONFIG_STA_SUPPORT //
8000 VOID APSDPeriodicExec(
8001 IN PVOID SystemSpecific1,
8002 IN PVOID FunctionContext,
8003 IN PVOID SystemSpecific2,
8004 IN PVOID SystemSpecific3)
8006 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8008 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8011 pAd->CommonCfg.TriggerTimerCount++;
8016 ========================================================================
8017 Routine Description:
8018 Set/reset MAC registers according to bPiggyBack parameter
8021 pAd - Adapter pointer
8022 bPiggyBack - Enable / Disable Piggy-Back
8027 ========================================================================
8029 VOID RTMPSetPiggyBack(
8030 IN PRTMP_ADAPTER pAd,
8031 IN BOOLEAN bPiggyBack)
8033 TX_LINK_CFG_STRUC TxLinkCfg;
8035 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8037 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8038 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8042 ========================================================================
8043 Routine Description:
8044 check if this entry need to switch rate automatically
8054 ========================================================================
8056 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8057 IN PRTMP_ADAPTER pAd,
8058 IN PMAC_TABLE_ENTRY pEntry)
8060 BOOLEAN result = TRUE;
8063 #ifdef CONFIG_STA_SUPPORT
8064 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8066 // only associated STA counts
8067 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8069 result = pAd->StaCfg.bAutoTxRateSwitch;
8074 #endif // CONFIG_STA_SUPPORT //
8082 BOOLEAN RTMPAutoRateSwitchCheck(
8083 IN PRTMP_ADAPTER pAd)
8086 #ifdef CONFIG_STA_SUPPORT
8087 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8089 if (pAd->StaCfg.bAutoTxRateSwitch)
8092 #endif // CONFIG_STA_SUPPORT //
8098 ========================================================================
8099 Routine Description:
8100 check if this entry need to fix tx legacy rate
8110 ========================================================================
8112 UCHAR RTMPStaFixedTxMode(
8113 IN PRTMP_ADAPTER pAd,
8114 IN PMAC_TABLE_ENTRY pEntry)
8116 UCHAR tx_mode = FIXED_TXMODE_HT;
8119 #ifdef CONFIG_STA_SUPPORT
8120 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8122 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8124 #endif // CONFIG_STA_SUPPORT //
8130 ========================================================================
8131 Routine Description:
8132 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8142 ========================================================================
8144 VOID RTMPUpdateLegacyTxSetting(
8145 UCHAR fixed_tx_mode,
8146 PMAC_TABLE_ENTRY pEntry)
8148 HTTRANSMIT_SETTING TransmitSetting;
8150 if (fixed_tx_mode == FIXED_TXMODE_HT)
8153 TransmitSetting.word = 0;
8155 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8156 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8158 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8160 TransmitSetting.field.MODE = MODE_CCK;
8161 // CCK mode allow MCS 0~3
8162 if (TransmitSetting.field.MCS > MCS_3)
8163 TransmitSetting.field.MCS = MCS_3;
8167 TransmitSetting.field.MODE = MODE_OFDM;
8168 // OFDM mode allow MCS 0~7
8169 if (TransmitSetting.field.MCS > MCS_7)
8170 TransmitSetting.field.MCS = MCS_7;
8173 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8175 pEntry->HTPhyMode.word = TransmitSetting.word;
8176 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8177 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8181 #ifdef CONFIG_STA_SUPPORT
8183 ==========================================================================
8185 dynamic tune BBP R66 to find a balance between sensibility and
8188 IRQL = DISPATCH_LEVEL
8190 ==========================================================================
8192 VOID AsicStaBbpTuning(
8193 IN PRTMP_ADAPTER pAd)
8195 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8198 // 2860C did not support Fase CCA, therefore can't tune
8199 if (pAd->MACVersion == 0x28600100)
8205 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8208 if ((pAd->OpMode == OPMODE_STA)
8209 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8211 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8212 && (pAd->bPCIclkOff == FALSE))
8214 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8217 if (pAd->Antenna.field.RxPath > 1)
8218 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8220 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8222 if (pAd->LatchRfRegs.Channel <= 14)
8225 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8227 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8228 if (OrigR66Value != R66)
8230 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8235 R66 = 0x2E + GET_LNA_GAIN(pAd);
8236 if (OrigR66Value != R66)
8238 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8245 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8247 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8249 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8250 if (OrigR66Value != R66)
8252 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8257 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8258 if (OrigR66Value != R66)
8260 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8266 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8268 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8269 if (OrigR66Value != R66)
8271 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8276 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8277 if (OrigR66Value != R66)
8279 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8289 VOID AsicResetFromDMABusy(
8290 IN PRTMP_ADAPTER pAd)
8293 BOOLEAN bCtrl = FALSE;
8295 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8297 // Be sure restore link control value so we can write register.
8298 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8299 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8301 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8302 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8303 RTMPusecDelay(6000);
8304 pAd->bPCIclkOff = FALSE;
8308 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8310 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8312 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8313 // Reset DMA/CPU ring index
8314 RTMPRingCleanUp(pAd, QID_AC_BK);
8315 RTMPRingCleanUp(pAd, QID_AC_BE);
8316 RTMPRingCleanUp(pAd, QID_AC_VI);
8317 RTMPRingCleanUp(pAd, QID_AC_VO);
8318 RTMPRingCleanUp(pAd, QID_HCCA);
8319 RTMPRingCleanUp(pAd, QID_MGMT);
8320 RTMPRingCleanUp(pAd, QID_RX);
8323 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8325 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8327 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8328 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8329 RTMPPCIeLinkCtrlSetting(pAd, 3);
8331 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8332 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8333 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8337 IN PRTMP_ADAPTER pAd)
8339 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8341 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8342 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8343 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8345 // After hard-reset BBP, initialize all BBP values.
8346 NICRestoreBBPValue(pAd);
8347 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8351 IN PRTMP_ADAPTER pAd)
8355 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8356 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8358 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8360 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8362 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8366 IN PRTMP_ADAPTER pAd)
8368 ULONG Value1, Value2;
8371 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8372 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8375 // sum should be equals to 0xff, which is the total buffer size.
8376 if ((Value1 + Value2) < 0xff)
8378 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8379 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8381 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8383 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8385 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8388 #endif // CONFIG_STA_SUPPORT //
8390 VOID RTMPSetAGCInitValue(
8391 IN PRTMP_ADAPTER pAd,
8396 if (pAd->LatchRfRegs.Channel <= 14)
8398 R66 = 0x2E + GET_LNA_GAIN(pAd);
8399 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8403 if (BandWidth == BW_20)
8405 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8406 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8408 #ifdef DOT11_N_SUPPORT
8411 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8412 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8414 #endif // DOT11_N_SUPPORT //
8419 VOID AsicTurnOffRFClk(
8420 IN PRTMP_ADAPTER pAd,
8425 UINT32 R1 = 0, R2 = 0, R3 = 0;
8427 RTMP_RF_REGS *RFRegTable;
8429 RFRegTable = RF2850RegTable;
8431 switch (pAd->RfIcType)
8438 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8440 if (Channel == RFRegTable[index].Channel)
8442 R1 = RFRegTable[index].R1 & 0xffffdfff;
8443 R2 = RFRegTable[index].R2 & 0xfffbffff;
8444 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8446 RTMP_RF_IO_WRITE32(pAd, R1);
8447 RTMP_RF_IO_WRITE32(pAd, R2);
8449 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8450 // Set RF R2 bit18=0, R3 bit[18:19]=0
8451 //if (pAd->StaCfg.bRadio == FALSE)
8454 RTMP_RF_IO_WRITE32(pAd, R3);
8456 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8457 Channel, pAd->RfIcType, R2, R3));
8460 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8461 Channel, pAd->RfIcType, R2));
8473 VOID AsicTurnOnRFClk(
8474 IN PRTMP_ADAPTER pAd,
8479 UINT32 R1 = 0, R2 = 0, R3 = 0;
8481 RTMP_RF_REGS *RFRegTable;
8483 RFRegTable = RF2850RegTable;
8485 switch (pAd->RfIcType)
8492 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8494 if (Channel == RFRegTable[index].Channel)
8496 R3 = pAd->LatchRfRegs.R3;
8499 RTMP_RF_IO_WRITE32(pAd, R3);
8501 R1 = RFRegTable[index].R1;
8502 RTMP_RF_IO_WRITE32(pAd, R1);
8504 R2 = RFRegTable[index].R2;
8505 if (pAd->Antenna.field.TxPath == 1)
8507 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8510 if (pAd->Antenna.field.RxPath == 2)
8512 R2 |= 0x40; // write 1 to off Rxpath.
8514 else if (pAd->Antenna.field.RxPath == 1)
8516 R2 |= 0x20040; // write 1 to off RxPath
8518 RTMP_RF_IO_WRITE32(pAd, R2);
8529 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",