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 #ifdef QOS_DLS_SUPPORT
505 DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc);
506 #endif // QOS_DLS_SUPPORT //
509 // Since we are using switch/case to implement it, the init is different from the above
510 // state machine init
511 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
513 #endif // CONFIG_STA_SUPPORT //
517 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
519 // Init mlme periodic timer
520 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
522 // Set mlme periodic timer
523 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
525 // software-based RX Antenna diversity
526 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
529 #ifdef CONFIG_STA_SUPPORT
531 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
533 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
535 // only PCIe cards need these two timers
536 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
537 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
541 #endif // CONFIG_STA_SUPPORT //
545 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
551 ==========================================================================
553 main loop of the MLME
555 Mlme has to be initialized, and there are something inside the queue
557 This function is invoked from MPSetInformation and MPReceive;
558 This task guarantee only one MlmeHandler will run.
560 IRQL = DISPATCH_LEVEL
562 ==========================================================================
565 IN PRTMP_ADAPTER pAd)
567 MLME_QUEUE_ELEM *Elem = NULL;
572 // Only accept MLME and Frame from peer side, no other (control/data) frame should
573 // get into this state machine
575 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
576 if(pAd->Mlme.bRunning)
578 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
583 pAd->Mlme.bRunning = TRUE;
585 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
587 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
589 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
590 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
591 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
593 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
600 DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n"));
603 #endif // RALINK_ATE //
605 //From message type, determine which state machine I should drive
606 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
609 // if dequeue success
610 switch (Elem->Machine)
612 // STA state machines
613 #ifdef CONFIG_STA_SUPPORT
614 case ASSOC_STATE_MACHINE:
615 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
617 case AUTH_STATE_MACHINE:
618 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
620 case AUTH_RSP_STATE_MACHINE:
621 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
623 case SYNC_STATE_MACHINE:
624 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
626 case MLME_CNTL_STATE_MACHINE:
627 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
629 case WPA_PSK_STATE_MACHINE:
630 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
633 case LEAP_STATE_MACHINE:
634 LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
637 case AIRONET_STATE_MACHINE:
638 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
641 #ifdef QOS_DLS_SUPPORT
642 case DLS_STATE_MACHINE:
643 StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem);
645 #endif // QOS_DLS_SUPPORT //
646 #endif // CONFIG_STA_SUPPORT //
648 case ACTION_STATE_MACHINE:
649 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
656 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
661 Elem->Occupied = FALSE;
666 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
670 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
671 pAd->Mlme.bRunning = FALSE;
672 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
676 ==========================================================================
678 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
680 Adapter - NIC Adapter pointer
682 The MLME task will no longer work properly
686 ==========================================================================
689 IN PRTMP_ADAPTER pAd)
693 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
695 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
697 // disable BEACON generation and other BEACON related hardware timers
698 AsicDisableSync(pAd);
701 #ifdef CONFIG_STA_SUPPORT
702 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
704 #ifdef QOS_DLS_SUPPORT
706 #endif // QOS_DLS_SUPPORT //
707 // Cancel pending timers
708 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
709 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
710 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
711 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
712 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
713 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
715 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
717 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
718 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
722 #ifdef QOS_DLS_SUPPORT
723 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
725 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
727 #endif // QOS_DLS_SUPPORT //
729 #endif // CONFIG_STA_SUPPORT //
731 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
732 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
736 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
739 RTMPSetLED(pAd, LED_HALT);
740 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
743 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
745 MlmeQueueDestroy(&pAd->Mlme.Queue);
746 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
748 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
751 VOID MlmeResetRalinkCounters(
752 IN PRTMP_ADAPTER pAd)
754 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
755 // clear all OneSecxxx counters.
756 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
757 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
758 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
759 pAd->RalinkCounters.OneSecRxOkCnt = 0;
760 pAd->RalinkCounters.OneSecTxFailCount = 0;
761 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
762 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
763 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
765 // TODO: for debug only. to be removed
766 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
767 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
768 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
769 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
770 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
771 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
772 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
773 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
774 pAd->RalinkCounters.OneSecTxDoneCount = 0;
775 pAd->RalinkCounters.OneSecRxCount = 0;
776 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
777 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
782 unsigned long rx_AMSDU;
783 unsigned long rx_Total;
786 ==========================================================================
788 This routine is executed periodically to -
789 1. Decide if it's a right time to turn on PwrMgmt bit of all
791 2. Calculate ChannelQuality based on statistics of the last
792 period, so that TX rate won't toggling very frequently between a
793 successful TX and a failed TX.
794 3. If the calculated ChannelQuality indicated current connection not
795 healthy, then a ROAMing attempt is tried here.
797 IRQL = DISPATCH_LEVEL
799 ==========================================================================
801 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
802 VOID MlmePeriodicExec(
803 IN PVOID SystemSpecific1,
804 IN PVOID FunctionContext,
805 IN PVOID SystemSpecific2,
806 IN PVOID SystemSpecific3)
809 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
811 #ifdef CONFIG_STA_SUPPORT
813 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
815 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
816 // Move code to here, because following code will return when radio is off
817 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) && (pAd->StaCfg.bHardwareRadio == TRUE) &&
818 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
819 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) &&
820 (pAd->bPCIclkOff == FALSE))
824 // Read GPIO pin2 as Hardware controlled radio state
825 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &data);
828 pAd->StaCfg.bHwRadio = TRUE;
832 pAd->StaCfg.bHwRadio = FALSE;
834 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
836 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
837 if (pAd->StaCfg.bRadio == TRUE)
840 // Update extra information
841 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
846 // Update extra information
847 pAd->ExtraInfo = HW_RADIO_OFF;
853 #endif // CONFIG_STA_SUPPORT //
855 // Do nothing if the driver is starting halt state.
856 // This might happen when timer already been fired before cancel timer with mlmehalt
857 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
858 fRTMP_ADAPTER_RADIO_OFF |
859 fRTMP_ADAPTER_RADIO_MEASUREMENT |
860 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
863 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
866 /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */
869 if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1))
871 pAd->Mlme.PeriodicRound ++;
875 #endif // RALINK_ATE //
877 #ifdef CONFIG_STA_SUPPORT
878 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
880 // Do nothing if monitor mode is on
884 if (pAd->Mlme.PeriodicRound & 0x1)
886 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
887 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
888 (STA_TGN_WIFI_ON(pAd)) &&
889 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
892 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
893 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
895 else if ((STA_TGN_WIFI_ON(pAd)) &&
896 ((pAd->MACVersion & 0xffff) == 0x0101))
898 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
899 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
903 #endif // CONFIG_STA_SUPPORT //
905 pAd->bUpdateBcnCntDone = FALSE;
907 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
908 pAd->Mlme.PeriodicRound ++;
910 // execute every 500ms
911 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
913 #ifdef CONFIG_STA_SUPPORT
914 // perform dynamic tx rate switching based on past TX history
915 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
917 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
919 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
920 MlmeDynamicTxRateSwitching(pAd);
922 #endif // CONFIG_STA_SUPPORT //
925 // Normal 1 second Mlme PeriodicExec.
926 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
928 pAd->Mlme.OneSecPeriodicRound ++;
933 /* request from Baron : move this routine from later to here */
934 /* for showing Rx error count in ATE RXFRAME */
935 NICUpdateRawCounters(pAd);
936 if (pAd->ate.bRxFer == 1)
938 pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec;
939 ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt);
940 pAd->ate.RxCntPerSec = 0;
942 if (pAd->ate.RxAntennaSel == 0)
943 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n",
944 pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2);
946 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0);
948 MlmeResetRalinkCounters(pAd);
951 #endif // RALINK_ATE //
962 // Media status changed, report to NDIS
963 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
965 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
966 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
968 pAd->IndicateMediaState = NdisMediaStateConnected;
969 RTMP_IndicateMediaState(pAd);
974 pAd->IndicateMediaState = NdisMediaStateDisconnected;
975 RTMP_IndicateMediaState(pAd);
979 NdisGetSystemUpTime(&pAd->Mlme.Now32);
981 // add the most up-to-date h/w raw counters into software variable, so that
982 // the dynamic tuning mechanism below are based on most up-to-date information
983 NICUpdateRawCounters(pAd);
986 #ifdef DOT11_N_SUPPORT
987 // Need statistics after read counter. So put after NICUpdateRawCounters
988 ORIBATimerTimeout(pAd);
989 #endif // DOT11_N_SUPPORT //
992 // The time period for checking antenna is according to traffic
993 if (pAd->Mlme.bEnableAutoAntennaCheck)
995 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
996 pAd->RalinkCounters.OneSecTxRetryOkCount +
997 pAd->RalinkCounters.OneSecTxFailCount;
1001 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
1003 AsicEvaluateRxAnt(pAd);
1008 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
1010 AsicEvaluateRxAnt(pAd);
1015 #ifdef CONFIG_STA_SUPPORT
1016 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1017 STAMlmePeriodicExec(pAd);
1018 #endif // CONFIG_STA_SUPPORT //
1020 MlmeResetRalinkCounters(pAd);
1022 #ifdef CONFIG_STA_SUPPORT
1023 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1026 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1029 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1030 // and sending CTS-to-self over and over.
1031 // Software Patch Solution:
1032 // 1. Polling debug state register 0x10F4 every one second.
1033 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1034 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1038 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1039 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1041 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1043 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1045 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1049 #endif // CONFIG_STA_SUPPORT //
1051 RT28XX_MLME_HANDLER(pAd);
1055 pAd->bUpdateBcnCntDone = FALSE;
1058 #ifdef CONFIG_STA_SUPPORT
1059 VOID STAMlmePeriodicExec(
1065 // We return here in ATE mode, because the statistics
1066 // that ATE needs are not collected via this routine.
1069 // It is supposed that we will never reach here in ATE mode.
1070 ASSERT(!(ATE_ON(pAd)));
1073 #endif // RALINK_ATE //
1075 #ifdef WPA_SUPPLICANT_SUPPORT
1076 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1077 #endif // WPA_SUPPLICANT_SUPPORT //
1079 // WPA MIC error should block association attempt for 60 seconds
1080 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1081 pAd->StaCfg.bBlockAssoc = FALSE;
1084 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1086 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1088 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1090 pAd->PreMediaState = pAd->IndicateMediaState;
1096 AsicStaBbpTuning(pAd);
1098 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1099 pAd->RalinkCounters.OneSecTxRetryOkCount +
1100 pAd->RalinkCounters.OneSecTxFailCount;
1102 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1104 // update channel quality for Roaming and UI LinkQuality display
1105 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1108 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1109 // Radio is currently in noisy environment
1110 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1111 AsicAdjustTxPower(pAd);
1115 #ifdef QOS_DLS_SUPPORT
1116 // Check DLS time out, then tear down those session
1117 RTMPCheckDLSTimeOut(pAd);
1118 #endif // QOS_DLS_SUPPORT //
1120 // Is PSM bit consistent with user power management policy?
1121 // This is the only place that will set PSM bit ON.
1122 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1123 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1125 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1127 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1128 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1129 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1131 RTMPSetAGCInitValue(pAd, BW_20);
1132 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1136 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1138 // When APSD is enabled, the period changes as 20 sec
1139 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1140 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1144 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1145 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1147 if (pAd->CommonCfg.bWmmCapable)
1148 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1150 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1155 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1157 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1158 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1159 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1161 // Lost AP, send disconnect & link down event
1162 LinkDown(pAd, FALSE);
1164 #ifdef WPA_SUPPLICANT_SUPPORT
1165 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1166 if (pAd->StaCfg.WpaSupplicantUP)
1168 union iwreq_data wrqu;
1169 //send disassociate event to wpa_supplicant
1170 memset(&wrqu, 0, sizeof(wrqu));
1171 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1172 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1174 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1175 #endif // WPA_SUPPLICANT_SUPPORT //
1177 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1179 union iwreq_data wrqu;
1180 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1181 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1183 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1185 MlmeAutoReconnectLastSSID(pAd);
1187 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1189 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1190 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1191 MlmeAutoReconnectLastSSID(pAd);
1194 // Add auto seamless roaming
1195 if (pAd->StaCfg.bFastRoaming)
1197 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1199 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));
1201 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1203 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1207 else if (ADHOC_ON(pAd))
1209 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1210 // the "TX BEACON competition" for the entire past 1 sec.
1211 // So that even when ASIC's BEACONgen engine been blocked
1212 // by peer's BEACON due to slower system clock, this STA still can send out
1213 // minimum BEACON to tell the peer I'm alive.
1214 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1215 // EnqueueBeaconFrame(pAd); // software send BEACON
1217 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1218 // restore outgoing BEACON to support B/G-mixed mode
1219 if ((pAd->CommonCfg.Channel <= 14) &&
1220 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1221 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1222 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1224 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1225 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1226 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1227 MlmeUpdateTxRates(pAd, FALSE, 0);
1228 MakeIbssBeacon(pAd); // re-build BEACON frame
1229 AsicEnableIbssSync(pAd); // copy to on-chip memory
1230 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1233 #ifdef DOT11_N_SUPPORT
1234 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1236 if ((pAd->StaCfg.AdhocBGJoined) &&
1237 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1239 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1240 pAd->StaCfg.AdhocBGJoined = FALSE;
1243 if ((pAd->StaCfg.Adhoc20NJoined) &&
1244 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1246 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1247 pAd->StaCfg.Adhoc20NJoined = FALSE;
1250 #endif // DOT11_N_SUPPORT //
1253 if ((pAd->CommonCfg.Channel > 14)
1254 && (pAd->CommonCfg.bIEEE80211H == 1)
1255 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1257 RadarDetectPeriodic(pAd);
1260 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1261 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1263 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1264 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1266 MLME_START_REQ_STRUCT StartReq;
1268 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1269 LinkDown(pAd, FALSE);
1271 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1272 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1273 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1276 else // no INFRA nor ADHOC connection
1279 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1280 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1281 goto SKIP_AUTO_SCAN_CONN;
1283 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1285 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1286 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1287 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1289 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1291 MLME_SCAN_REQ_STRUCT ScanReq;
1293 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1295 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1296 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1297 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1298 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1299 // Reset Missed scan number
1300 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1302 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1303 MlmeAutoReconnectLastSSID(pAd);
1305 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1307 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1310 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1314 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1315 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1317 if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1)
1318 MlmeAutoReconnectLastSSID(pAd);
1321 #endif // CARRIER_DETECTION_SUPPORT //
1322 MlmeAutoReconnectLastSSID(pAd);
1328 SKIP_AUTO_SCAN_CONN:
1330 #ifdef DOT11_N_SUPPORT
1331 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1333 pAd->MacTab.fAnyBASession = TRUE;
1334 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1336 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1338 pAd->MacTab.fAnyBASession = FALSE;
1339 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1341 #endif // DOT11_N_SUPPORT //
1344 #ifdef DOT11_N_SUPPORT
1345 #ifdef DOT11N_DRAFT3
1346 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1347 TriEventCounterMaintenance(pAd);
1348 #endif // DOT11N_DRAFT3 //
1349 #endif // DOT11_N_SUPPORT //
1356 IN PVOID SystemSpecific1,
1357 IN PVOID FunctionContext,
1358 IN PVOID SystemSpecific2,
1359 IN PVOID SystemSpecific3)
1362 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1364 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1365 RTMP_IndicateMediaState(pAd);
1366 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1369 // IRQL = DISPATCH_LEVEL
1371 IN PRTMP_ADAPTER pAd)
1373 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1374 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1376 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1378 MLME_CNTL_STATE_MACHINE,
1379 OID_802_11_BSSID_LIST_SCAN,
1382 RT28XX_MLME_HANDLER(pAd);
1386 // IRQL = DISPATCH_LEVEL
1387 VOID MlmeAutoReconnectLastSSID(
1388 IN PRTMP_ADAPTER pAd)
1392 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1393 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1394 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1396 NDIS_802_11_SSID OidSsid;
1397 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1398 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1400 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1402 MLME_CNTL_STATE_MACHINE,
1404 sizeof(NDIS_802_11_SSID),
1406 RT28XX_MLME_HANDLER(pAd);
1409 #endif // CONFIG_STA_SUPPORT //
1412 ==========================================================================
1413 Validate SSID for connection try and rescan purpose
1414 Valid SSID will have visible chars only.
1415 The valid length is from 0 to 32.
1416 IRQL = DISPATCH_LEVEL
1417 ==========================================================================
1419 BOOLEAN MlmeValidateSSID(
1425 if (SsidLen > MAX_LEN_OF_SSID)
1428 // Check each character value
1429 for (index = 0; index < SsidLen; index++)
1431 if (pSsid[index] < 0x20)
1439 VOID MlmeSelectTxRateTable(
1440 IN PRTMP_ADAPTER pAd,
1441 IN PMAC_TABLE_ENTRY pEntry,
1443 IN PUCHAR pTableSize,
1444 IN PUCHAR pInitTxRateIdx)
1448 // decide the rate table for tuning
1449 if (pAd->CommonCfg.TxRateTableSize > 0)
1451 *ppTable = RateSwitchTable;
1452 *pTableSize = RateSwitchTable[0];
1453 *pInitTxRateIdx = RateSwitchTable[1];
1458 #ifdef CONFIG_STA_SUPPORT
1459 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1461 #ifdef DOT11_N_SUPPORT
1462 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1463 !pAd->StaCfg.AdhocBOnlyJoined &&
1464 !pAd->StaCfg.AdhocBGJoined &&
1465 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1466 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1468 *ppTable = RateSwitchTable11N1S;
1469 *pTableSize = RateSwitchTable11N1S[0];
1470 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1473 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1474 !pAd->StaCfg.AdhocBOnlyJoined &&
1475 !pAd->StaCfg.AdhocBGJoined &&
1476 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1477 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1478 (pAd->Antenna.field.TxPath == 2))
1480 if (pAd->LatchRfRegs.Channel <= 14)
1482 *ppTable = RateSwitchTable11N2S;
1483 *pTableSize = RateSwitchTable11N2S[0];
1484 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1488 *ppTable = RateSwitchTable11N2SForABand;
1489 *pTableSize = RateSwitchTable11N2SForABand[0];
1490 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1495 #endif // DOT11_N_SUPPORT //
1496 if (pAd->CommonCfg.PhyMode == PHY_11B)
1498 *ppTable = RateSwitchTable11B;
1499 *pTableSize = RateSwitchTable11B[0];
1500 *pInitTxRateIdx = RateSwitchTable11B[1];
1503 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1505 // USe B Table when Only b-only Station in my IBSS .
1506 *ppTable = RateSwitchTable11B;
1507 *pTableSize = RateSwitchTable11B[0];
1508 *pInitTxRateIdx = RateSwitchTable11B[1];
1511 else if (pAd->LatchRfRegs.Channel <= 14)
1513 *ppTable = RateSwitchTable11BG;
1514 *pTableSize = RateSwitchTable11BG[0];
1515 *pInitTxRateIdx = RateSwitchTable11BG[1];
1520 *ppTable = RateSwitchTable11G;
1521 *pTableSize = RateSwitchTable11G[0];
1522 *pInitTxRateIdx = RateSwitchTable11G[1];
1527 #endif // CONFIG_STA_SUPPORT //
1529 #ifdef DOT11_N_SUPPORT
1530 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1531 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1533 *ppTable = RateSwitchTable11BGN1S;
1534 *pTableSize = RateSwitchTable11BGN1S[0];
1535 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1540 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1541 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1543 if (pAd->LatchRfRegs.Channel <= 14)
1545 *ppTable = RateSwitchTable11BGN2S;
1546 *pTableSize = RateSwitchTable11BGN2S[0];
1547 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1552 *ppTable = RateSwitchTable11BGN2SForABand;
1553 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1554 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1560 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1562 *ppTable = RateSwitchTable11N1S;
1563 *pTableSize = RateSwitchTable11N1S[0];
1564 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1569 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1571 if (pAd->LatchRfRegs.Channel <= 14)
1573 *ppTable = RateSwitchTable11N2S;
1574 *pTableSize = RateSwitchTable11N2S[0];
1575 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1579 *ppTable = RateSwitchTable11N2SForABand;
1580 *pTableSize = RateSwitchTable11N2SForABand[0];
1581 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1586 #endif // DOT11_N_SUPPORT //
1587 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1588 if ((pEntry->RateLen == 4)
1589 #ifdef DOT11_N_SUPPORT
1590 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1591 #endif // DOT11_N_SUPPORT //
1594 *ppTable = RateSwitchTable11B;
1595 *pTableSize = RateSwitchTable11B[0];
1596 *pInitTxRateIdx = RateSwitchTable11B[1];
1601 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1602 if ((pEntry->RateLen > 8)
1603 #ifdef DOT11_N_SUPPORT
1604 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1605 #endif // DOT11_N_SUPPORT //
1608 *ppTable = RateSwitchTable11BG;
1609 *pTableSize = RateSwitchTable11BG[0];
1610 *pInitTxRateIdx = RateSwitchTable11BG[1];
1615 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1616 if ((pEntry->RateLen == 8)
1617 #ifdef DOT11_N_SUPPORT
1618 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1619 #endif // DOT11_N_SUPPORT //
1622 *ppTable = RateSwitchTable11G;
1623 *pTableSize = RateSwitchTable11G[0];
1624 *pInitTxRateIdx = RateSwitchTable11G[1];
1628 #ifdef DOT11_N_SUPPORT
1629 #endif // DOT11_N_SUPPORT //
1631 #ifdef CONFIG_STA_SUPPORT
1632 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1634 #ifdef DOT11_N_SUPPORT
1635 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1636 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1637 #endif // DOT11_N_SUPPORT //
1639 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1641 *ppTable = RateSwitchTable11B;
1642 *pTableSize = RateSwitchTable11B[0];
1643 *pInitTxRateIdx = RateSwitchTable11B[1];
1645 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1647 *ppTable = RateSwitchTable11G;
1648 *pTableSize = RateSwitchTable11G[0];
1649 *pInitTxRateIdx = RateSwitchTable11G[1];
1654 *ppTable = RateSwitchTable11BG;
1655 *pTableSize = RateSwitchTable11BG[0];
1656 *pInitTxRateIdx = RateSwitchTable11BG[1];
1660 #ifdef DOT11_N_SUPPORT
1661 if (pAd->LatchRfRegs.Channel <= 14)
1663 if (pAd->CommonCfg.TxStream == 1)
1665 *ppTable = RateSwitchTable11N1S;
1666 *pTableSize = RateSwitchTable11N1S[0];
1667 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1668 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1672 *ppTable = RateSwitchTable11N2S;
1673 *pTableSize = RateSwitchTable11N2S[0];
1674 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1675 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1680 if (pAd->CommonCfg.TxStream == 1)
1682 *ppTable = RateSwitchTable11N1S;
1683 *pTableSize = RateSwitchTable11N1S[0];
1684 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1685 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1689 *ppTable = RateSwitchTable11N2SForABand;
1690 *pTableSize = RateSwitchTable11N2SForABand[0];
1691 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1692 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1695 #endif // DOT11_N_SUPPORT //
1696 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1697 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1699 #endif // CONFIG_STA_SUPPORT //
1703 #ifdef CONFIG_STA_SUPPORT
1705 ==========================================================================
1707 This routine checks if there're other APs out there capable for
1708 roaming. Caller should call this routine only when Link up in INFRA mode
1709 and channel quality is below CQI_GOOD_THRESHOLD.
1711 IRQL = DISPATCH_LEVEL
1714 ==========================================================================
1716 VOID MlmeCheckForRoaming(
1717 IN PRTMP_ADAPTER pAd,
1721 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1724 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1725 // put all roaming candidates into RoamTab, and sort in RSSI order
1726 BssTableInit(pRoamTab);
1727 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1729 pBss = &pAd->ScanTab.BssEntry[i];
1731 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1732 continue; // AP disappear
1733 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1734 continue; // RSSI too weak. forget it.
1735 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1736 continue; // skip current AP
1737 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1738 continue; // only AP with stronger RSSI is eligible for roaming
1740 // AP passing all above rules is put into roaming candidate table
1741 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1742 pRoamTab->BssNr += 1;
1745 if (pRoamTab->BssNr > 0)
1747 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1748 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1750 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1751 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1752 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1753 RT28XX_MLME_HANDLER(pAd);
1756 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1760 ==========================================================================
1762 This routine checks if there're other APs out there capable for
1763 roaming. Caller should call this routine only when link up in INFRA mode
1764 and channel quality is below CQI_GOOD_THRESHOLD.
1766 IRQL = DISPATCH_LEVEL
1769 ==========================================================================
1771 VOID MlmeCheckForFastRoaming(
1772 IN PRTMP_ADAPTER pAd,
1776 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1779 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1780 // put all roaming candidates into RoamTab, and sort in RSSI order
1781 BssTableInit(pRoamTab);
1782 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1784 pBss = &pAd->ScanTab.BssEntry[i];
1786 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1787 continue; // RSSI too weak. forget it.
1788 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1789 continue; // skip current AP
1790 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1791 continue; // skip different SSID
1792 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1793 continue; // skip AP without better RSSI
1795 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));
1796 // AP passing all above rules is put into roaming candidate table
1797 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1798 pRoamTab->BssNr += 1;
1801 if (pRoamTab->BssNr > 0)
1803 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1804 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1806 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1807 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1808 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1809 RT28XX_MLME_HANDLER(pAd);
1812 // Maybe site survey required
1815 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1817 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1818 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1819 pAd->StaCfg.ScanCnt = 2;
1820 pAd->StaCfg.LastScanTime = Now;
1825 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1829 ==========================================================================
1831 This routine calculates TxPER, RxPER of the past N-sec period. And
1832 according to the calculation result, ChannelQuality is calculated here
1833 to decide if current AP is still doing the job.
1835 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1837 StaCfg.ChannelQuality - 0..100
1839 IRQL = DISPATCH_LEVEL
1841 NOTE: This routine decide channle quality based on RX CRC error ratio.
1842 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1843 is performed right before this routine, so that this routine can decide
1844 channel quality based on the most up-to-date information
1845 ==========================================================================
1847 VOID MlmeCalculateChannelQuality(
1848 IN PRTMP_ADAPTER pAd,
1851 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1855 ULONG BeaconLostTime = BEACON_LOST_TIME;
1857 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1858 // longer beacon lost time when carrier detection enabled
1859 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1861 BeaconLostTime = BEACON_LOST_TIME + BEACON_LOST_TIME/2;
1863 #endif // CARRIER_DETECTION_SUPPORT //
1865 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1868 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1870 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1871 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1879 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1880 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1884 // calculate RX PER - don't take RxPER into consideration if too few sample
1886 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1890 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1893 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1895 if (INFRA_ON(pAd) &&
1896 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1897 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1899 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1900 pAd->Mlme.ChannelQuality = 0;
1907 else if (MaxRssi < -90)
1910 NorRssi = (MaxRssi + 90) * 2;
1912 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1913 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1914 TX_WEIGHTING * (100 - TxPRR) +
1915 RX_WEIGHTING* (100 - RxPER)) / 100;
1916 if (pAd->Mlme.ChannelQuality >= 100)
1917 pAd->Mlme.ChannelQuality = 100;
1923 IN PRTMP_ADAPTER pAd,
1924 IN PMAC_TABLE_ENTRY pEntry,
1925 IN PRTMP_TX_RATE_SWITCH pTxRate)
1927 UCHAR MaxMode = MODE_OFDM;
1929 #ifdef DOT11_N_SUPPORT
1930 MaxMode = MODE_HTGREENFIELD;
1932 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1933 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1935 #endif // DOT11_N_SUPPORT //
1936 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1938 if (pTxRate->CurrMCS < MCS_AUTO)
1939 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1941 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1942 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1946 // If peer adhoc is b-only mode, we can't send 11g rate.
1947 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1948 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1951 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1953 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1954 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1955 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1957 // Patch speed error in status page
1958 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1962 if (pTxRate->Mode <= MaxMode)
1963 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1965 #ifdef DOT11_N_SUPPORT
1966 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1967 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1969 #endif // DOT11_N_SUPPORT //
1970 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1972 #ifdef DOT11_N_SUPPORT
1973 // Reexam each bandwidth's SGI support.
1974 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1976 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1977 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1978 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1979 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1982 // Turn RTS/CTS rate to 6Mbps.
1983 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1985 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1986 if (pAd->MacTab.fAnyBASession)
1988 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1992 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1995 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1997 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1998 if (pAd->MacTab.fAnyBASession)
2000 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2004 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2007 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
2009 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2012 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
2014 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2016 #endif // DOT11_N_SUPPORT //
2018 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
2019 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
2020 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
2021 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
2022 #ifdef DOT11_N_SUPPORT
2023 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
2024 pAd->WIFItestbed.bGreenField)
2025 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
2026 #endif // DOT11_N_SUPPORT //
2029 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
2033 ==========================================================================
2035 This routine calculates the acumulated TxPER of eaxh TxRate. And
2036 according to the calculation result, change CommonCfg.TxRate which
2037 is the stable TX Rate we expect the Radio situation could sustained.
2039 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
2043 IRQL = DISPATCH_LEVEL
2046 call this routine every second
2047 ==========================================================================
2049 VOID MlmeDynamicTxRateSwitching(
2050 IN PRTMP_ADAPTER pAd)
2052 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2053 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2054 ULONG TxErrorRatio = 0;
2055 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2056 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2058 UCHAR TableSize = 0;
2059 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2060 CHAR Rssi, RssiOffset = 0;
2061 TX_STA_CNT1_STRUC StaTx1;
2062 TX_STA_CNT0_STRUC TxStaCnt0;
2063 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2064 MAC_TABLE_ENTRY *pEntry;
2071 #endif // RALINK_ATE //
2073 /*if (pAd->Antenna.field.RxPath > 1)
2074 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2076 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
2079 // walk through MAC table, see if need to change AP's TX rate toward each entry
2081 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2083 pEntry = &pAd->MacTab.Content[i];
2085 // check if this entry need to switch rate automatically
2086 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2089 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2091 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2093 // Update statistic counter
2094 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2095 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2096 pAd->bUpdateBcnCntDone = TRUE;
2097 TxRetransmit = StaTx1.field.TxRetransmit;
2098 TxSuccess = StaTx1.field.TxSuccess;
2099 TxFailCount = TxStaCnt0.field.TxFailCount;
2100 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2102 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2103 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2104 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2105 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2106 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2107 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2109 // if no traffic in the past 1-sec period, don't change TX rate,
2110 // but clear all bad history. because the bad history may affect the next
2111 // Chariot throughput test
2112 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2113 pAd->RalinkCounters.OneSecTxRetryOkCount +
2114 pAd->RalinkCounters.OneSecTxFailCount;
2117 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2121 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2123 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2124 pEntry->OneSecTxRetryOkCount +
2125 pEntry->OneSecTxFailCount;
2128 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2131 CurrRateIdx = pEntry->CurrTxRateIndex;
2133 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2135 if (CurrRateIdx >= TableSize)
2137 CurrRateIdx = TableSize - 1;
2140 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2141 // So need to sync here.
2142 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2143 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2144 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2148 // Need to sync Real Tx rate and our record.
2149 // Then return for next DRS.
2150 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2151 pEntry->CurrTxRateIndex = InitTxRateIdx;
2152 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2154 // reset all OneSecTx counters
2155 RESET_ONE_SEC_TX_CNT(pEntry);
2159 // decide the next upgrade rate and downgrade rate, if any
2160 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2162 UpRateIdx = CurrRateIdx + 1;
2163 DownRateIdx = CurrRateIdx -1;
2165 else if (CurrRateIdx == 0)
2167 UpRateIdx = CurrRateIdx + 1;
2168 DownRateIdx = CurrRateIdx;
2170 else if (CurrRateIdx == (TableSize - 1))
2172 UpRateIdx = CurrRateIdx;
2173 DownRateIdx = CurrRateIdx - 1;
2176 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2178 #ifdef DOT11_N_SUPPORT
2179 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2181 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2182 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2185 #endif // DOT11_N_SUPPORT //
2187 TrainUp = pCurrTxRate->TrainUp;
2188 TrainDown = pCurrTxRate->TrainDown;
2191 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2194 // Keep the last time TxRateChangeAction status.
2196 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2201 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2202 // (criteria copied from RT2500 for Netopia case)
2204 if (TxTotalCnt <= 15)
2208 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2209 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2210 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2211 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2213 // check the existence and index of each needed MCS
2214 while (idx < pTable[0])
2216 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2218 if (pCurrTxRate->CurrMCS == MCS_0)
2222 else if (pCurrTxRate->CurrMCS == MCS_1)
2226 else if (pCurrTxRate->CurrMCS == MCS_2)
2230 else if (pCurrTxRate->CurrMCS == MCS_3)
2234 else if (pCurrTxRate->CurrMCS == MCS_4)
2238 else if (pCurrTxRate->CurrMCS == MCS_5)
2242 else if (pCurrTxRate->CurrMCS == MCS_6)
2246 //else if (pCurrTxRate->CurrMCS == MCS_7)
2247 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2251 else if (pCurrTxRate->CurrMCS == MCS_12)
2255 else if (pCurrTxRate->CurrMCS == MCS_13)
2259 else if (pCurrTxRate->CurrMCS == MCS_14)
2263 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2264 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
2268 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2272 else if (pCurrTxRate->CurrMCS == MCS_21)
2276 else if (pCurrTxRate->CurrMCS == MCS_22)
2280 else if (pCurrTxRate->CurrMCS == MCS_23)
2287 if (pAd->LatchRfRegs.Channel <= 14)
2289 if (pAd->NicConfig2.field.ExternalLNAForG)
2300 if (pAd->NicConfig2.field.ExternalLNAForA)
2309 #ifdef DOT11_N_SUPPORT
2311 if ((pTable == RateSwitchTable11BGN3S) ||
2312 (pTable == RateSwitchTable11N3S) ||
2313 (pTable == RateSwitchTable))
2314 {// N mode with 3 stream // 3*3
2315 if (MCS23 && (Rssi >= -70))
2317 else if (MCS22 && (Rssi >= -72))
2319 else if (MCS21 && (Rssi >= -76))
2321 else if (MCS20 && (Rssi >= -78))
2323 else if (MCS4 && (Rssi >= -82))
2325 else if (MCS3 && (Rssi >= -84))
2327 else if (MCS2 && (Rssi >= -86))
2329 else if (MCS1 && (Rssi >= -88))
2334 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2335 {// N mode with 2 stream
2336 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2338 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2340 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2342 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2344 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2346 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2348 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2350 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2355 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2356 {// N mode with 1 stream
2357 if (MCS7 && (Rssi > (-72+RssiOffset)))
2359 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2361 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2363 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2365 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2367 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2369 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2375 #endif // DOT11_N_SUPPORT //
2377 if (MCS7 && (Rssi > -70))
2379 else if (MCS6 && (Rssi > -74))
2381 else if (MCS5 && (Rssi > -78))
2383 else if (MCS4 && (Rssi > -82))
2385 else if (MCS4 == 0) // for B-only mode
2387 else if (MCS3 && (Rssi > -85))
2389 else if (MCS2 && (Rssi > -87))
2391 else if (MCS1 && (Rssi > -90))
2398 pEntry->CurrTxRateIndex = TxRateIdx;
2399 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2400 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2403 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2404 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2405 pEntry->fLastSecAccordingRSSI = TRUE;
2406 // reset all OneSecTx counters
2407 RESET_ONE_SEC_TX_CNT(pEntry);
2412 if (pEntry->fLastSecAccordingRSSI == TRUE)
2414 pEntry->fLastSecAccordingRSSI = FALSE;
2415 pEntry->LastSecTxRateChangeAction = 0;
2416 // reset all OneSecTx counters
2417 RESET_ONE_SEC_TX_CNT(pEntry);
2424 BOOLEAN bTrainUpDown = FALSE;
2426 pEntry->CurrTxRateStableTime ++;
2428 // downgrade TX quality if PER >= Rate-Down threshold
2429 if (TxErrorRatio >= TrainDown)
2431 bTrainUpDown = TRUE;
2432 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2434 // upgrade TX quality if PER <= Rate-Up threshold
2435 else if (TxErrorRatio <= TrainUp)
2437 bTrainUpDown = TRUE;
2438 bUpgradeQuality = TRUE;
2439 if (pEntry->TxQuality[CurrRateIdx])
2440 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2442 if (pEntry->TxRateUpPenalty)
2443 pEntry->TxRateUpPenalty --;
2444 else if (pEntry->TxQuality[UpRateIdx])
2445 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2448 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2452 // perform DRS - consider TxRate Down first, then rate up.
2453 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2455 pEntry->CurrTxRateIndex = DownRateIdx;
2457 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2459 pEntry->CurrTxRateIndex = UpRateIdx;
2464 // if rate-up happen, clear all bad history of all TX rates
2465 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2467 pEntry->CurrTxRateStableTime = 0;
2468 pEntry->TxRateUpPenalty = 0;
2469 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2470 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2471 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2474 // For TxRate fast train up
2476 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2478 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2480 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2482 bTxRateChanged = TRUE;
2484 // if rate-down happen, only clear DownRate's bad history
2485 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2487 pEntry->CurrTxRateStableTime = 0;
2488 pEntry->TxRateUpPenalty = 0; // no penalty
2489 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2490 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2491 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2494 // For TxRate fast train down
2496 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2498 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2500 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2502 bTxRateChanged = TRUE;
2506 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2507 bTxRateChanged = FALSE;
2510 pEntry->LastTxOkCount = TxSuccess;
2512 // reset all OneSecTx counters
2513 RESET_ONE_SEC_TX_CNT(pEntry);
2515 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2516 if (bTxRateChanged && pNextTxRate)
2518 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2524 ========================================================================
2525 Routine Description:
2526 Station side, Auto TxRate faster train up timer call back function.
2529 SystemSpecific1 - Not used.
2530 FunctionContext - Pointer to our Adapter context.
2531 SystemSpecific2 - Not used.
2532 SystemSpecific3 - Not used.
2537 ========================================================================
2539 VOID StaQuickResponeForRateUpExec(
2540 IN PVOID SystemSpecific1,
2541 IN PVOID FunctionContext,
2542 IN PVOID SystemSpecific2,
2543 IN PVOID SystemSpecific3)
2545 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2546 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2548 ULONG TxErrorRatio = 0;
2549 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2550 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2552 UCHAR TableSize = 0;
2553 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2554 TX_STA_CNT1_STRUC StaTx1;
2555 TX_STA_CNT0_STRUC TxStaCnt0;
2557 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2558 MAC_TABLE_ENTRY *pEntry;
2561 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2564 // walk through MAC table, see if need to change AP's TX rate toward each entry
2566 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2568 pEntry = &pAd->MacTab.Content[i];
2570 // check if this entry need to switch rate automatically
2571 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2574 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2575 if (pAd->Antenna.field.TxPath > 1)
2576 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2578 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2580 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2582 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2584 // decide the next upgrade rate and downgrade rate, if any
2585 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2587 UpRateIdx = CurrRateIdx + 1;
2588 DownRateIdx = CurrRateIdx -1;
2590 else if (CurrRateIdx == 0)
2592 UpRateIdx = CurrRateIdx + 1;
2593 DownRateIdx = CurrRateIdx;
2595 else if (CurrRateIdx == (TableSize - 1))
2597 UpRateIdx = CurrRateIdx;
2598 DownRateIdx = CurrRateIdx - 1;
2601 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2603 #ifdef DOT11_N_SUPPORT
2604 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2606 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2607 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2610 #endif // DOT11_N_SUPPORT //
2612 TrainUp = pCurrTxRate->TrainUp;
2613 TrainDown = pCurrTxRate->TrainDown;
2616 if (pAd->MacTab.Size == 1)
2618 // Update statistic counter
2619 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2620 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2622 TxRetransmit = StaTx1.field.TxRetransmit;
2623 TxSuccess = StaTx1.field.TxSuccess;
2624 TxFailCount = TxStaCnt0.field.TxFailCount;
2625 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2627 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2628 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2629 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2630 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2631 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2632 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2635 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2639 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2640 pEntry->OneSecTxRetryOkCount +
2641 pEntry->OneSecTxFailCount;
2644 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2649 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2650 // (criteria copied from RT2500 for Netopia case)
2652 if (TxTotalCnt <= 12)
2654 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2655 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2657 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2659 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2660 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2662 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2664 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2667 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2673 ULONG OneSecTxNoRetryOKRationCount;
2675 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2680 // downgrade TX quality if PER >= Rate-Down threshold
2681 if (TxErrorRatio >= TrainDown)
2683 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2686 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2688 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2690 // perform DRS - consider TxRate Down first, then rate up.
2691 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2693 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2695 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2696 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2701 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2703 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2707 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2709 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2714 // if rate-up happen, clear all bad history of all TX rates
2715 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2717 pAd->DrsCounters.TxRateUpPenalty = 0;
2718 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2719 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2721 // if rate-down happen, only clear DownRate's bad history
2722 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2724 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2726 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2727 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2728 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2732 bTxRateChanged = FALSE;
2735 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2736 if (bTxRateChanged && pNextTxRate)
2738 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2744 ==========================================================================
2746 This routine is executed periodically inside MlmePeriodicExec() after
2747 association with an AP.
2748 It checks if StaCfg.Psm is consistent with user policy (recorded in
2749 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2750 there're some conditions to consider:
2751 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2752 the time when Mibss==TRUE
2753 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2754 if outgoing traffic available in TxRing or MgmtRing.
2756 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2758 IRQL = DISPATCH_LEVEL
2760 ==========================================================================
2762 VOID MlmeCheckPsmChange(
2763 IN PRTMP_ADAPTER pAd,
2769 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2770 // 2. user wants either MAX_PSP or FAST_PSP
2771 // 3. but current psm is not in PWR_SAVE
2772 // 4. CNTL state machine is not doing SCANning
2773 // 5. no TX SUCCESS event for the past 1-sec period
2774 #ifdef NDIS51_MINIPORT
2775 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2776 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2779 PowerMode = pAd->StaCfg.WindowsPowerMode;
2781 if (INFRA_ON(pAd) &&
2782 (PowerMode != Ndis802_11PowerModeCAM) &&
2783 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2784 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
2786 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2787 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2788 MlmeSetPsmBit(pAd, PWR_SAVE);
2789 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2791 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2795 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2800 // IRQL = PASSIVE_LEVEL
2801 // IRQL = DISPATCH_LEVEL
2803 IN PRTMP_ADAPTER pAd,
2806 AUTO_RSP_CFG_STRUC csr4;
2808 pAd->StaCfg.Psm = psm;
2809 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2810 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2811 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2812 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2814 #endif // CONFIG_STA_SUPPORT //
2817 // IRQL = DISPATCH_LEVEL
2818 VOID MlmeSetTxPreamble(
2819 IN PRTMP_ADAPTER pAd,
2820 IN USHORT TxPreamble)
2822 AUTO_RSP_CFG_STRUC csr4;
2825 // Always use Long preamble before verifiation short preamble functionality works well.
2826 // Todo: remove the following line if short preamble functionality works
2828 //TxPreamble = Rt802_11PreambleLong;
2830 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2831 if (TxPreamble == Rt802_11PreambleLong)
2833 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2834 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2835 csr4.field.AutoResponderPreamble = 0;
2839 // NOTE: 1Mbps should always use long preamble
2840 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2841 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2842 csr4.field.AutoResponderPreamble = 1;
2845 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2849 ==========================================================================
2851 Update basic rate bitmap
2852 ==========================================================================
2855 VOID UpdateBasicRateBitmap(
2856 IN PRTMP_ADAPTER pAdapter)
2859 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2860 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2861 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2862 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2863 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2866 /* if A mode, always use fix BasicRateBitMap */
2867 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2868 if (pAdapter->CommonCfg.Channel > 14)
2869 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2872 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2874 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2878 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2884 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2886 if (bitmap & (1 << i))
2888 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2890 if (sup_p[j] == rate[i])
2895 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2897 if (ext_p[j] == rate[i])
2903 } /* End of UpdateBasicRateBitmap */
2905 // IRQL = PASSIVE_LEVEL
2906 // IRQL = DISPATCH_LEVEL
2907 // bLinkUp is to identify the inital link speed.
2908 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2909 VOID MlmeUpdateTxRates(
2910 IN PRTMP_ADAPTER pAd,
2915 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2916 UCHAR MinSupport = RATE_54;
2917 ULONG BasicRateBitmap = 0;
2918 UCHAR CurrBasicRate = RATE_1;
2919 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2920 PHTTRANSMIT_SETTING pHtPhy = NULL;
2921 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2922 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2923 BOOLEAN *auto_rate_cur_p;
2924 UCHAR HtMcs = MCS_AUTO;
2926 // find max desired rate
2927 UpdateBasicRateBitmap(pAd);
2930 auto_rate_cur_p = NULL;
2931 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2933 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2935 case 2: Rate = RATE_1; num++; break;
2936 case 4: Rate = RATE_2; num++; break;
2937 case 11: Rate = RATE_5_5; num++; break;
2938 case 22: Rate = RATE_11; num++; break;
2939 case 12: Rate = RATE_6; num++; break;
2940 case 18: Rate = RATE_9; num++; break;
2941 case 24: Rate = RATE_12; num++; break;
2942 case 36: Rate = RATE_18; num++; break;
2943 case 48: Rate = RATE_24; num++; break;
2944 case 72: Rate = RATE_36; num++; break;
2945 case 96: Rate = RATE_48; num++; break;
2946 case 108: Rate = RATE_54; num++; break;
2947 //default: Rate = RATE_1; break;
2949 if (MaxDesire < Rate) MaxDesire = Rate;
2952 //===========================================================================
2953 //===========================================================================
2955 #ifdef CONFIG_STA_SUPPORT
2956 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2958 pHtPhy = &pAd->StaCfg.HTPhyMode;
2959 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2960 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2962 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2963 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2965 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2966 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2967 (MaxDesire > RATE_11))
2969 MaxDesire = RATE_11;
2972 #endif // CONFIG_STA_SUPPORT //
2974 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2975 pMinHtPhy->word = 0;
2976 pMaxHtPhy->word = 0;
2979 // Auto rate switching is enabled only if more than one DESIRED RATES are
2980 // specified; otherwise disabled
2983 *auto_rate_cur_p = FALSE;
2987 *auto_rate_cur_p = TRUE;
2991 if (HtMcs != MCS_AUTO)
2993 *auto_rate_cur_p = FALSE;
2997 *auto_rate_cur_p = TRUE;
3001 #ifdef CONFIG_STA_SUPPORT
3002 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3004 pSupRate = &pAd->StaActive.SupRate[0];
3005 pExtRate = &pAd->StaActive.ExtRate[0];
3006 SupRateLen = pAd->StaActive.SupRateLen;
3007 ExtRateLen = pAd->StaActive.ExtRateLen;
3010 #endif // CONFIG_STA_SUPPORT //
3012 pSupRate = &pAd->CommonCfg.SupRate[0];
3013 pExtRate = &pAd->CommonCfg.ExtRate[0];
3014 SupRateLen = pAd->CommonCfg.SupRateLen;
3015 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3018 // find max supported rate
3019 for (i=0; i<SupRateLen; i++)
3021 switch (pSupRate[i] & 0x7f)
3023 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3024 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3025 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3026 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3027 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3028 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3029 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3030 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3031 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3032 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3033 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3034 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3035 default: Rate = RATE_1; break;
3037 if (MaxSupport < Rate) MaxSupport = Rate;
3039 if (MinSupport > Rate) MinSupport = Rate;
3042 for (i=0; i<ExtRateLen; i++)
3044 switch (pExtRate[i] & 0x7f)
3046 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3047 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3048 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3049 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3050 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3051 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3052 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3053 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3054 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3055 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3056 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3057 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3058 default: Rate = RATE_1; break;
3060 if (MaxSupport < Rate) MaxSupport = Rate;
3062 if (MinSupport > Rate) MinSupport = Rate;
3065 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3067 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3068 // the DURATION field of outgoing uniicast DATA/MGMT frame
3069 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3071 if (BasicRateBitmap & (0x01 << i))
3072 CurrBasicRate = (UCHAR)i;
3073 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3076 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3077 // max tx rate = min {max desire rate, max supported rate}
3078 if (MaxSupport < MaxDesire)
3079 pAd->CommonCfg.MaxTxRate = MaxSupport;
3081 pAd->CommonCfg.MaxTxRate = MaxDesire;
3083 pAd->CommonCfg.MinTxRate = MinSupport;
3084 if (*auto_rate_cur_p)
3087 #ifdef CONFIG_STA_SUPPORT
3088 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3089 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3090 #endif // CONFIG_STA_SUPPORT //
3091 if (bLinkUp == TRUE)
3092 pAd->CommonCfg.TxRate = RATE_24;
3094 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3097 pAd->CommonCfg.TxRate = RATE_11;
3099 pAd->CommonCfg.TxRate = RATE_24;
3101 // should never exceed MaxTxRate (consider 11B-only mode)
3102 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3103 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3105 pAd->CommonCfg.TxRateIndex = 0;
3109 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3110 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3111 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3113 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3114 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3115 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3116 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3119 if (pAd->CommonCfg.TxRate <= RATE_11)
3121 pMaxHtPhy->field.MODE = MODE_CCK;
3122 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3123 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3127 pMaxHtPhy->field.MODE = MODE_OFDM;
3128 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3129 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3130 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3132 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3135 pHtPhy->word = (pMaxHtPhy->word);
3136 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3138 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3139 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3140 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3144 switch (pAd->CommonCfg.PhyMode)
3146 case PHY_11BG_MIXED:
3148 #ifdef DOT11_N_SUPPORT
3149 case PHY_11BGN_MIXED:
3150 #endif // DOT11_N_SUPPORT //
3151 pAd->CommonCfg.MlmeRate = RATE_1;
3152 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3153 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3154 pAd->CommonCfg.RtsRate = RATE_11;
3158 #ifdef DOT11_N_SUPPORT
3159 case PHY_11AGN_MIXED:
3160 case PHY_11GN_MIXED:
3162 case PHY_11AN_MIXED:
3164 #endif // DOT11_N_SUPPORT //
3165 pAd->CommonCfg.MlmeRate = RATE_6;
3166 pAd->CommonCfg.RtsRate = RATE_6;
3167 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3168 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3170 case PHY_11ABG_MIXED:
3171 #ifdef DOT11_N_SUPPORT
3172 case PHY_11ABGN_MIXED:
3173 #endif // DOT11_N_SUPPORT //
3174 if (pAd->CommonCfg.Channel <= 14)
3176 pAd->CommonCfg.MlmeRate = RATE_1;
3177 pAd->CommonCfg.RtsRate = RATE_1;
3178 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3179 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3183 pAd->CommonCfg.MlmeRate = RATE_6;
3184 pAd->CommonCfg.RtsRate = RATE_6;
3185 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3186 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3190 pAd->CommonCfg.MlmeRate = RATE_6;
3191 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3192 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3193 pAd->CommonCfg.RtsRate = RATE_1;
3197 // Keep Basic Mlme Rate.
3199 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3200 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3201 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3203 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3204 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3207 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3208 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3209 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3210 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3211 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3212 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3213 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 ));
3216 #ifdef DOT11_N_SUPPORT
3218 ==========================================================================
3220 This function update HT Rate setting.
3221 Input Wcid value is valid for 2 case :
3222 1. it's used for Station in infra mode that copy AP rate to Mactable.
3223 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3225 IRQL = DISPATCH_LEVEL
3227 ==========================================================================
3229 VOID MlmeUpdateHtTxRates(
3230 IN PRTMP_ADAPTER pAd,
3233 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3235 RT_HT_CAPABILITY *pRtHtCap = NULL;
3236 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3239 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3240 PHTTRANSMIT_SETTING pHtPhy = NULL;
3241 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3242 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3243 BOOLEAN *auto_rate_cur_p;
3245 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3247 auto_rate_cur_p = NULL;
3249 #ifdef CONFIG_STA_SUPPORT
3250 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3252 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3253 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3254 pHtPhy = &pAd->StaCfg.HTPhyMode;
3255 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3256 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3258 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3260 #endif // CONFIG_STA_SUPPORT //
3262 #ifdef CONFIG_STA_SUPPORT
3263 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3265 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3268 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3269 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3270 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3271 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3272 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3273 pMaxHtPhy->field.STBC = STBC_USE;
3275 pMaxHtPhy->field.STBC = STBC_NONE;
3278 #endif // CONFIG_STA_SUPPORT //
3280 if (pDesireHtPhy->bHtEnable == FALSE)
3283 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3284 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3285 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3286 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3287 pMaxHtPhy->field.STBC = STBC_USE;
3289 pMaxHtPhy->field.STBC = STBC_NONE;
3292 // Decide MAX ht rate.
3293 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3294 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3296 pMaxHtPhy->field.MODE = MODE_HTMIX;
3298 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3299 pMaxHtPhy->field.BW = BW_40;
3301 pMaxHtPhy->field.BW = BW_20;
3303 if (pMaxHtPhy->field.BW == BW_20)
3304 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3306 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3308 for (i=23; i>=0; i--) // 3*3
3311 bitmask = (1<<(i-(j*8)));
3313 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3315 pMaxHtPhy->field.MCS = i;
3323 // Copy MIN ht rate. rt2860???
3324 pMinHtPhy->field.BW = BW_20;
3325 pMinHtPhy->field.MCS = 0;
3326 pMinHtPhy->field.STBC = 0;
3327 pMinHtPhy->field.ShortGI = 0;
3328 //If STA assigns fixed rate. update to fixed here.
3329 #ifdef CONFIG_STA_SUPPORT
3330 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3332 if (pDesireHtPhy->MCSSet[4] != 0)
3334 pMaxHtPhy->field.MCS = 32;
3335 pMinHtPhy->field.MCS = 32;
3336 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3339 for (i=23; (CHAR)i >= 0; i--) // 3*3
3342 bitmask = (1<<(i-(j*8)));
3343 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3345 pMaxHtPhy->field.MCS = i;
3346 pMinHtPhy->field.MCS = i;
3353 #endif // CONFIG_STA_SUPPORT //
3357 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3358 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3359 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3360 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3361 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3363 // use default now. rt2860
3364 if (pDesireHtPhy->MCSSet[0] != 0xff)
3365 *auto_rate_cur_p = FALSE;
3367 *auto_rate_cur_p = TRUE;
3369 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3370 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3371 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3372 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3374 #endif // DOT11_N_SUPPORT //
3376 // IRQL = DISPATCH_LEVEL
3378 IN PRTMP_ADAPTER pAd)
3380 RT28XX_MLME_RADIO_OFF(pAd);
3383 // IRQL = DISPATCH_LEVEL
3385 IN PRTMP_ADAPTER pAd)
3387 RT28XX_MLME_RADIO_ON(pAd);
3390 // ===========================================================================================
3392 // ===========================================================================================
3395 /*! \brief initialize BSS table
3396 * \param p_tab pointer to the table
3401 IRQL = PASSIVE_LEVEL
3402 IRQL = DISPATCH_LEVEL
3411 Tab->BssOverlapNr = 0;
3412 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3414 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3415 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3419 #ifdef DOT11_N_SUPPORT
3421 IN PRTMP_ADAPTER pAd,
3426 Tab->numAsOriginator = 0;
3427 Tab->numAsRecipient = 0;
3428 NdisAllocateSpinLock(&pAd->BATabLock);
3429 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3431 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3432 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3434 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3436 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3439 #endif // DOT11_N_SUPPORT //
3441 /*! \brief search the BSS table by SSID
3442 * \param p_tab pointer to the bss table
3443 * \param ssid SSID string
3444 * \return index of the table, BSS_NOT_FOUND if not in the table
3447 * \note search by sequential search
3449 IRQL = DISPATCH_LEVEL
3452 ULONG BssTableSearch(
3459 for (i = 0; i < Tab->BssNr; i++)
3462 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3463 // We should distinguish this case.
3465 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3466 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3467 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3472 return (ULONG)BSS_NOT_FOUND;
3475 ULONG BssSsidTableSearch(
3484 for (i = 0; i < Tab->BssNr; i++)
3487 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3488 // We should distinguish this case.
3490 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3491 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3492 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3493 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3498 return (ULONG)BSS_NOT_FOUND;
3501 ULONG BssTableSearchWithSSID(
3510 for (i = 0; i < Tab->BssNr; i++)
3512 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3513 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3514 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3515 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3516 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3517 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3522 return (ULONG)BSS_NOT_FOUND;
3525 // IRQL = DISPATCH_LEVEL
3526 VOID BssTableDeleteEntry(
3527 IN OUT BSS_TABLE *Tab,
3533 for (i = 0; i < Tab->BssNr; i++)
3535 if ((Tab->BssEntry[i].Channel == Channel) &&
3536 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3538 for (j = i; j < Tab->BssNr - 1; j++)
3540 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3542 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3549 #ifdef DOT11_N_SUPPORT
3551 ========================================================================
3552 Routine Description:
3553 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3556 // IRQL = DISPATCH_LEVEL
3557 ========================================================================
3559 VOID BATableDeleteORIEntry(
3560 IN OUT PRTMP_ADAPTER pAd,
3561 IN BA_ORI_ENTRY *pBAORIEntry)
3564 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3566 NdisAcquireSpinLock(&pAd->BATabLock);
3567 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3569 pAd->BATable.numAsOriginator -= 1;
3570 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3571 // Erase Bitmap flag.
3573 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3574 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3575 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3576 pBAORIEntry->Token = 1;
3577 // Not clear Sequence here.
3578 NdisReleaseSpinLock(&pAd->BATabLock);
3581 #endif // DOT11_N_SUPPORT //
3589 IRQL = DISPATCH_LEVEL
3593 IN PRTMP_ADAPTER pAd,
3594 OUT BSS_ENTRY *pBss,
3599 IN USHORT BeaconPeriod,
3600 IN PCF_PARM pCfParm,
3602 IN USHORT CapabilityInfo,
3604 IN UCHAR SupRateLen,
3606 IN UCHAR ExtRateLen,
3607 IN HT_CAPABILITY_IE *pHtCapability,
3608 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3609 IN UCHAR HtCapabilityLen,
3610 IN UCHAR AddHtInfoLen,
3611 IN UCHAR NewExtChanOffset,
3614 IN LARGE_INTEGER TimeStamp,
3616 IN PEDCA_PARM pEdcaParm,
3617 IN PQOS_CAPABILITY_PARM pQosCapability,
3618 IN PQBSS_LOAD_PARM pQbssLoad,
3619 IN USHORT LengthVIE,
3620 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3622 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3623 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3627 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3628 // Or send beacon /probe response with SSID len matching real SSID length,
3629 // but SSID is all zero. such as "00-00-00-00" with length 4.
3630 // We have to prevent this case overwrite correct table
3631 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3633 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3634 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3635 pBss->SsidLen = SsidLen;
3641 pBss->BssType = BssType;
3642 pBss->BeaconPeriod = BeaconPeriod;
3643 if (BssType == BSS_INFRA)
3645 if (pCfParm->bValid)
3647 pBss->CfpCount = pCfParm->CfpCount;
3648 pBss->CfpPeriod = pCfParm->CfpPeriod;
3649 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3650 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3655 pBss->AtimWin = AtimWin;
3658 pBss->CapabilityInfo = CapabilityInfo;
3659 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3660 // Combine with AuthMode, they will decide the connection methods.
3661 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3662 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3663 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3664 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3666 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3667 pBss->SupRateLen = SupRateLen;
3668 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3669 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3670 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3671 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3672 pBss->NewExtChanOffset = NewExtChanOffset;
3673 pBss->ExtRateLen = ExtRateLen;
3674 pBss->Channel = Channel;
3675 pBss->CentralChannel = Channel;
3677 // Update CkipFlag. if not exists, the value is 0x0
3678 pBss->CkipFlag = CkipFlag;
3680 // New for microsoft Fixed IEs
3681 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3682 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3683 pBss->FixIEs.Capabilities = CapabilityInfo;
3685 // New for microsoft Variable IEs
3688 pBss->VarIELen = LengthVIE;
3689 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3696 pBss->AddHtInfoLen = 0;
3697 pBss->HtCapabilityLen = 0;
3698 #ifdef DOT11_N_SUPPORT
3699 if (HtCapabilityLen> 0)
3701 pBss->HtCapabilityLen = HtCapabilityLen;
3702 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3703 if (AddHtInfoLen > 0)
3705 pBss->AddHtInfoLen = AddHtInfoLen;
3706 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3708 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3710 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3712 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3714 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3718 #endif // DOT11_N_SUPPORT //
3720 BssCipherParse(pBss);
3724 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3726 pBss->EdcaParm.bValid = FALSE;
3728 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3730 pBss->QosCapability.bValid = FALSE;
3732 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3734 pBss->QbssLoad.bValid = FALSE;
3736 #ifdef CONFIG_STA_SUPPORT
3737 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3743 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3744 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3745 #ifdef EXT_BUILD_CHANNEL_LIST
3746 NdisZeroMemory(&pBss->CountryString[0], 3);
3747 pBss->bHasCountryIE = FALSE;
3748 #endif // EXT_BUILD_CHANNEL_LIST //
3749 pEid = (PEID_STRUCT) pVIE;
3750 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3755 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3757 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3759 pBss->WpaIE.IELen = 0;
3762 pBss->WpaIE.IELen = pEid->Len + 2;
3763 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3767 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3769 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3771 pBss->RsnIE.IELen = 0;
3774 pBss->RsnIE.IELen = pEid->Len + 2;
3775 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3778 #ifdef EXT_BUILD_CHANNEL_LIST
3780 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3781 pBss->bHasCountryIE = TRUE;
3783 #endif // EXT_BUILD_CHANNEL_LIST //
3785 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3786 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3789 #endif // CONFIG_STA_SUPPORT //
3793 * \brief insert an entry into the bss table
3794 * \param p_tab The BSS table
3795 * \param Bssid BSSID
3797 * \param ssid_len Length of SSID
3799 * \param beacon_period
3806 * \param channel_idx
3810 * \note If SSID is identical, the old entry will be replaced by the new one
3812 IRQL = DISPATCH_LEVEL
3815 ULONG BssTableSetEntry(
3816 IN PRTMP_ADAPTER pAd,
3822 IN USHORT BeaconPeriod,
3825 IN USHORT CapabilityInfo,
3827 IN UCHAR SupRateLen,
3829 IN UCHAR ExtRateLen,
3830 IN HT_CAPABILITY_IE *pHtCapability,
3831 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3832 IN UCHAR HtCapabilityLen,
3833 IN UCHAR AddHtInfoLen,
3834 IN UCHAR NewExtChanOffset,
3837 IN LARGE_INTEGER TimeStamp,
3839 IN PEDCA_PARM pEdcaParm,
3840 IN PQOS_CAPABILITY_PARM pQosCapability,
3841 IN PQBSS_LOAD_PARM pQbssLoad,
3842 IN USHORT LengthVIE,
3843 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3847 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3848 if (Idx == BSS_NOT_FOUND)
3850 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3853 // It may happen when BSS Table was full.
3854 // The desired AP will not be added into BSS Table
3855 // In this case, if we found the desired AP then overwrite BSS Table.
3857 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3859 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3860 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3862 Idx = Tab->BssOverlapNr;
3863 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3864 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3865 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3866 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3872 return BSS_NOT_FOUND;
3876 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3877 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3878 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3883 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3884 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3885 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3891 #ifdef CONFIG_STA_SUPPORT
3892 #ifdef DOT11_N_SUPPORT
3893 #ifdef DOT11N_DRAFT3
3895 IN PRTMP_ADAPTER pAd)
3899 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3900 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3902 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3903 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3906 ULONG TriEventTableSetEntry(
3907 IN PRTMP_ADAPTER pAd,
3908 OUT TRIGGER_EVENT_TAB *Tab,
3910 IN HT_CAPABILITY_IE *pHtCapability,
3911 IN UCHAR HtCapabilityLen,
3916 if (HtCapabilityLen == 0)
3918 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3920 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3921 Tab->EventA[Tab->EventANo].bValid = TRUE;
3922 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3923 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3926 // Beacon has Regulatory class IE. So use beacon's
3927 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3931 // Use Station's Regulatory class instead.
3932 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3934 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3936 Tab->EventA[Tab->EventANo].RegClass = 32;
3938 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3939 Tab->EventA[Tab->EventANo].RegClass = 33;
3942 Tab->EventA[Tab->EventANo].RegClass = ??;
3949 else if (pHtCapability->HtCapInfo.Intolerant40)
3951 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3957 ========================================================================
3958 Routine Description:
3959 Trigger Event table Maintainence called once every second.
3962 // IRQL = DISPATCH_LEVEL
3963 ========================================================================
3965 VOID TriEventCounterMaintenance(
3966 IN PRTMP_ADAPTER pAd)
3969 BOOLEAN bNotify = FALSE;
3970 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3972 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3974 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3975 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3977 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3978 pAd->CommonCfg.TriggerEventTab.EventANo --;
3979 // Need to send 20/40 Coexistence Notify frame if has status change.
3984 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
3986 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
3987 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
3991 if (bNotify == TRUE)
3992 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
3994 #endif // DOT11N_DRAFT3 //
3995 #endif // DOT11_N_SUPPORT //
3997 // IRQL = DISPATCH_LEVEL
3998 VOID BssTableSsidSort(
3999 IN PRTMP_ADAPTER pAd,
4000 OUT BSS_TABLE *OutTab,
4005 BssTableInit(OutTab);
4007 for (i = 0; i < pAd->ScanTab.BssNr; i++)
4009 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
4010 BOOLEAN bIsHiddenApIncluded = FALSE;
4012 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
4013 (pAd->MlmeAux.Channel > 14) &&
4014 RadarChannelCheck(pAd, pInBss->Channel))
4015 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
4016 || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
4017 #endif // CARRIER_DETECTION_SUPPORT //
4021 bIsHiddenApIncluded = TRUE;
4024 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
4025 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
4027 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4030 #ifdef EXT_BUILD_CHANNEL_LIST
4031 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
4032 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
4033 (pInBss->bHasCountryIE == FALSE))
4035 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
4038 #endif // EXT_BUILD_CHANNEL_LIST //
4040 #ifdef DOT11_N_SUPPORT
4041 // 2.4G/5G N only mode
4042 if ((pInBss->HtCapabilityLen == 0) &&
4043 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4045 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4048 #endif // DOT11_N_SUPPORT //
4051 // Check the Authmode first
4052 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4054 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4055 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4059 // Check cipher suite, AP must have more secured cipher than station setting
4060 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4062 // If it's not mixed mode, we should only let BSS pass with the same encryption
4063 if (pInBss->WPA.bMixMode == FALSE)
4064 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4067 // check group cipher
4068 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4071 // check pairwise cipher, skip if none matched
4072 // If profile set to AES, let it pass without question.
4073 // If profile set to TKIP, we must find one mateched
4074 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4075 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4076 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4079 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4081 // If it's not mixed mode, we should only let BSS pass with the same encryption
4082 if (pInBss->WPA2.bMixMode == FALSE)
4083 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4086 // check group cipher
4087 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4090 // check pairwise cipher, skip if none matched
4091 // If profile set to AES, let it pass without question.
4092 // If profile set to TKIP, we must find one mateched
4093 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4094 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4095 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4099 // Bss Type matched, SSID matched.
4100 // We will check wepstatus for qualification Bss
4101 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4103 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4105 // For the SESv2 case, we will not qualify WepStatus.
4111 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4112 // It definitely will fail. So, skip it.
4113 // CCX also require not even try to connect it!!
4117 #ifdef DOT11_N_SUPPORT
4118 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4119 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4120 if ((pInBss->CentralChannel != pInBss->Channel) &&
4121 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4123 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4125 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4127 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4131 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4137 #endif // DOT11_N_SUPPORT //
4139 // copy matching BSS from InTab to OutTab
4140 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4144 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4146 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4149 #ifdef DOT11_N_SUPPORT
4150 // 2.4G/5G N only mode
4151 if ((pInBss->HtCapabilityLen == 0) &&
4152 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4154 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4157 #endif // DOT11_N_SUPPORT //
4160 // Check the Authmode first
4161 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4163 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4164 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4168 // Check cipher suite, AP must have more secured cipher than station setting
4169 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4171 // If it's not mixed mode, we should only let BSS pass with the same encryption
4172 if (pInBss->WPA.bMixMode == FALSE)
4173 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4176 // check group cipher
4177 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4180 // check pairwise cipher, skip if none matched
4181 // If profile set to AES, let it pass without question.
4182 // If profile set to TKIP, we must find one mateched
4183 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4184 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4185 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4188 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4190 // If it's not mixed mode, we should only let BSS pass with the same encryption
4191 if (pInBss->WPA2.bMixMode == FALSE)
4192 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4195 // check group cipher
4196 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4199 // check pairwise cipher, skip if none matched
4200 // If profile set to AES, let it pass without question.
4201 // If profile set to TKIP, we must find one mateched
4202 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4203 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4204 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4208 // Bss Type matched, SSID matched.
4209 // We will check wepstatus for qualification Bss
4210 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4213 #ifdef DOT11_N_SUPPORT
4214 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4215 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4216 if ((pInBss->CentralChannel != pInBss->Channel) &&
4217 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4219 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4221 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4223 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4226 #endif // DOT11_N_SUPPORT //
4228 // copy matching BSS from InTab to OutTab
4229 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4234 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4238 BssTableSortByRssi(OutTab);
4242 // IRQL = DISPATCH_LEVEL
4243 VOID BssTableSortByRssi(
4244 IN OUT BSS_TABLE *OutTab)
4249 for (i = 0; i < OutTab->BssNr - 1; i++)
4251 for (j = i+1; j < OutTab->BssNr; j++)
4253 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4255 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4256 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4257 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4262 #endif // CONFIG_STA_SUPPORT //
4265 VOID BssCipherParse(
4266 IN OUT PBSS_ENTRY pBss)
4270 PRSN_IE_HEADER_STRUCT pRsnHeader;
4271 PCIPHER_SUITE_STRUCT pCipher;
4272 PAKM_SUITE_STRUCT pAKM;
4275 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4278 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4282 pBss->WepStatus = Ndis802_11WEPEnabled;
4286 pBss->WepStatus = Ndis802_11WEPDisabled;
4288 // Set default to disable & open authentication before parsing variable IE
4289 pBss->AuthMode = Ndis802_11AuthModeOpen;
4290 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4293 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4294 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4295 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4296 pBss->WPA.RsnCapability = 0;
4297 pBss->WPA.bMixMode = FALSE;
4299 // Init WPA2 setting
4300 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4301 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4302 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4303 pBss->WPA2.RsnCapability = 0;
4304 pBss->WPA2.bMixMode = FALSE;
4307 Length = (INT) pBss->VarIELen;
4311 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4312 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4313 pEid = (PEID_STRUCT) pTmp;
4317 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4318 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4324 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4325 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4326 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4327 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4330 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4331 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4332 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4335 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4336 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4337 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4343 // if Cisco IE_WPA, break
4346 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4351 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4353 // if unsupported vendor specific IE
4356 // Skip OUI, version, and multicast suite
4357 // This part should be improved in the future when AP supported multiple cipher suite.
4358 // For now, it's OK since almost all APs have fixed cipher suite supported.
4359 // pTmp = (PUCHAR) pEid->Octet;
4362 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4370 // Parse group cipher
4374 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4375 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4378 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4381 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4386 // number of unicast suite
4389 // skip all unicast cipher suites
4390 //Count = *(PUSHORT) pTmp;
4391 Count = (pTmp[1]<<8) + pTmp[0];
4392 pTmp += sizeof(USHORT);
4394 // Parsing all unicast cipher suite
4399 TmpCipher = Ndis802_11WEPDisabled;
4403 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4404 TmpCipher = Ndis802_11Encryption1Enabled;
4407 TmpCipher = Ndis802_11Encryption2Enabled;
4410 TmpCipher = Ndis802_11Encryption3Enabled;
4415 if (TmpCipher > pBss->WPA.PairCipher)
4417 // Move the lower cipher suite to PairCipherAux
4418 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4419 pBss->WPA.PairCipher = TmpCipher;
4423 pBss->WPA.PairCipherAux = TmpCipher;
4429 // 4. get AKM suite counts
4430 //Count = *(PUSHORT) pTmp;
4431 Count = (pTmp[1]<<8) + pTmp[0];
4432 pTmp += sizeof(USHORT);
4438 // Set AP support WPA mode
4439 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4440 pBss->AuthMode = Ndis802_11AuthModeWPA;
4442 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4445 // Set AP support WPA mode
4446 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4447 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4449 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4456 // Fixed for WPA-None
4457 if (pBss->BssType == BSS_ADHOC)
4459 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4460 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4461 pBss->WepStatus = pBss->WPA.GroupCipher;
4462 // Patched bugs for old driver
4463 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4464 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4467 pBss->WepStatus = pBss->WPA.PairCipher;
4469 // Check the Pair & Group, if different, turn on mixed mode flag
4470 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4471 pBss->WPA.bMixMode = TRUE;
4476 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4478 // 0. Version must be 1
4479 if (le2cpu16(pRsnHeader->Version) != 1)
4481 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4483 // 1. Check group cipher
4484 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4485 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4488 // Parse group cipher
4489 switch (pCipher->Type)
4492 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4493 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4496 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4499 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4504 // set to correct offset for next parsing
4505 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4507 // 2. Get pairwise cipher counts
4508 //Count = *(PUSHORT) pTmp;
4509 Count = (pTmp[1]<<8) + pTmp[0];
4510 pTmp += sizeof(USHORT);
4512 // 3. Get pairwise cipher
4513 // Parsing all unicast cipher suite
4517 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4518 TmpCipher = Ndis802_11WEPDisabled;
4519 switch (pCipher->Type)
4522 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4523 TmpCipher = Ndis802_11Encryption1Enabled;
4526 TmpCipher = Ndis802_11Encryption2Enabled;
4529 TmpCipher = Ndis802_11Encryption3Enabled;
4534 if (TmpCipher > pBss->WPA2.PairCipher)
4536 // Move the lower cipher suite to PairCipherAux
4537 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4538 pBss->WPA2.PairCipher = TmpCipher;
4542 pBss->WPA2.PairCipherAux = TmpCipher;
4544 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4548 // 4. get AKM suite counts
4549 //Count = *(PUSHORT) pTmp;
4550 Count = (pTmp[1]<<8) + pTmp[0];
4551 pTmp += sizeof(USHORT);
4553 // 5. Get AKM ciphers
4554 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4555 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4561 // Set AP support WPA mode
4562 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4563 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4565 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4568 // Set AP support WPA mode
4569 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4570 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4572 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4577 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4579 // Fixed for WPA-None
4580 if (pBss->BssType == BSS_ADHOC)
4582 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4583 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4584 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4585 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4586 pBss->WepStatus = pBss->WPA.GroupCipher;
4587 // Patched bugs for old driver
4588 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4589 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4591 pBss->WepStatus = pBss->WPA2.PairCipher;
4593 // 6. Get RSN capability
4594 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4595 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4596 pTmp += sizeof(USHORT);
4598 // Check the Pair & Group, if different, turn on mixed mode flag
4599 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4600 pBss->WPA2.bMixMode = TRUE;
4606 Length -= (pEid->Len + 2);
4610 // ===========================================================================================
4612 // ===========================================================================================
4614 /*! \brief generates a random mac address value for IBSS BSSID
4615 * \param Addr the bssid location
4620 VOID MacAddrRandomBssid(
4621 IN PRTMP_ADAPTER pAd,
4626 for (i = 0; i < MAC_ADDR_LEN; i++)
4628 pAddr[i] = RandomByte(pAd);
4631 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4634 /*! \brief init the management mac frame header
4635 * \param p_hdr mac header
4636 * \param subtype subtype of the frame
4637 * \param p_ds destination address, don't care if it is a broadcast address
4639 * \pre the station has the following information in the pAd->StaCfg
4643 * \note this function initializes the following field
4645 IRQL = PASSIVE_LEVEL
4646 IRQL = DISPATCH_LEVEL
4649 VOID MgtMacHeaderInit(
4650 IN PRTMP_ADAPTER pAd,
4651 IN OUT PHEADER_802_11 pHdr80211,
4657 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4659 pHdr80211->FC.Type = BTYPE_MGMT;
4660 pHdr80211->FC.SubType = SubType;
4661 pHdr80211->FC.ToDs = ToDs;
4662 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4663 #ifdef CONFIG_STA_SUPPORT
4664 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4665 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4666 #endif // CONFIG_STA_SUPPORT //
4667 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4670 // ===========================================================================================
4672 // ===========================================================================================
4674 /*!***************************************************************************
4675 * This routine build an outgoing frame, and fill all information specified
4676 * in argument list to the frame body. The actual frame size is the summation
4679 * Buffer - pointer to a pre-allocated memory segment
4680 * args - a list of <int arg_size, arg> pairs.
4681 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4682 * function will FAIL!!!
4684 * Size of the buffer
4686 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4688 IRQL = PASSIVE_LEVEL
4689 IRQL = DISPATCH_LEVEL
4691 ****************************************************************************/
4692 ULONG MakeOutgoingFrame(
4694 OUT ULONG *FrameLen, ...)
4701 // calculates the total length
4703 va_start(Args, FrameLen);
4706 leng = va_arg(Args, int);
4707 if (leng == END_OF_ARGS)
4711 p = va_arg(Args, PVOID);
4712 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4713 TotLeng = TotLeng + leng;
4716 va_end(Args); /* clean up */
4717 *FrameLen = TotLeng;
4721 // ===========================================================================================
4723 // ===========================================================================================
4725 /*! \brief Initialize The MLME Queue, used by MLME Functions
4726 * \param *Queue The MLME Queue
4727 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4730 * \note Because this is done only once (at the init stage), no need to be locked
4732 IRQL = PASSIVE_LEVEL
4735 NDIS_STATUS MlmeQueueInit(
4736 IN MLME_QUEUE *Queue)
4740 NdisAllocateSpinLock(&Queue->Lock);
4746 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4748 Queue->Entry[i].Occupied = FALSE;
4749 Queue->Entry[i].MsgLen = 0;
4750 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4753 return NDIS_STATUS_SUCCESS;
4756 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4757 * \param *Queue The MLME Queue
4758 * \param Machine The State Machine Id
4759 * \param MsgType The Message Type
4760 * \param MsgLen The Message length
4761 * \param *Msg The message pointer
4762 * \return TRUE if enqueue is successful, FALSE if the queue is full
4765 * \note The message has to be initialized
4767 IRQL = PASSIVE_LEVEL
4768 IRQL = DISPATCH_LEVEL
4771 BOOLEAN MlmeEnqueue(
4772 IN PRTMP_ADAPTER pAd,
4779 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4781 // Do nothing if the driver is starting halt state.
4782 // This might happen when timer already been fired before cancel timer with mlmehalt
4783 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4786 // First check the size, it MUST not exceed the mlme queue size
4787 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4789 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4793 if (MlmeQueueFull(Queue))
4798 NdisAcquireSpinLock(&(Queue->Lock));
4802 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4807 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4808 Queue->Entry[Tail].Occupied = TRUE;
4809 Queue->Entry[Tail].Machine = Machine;
4810 Queue->Entry[Tail].MsgType = MsgType;
4811 Queue->Entry[Tail].MsgLen = MsgLen;
4815 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4818 NdisReleaseSpinLock(&(Queue->Lock));
4822 /*! \brief This function is used when Recv gets a MLME message
4823 * \param *Queue The MLME Queue
4824 * \param TimeStampHigh The upper 32 bit of timestamp
4825 * \param TimeStampLow The lower 32 bit of timestamp
4826 * \param Rssi The receiving RSSI strength
4827 * \param MsgLen The length of the message
4828 * \param *Msg The message pointer
4829 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4833 IRQL = DISPATCH_LEVEL
4836 BOOLEAN MlmeEnqueueForRecv(
4837 IN PRTMP_ADAPTER pAd,
4839 IN ULONG TimeStampHigh,
4840 IN ULONG TimeStampLow,
4849 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4851 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4854 /* Nothing to do in ATE mode */
4857 #endif // RALINK_ATE //
4859 // Do nothing if the driver is starting halt state.
4860 // This might happen when timer already been fired before cancel timer with mlmehalt
4861 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4863 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4867 // First check the size, it MUST not exceed the mlme queue size
4868 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4870 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4874 if (MlmeQueueFull(Queue))
4879 #ifdef CONFIG_STA_SUPPORT
4880 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4882 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4884 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4888 #endif // CONFIG_STA_SUPPORT //
4890 // OK, we got all the informations, it is time to put things into queue
4891 NdisAcquireSpinLock(&(Queue->Lock));
4895 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4899 Queue->Entry[Tail].Occupied = TRUE;
4900 Queue->Entry[Tail].Machine = Machine;
4901 Queue->Entry[Tail].MsgType = MsgType;
4902 Queue->Entry[Tail].MsgLen = MsgLen;
4903 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4904 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4905 Queue->Entry[Tail].Rssi0 = Rssi0;
4906 Queue->Entry[Tail].Rssi1 = Rssi1;
4907 Queue->Entry[Tail].Rssi2 = Rssi2;
4908 Queue->Entry[Tail].Signal = Signal;
4909 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4911 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4915 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4918 NdisReleaseSpinLock(&(Queue->Lock));
4920 RT28XX_MLME_HANDLER(pAd);
4926 /*! \brief Dequeue a message from the MLME Queue
4927 * \param *Queue The MLME Queue
4928 * \param *Elem The message dequeued from MLME Queue
4929 * \return TRUE if the Elem contains something, FALSE otherwise
4933 IRQL = DISPATCH_LEVEL
4936 BOOLEAN MlmeDequeue(
4937 IN MLME_QUEUE *Queue,
4938 OUT MLME_QUEUE_ELEM **Elem)
4940 NdisAcquireSpinLock(&(Queue->Lock));
4941 *Elem = &(Queue->Entry[Queue->Head]);
4944 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4948 NdisReleaseSpinLock(&(Queue->Lock));
4952 // IRQL = DISPATCH_LEVEL
4953 VOID MlmeRestartStateMachine(
4954 IN PRTMP_ADAPTER pAd)
4957 MLME_QUEUE_ELEM *Elem = NULL;
4959 #ifdef CONFIG_STA_SUPPORT
4961 #endif // CONFIG_STA_SUPPORT //
4963 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4966 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4967 if(pAd->Mlme.bRunning)
4969 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4974 pAd->Mlme.bRunning = TRUE;
4976 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4978 // Remove all Mlme queues elements
4979 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4981 //From message type, determine which state machine I should drive
4982 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4984 // free MLME element
4985 Elem->Occupied = FALSE;
4990 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4995 #ifdef CONFIG_STA_SUPPORT
4996 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4998 #ifdef QOS_DLS_SUPPORT
5000 #endif // QOS_DLS_SUPPORT //
5001 // Cancel all timer events
5002 // Be careful to cancel new added timer
5003 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
5004 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
5005 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
5006 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
5007 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
5008 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
5010 #ifdef QOS_DLS_SUPPORT
5011 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
5013 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
5015 #endif // QOS_DLS_SUPPORT //
5017 #endif // CONFIG_STA_SUPPORT //
5019 // Change back to original channel in case of doing scan
5020 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
5021 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
5023 // Resume MSDU which is turned off durning scan
5024 RTMPResumeMsduTransmission(pAd);
5026 #ifdef CONFIG_STA_SUPPORT
5027 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5029 // Set all state machines back IDLE
5030 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
5031 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
5032 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
5033 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
5034 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
5035 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
5036 #ifdef QOS_DLS_SUPPORT
5037 pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
5038 #endif // QOS_DLS_SUPPORT //
5040 #endif // CONFIG_STA_SUPPORT //
5043 // Remove running state
5044 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
5045 pAd->Mlme.bRunning = FALSE;
5046 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
5050 /*! \brief test if the MLME Queue is empty
5051 * \param *Queue The MLME Queue
5052 * \return TRUE if the Queue is empty, FALSE otherwise
5056 IRQL = DISPATCH_LEVEL
5059 BOOLEAN MlmeQueueEmpty(
5060 IN MLME_QUEUE *Queue)
5064 NdisAcquireSpinLock(&(Queue->Lock));
5065 Ans = (Queue->Num == 0);
5066 NdisReleaseSpinLock(&(Queue->Lock));
5071 /*! \brief test if the MLME Queue is full
5072 * \param *Queue The MLME Queue
5073 * \return TRUE if the Queue is empty, FALSE otherwise
5077 IRQL = PASSIVE_LEVEL
5078 IRQL = DISPATCH_LEVEL
5081 BOOLEAN MlmeQueueFull(
5082 IN MLME_QUEUE *Queue)
5086 NdisAcquireSpinLock(&(Queue->Lock));
5087 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5088 NdisReleaseSpinLock(&(Queue->Lock));
5093 /*! \brief The destructor of MLME Queue
5098 * \note Clear Mlme Queue, Set Queue->Num to Zero.
5100 IRQL = PASSIVE_LEVEL
5103 VOID MlmeQueueDestroy(
5104 IN MLME_QUEUE *pQueue)
5106 NdisAcquireSpinLock(&(pQueue->Lock));
5110 NdisReleaseSpinLock(&(pQueue->Lock));
5111 NdisFreeSpinLock(&(pQueue->Lock));
5114 /*! \brief To substitute the message type if the message is coming from external
5115 * \param pFrame The frame received
5116 * \param *Machine The state machine
5117 * \param *MsgType the message type for the state machine
5118 * \return TRUE if the substitution is successful, FALSE otherwise
5122 IRQL = DISPATCH_LEVEL
5125 #ifdef CONFIG_STA_SUPPORT
5126 BOOLEAN MsgTypeSubst(
5127 IN PRTMP_ADAPTER pAd,
5128 IN PFRAME_802_11 pFrame,
5136 // Pointer to start of data frames including SNAP header
5137 pData = (PUCHAR) pFrame + LENGTH_802_11;
5139 // The only data type will pass to this function is EAPOL frame
5140 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5142 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5144 // Cisco Aironet SNAP header
5145 *Machine = AIRONET_STATE_MACHINE;
5146 *MsgType = MT2_AIRONET_MSG;
5150 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5153 *Machine = LEAP_STATE_MACHINE;
5154 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5155 return (LeapMsgTypeSubst(EAPType, MsgType));
5158 #endif // LEAP_SUPPORT //
5160 *Machine = WPA_PSK_STATE_MACHINE;
5161 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5162 return(WpaMsgTypeSubst(EAPType, MsgType));
5166 switch (pFrame->Hdr.FC.SubType)
5168 case SUBTYPE_ASSOC_REQ:
5169 *Machine = ASSOC_STATE_MACHINE;
5170 *MsgType = MT2_PEER_ASSOC_REQ;
5172 case SUBTYPE_ASSOC_RSP:
5173 *Machine = ASSOC_STATE_MACHINE;
5174 *MsgType = MT2_PEER_ASSOC_RSP;
5176 case SUBTYPE_REASSOC_REQ:
5177 *Machine = ASSOC_STATE_MACHINE;
5178 *MsgType = MT2_PEER_REASSOC_REQ;
5180 case SUBTYPE_REASSOC_RSP:
5181 *Machine = ASSOC_STATE_MACHINE;
5182 *MsgType = MT2_PEER_REASSOC_RSP;
5184 case SUBTYPE_PROBE_REQ:
5185 *Machine = SYNC_STATE_MACHINE;
5186 *MsgType = MT2_PEER_PROBE_REQ;
5188 case SUBTYPE_PROBE_RSP:
5189 *Machine = SYNC_STATE_MACHINE;
5190 *MsgType = MT2_PEER_PROBE_RSP;
5192 case SUBTYPE_BEACON:
5193 *Machine = SYNC_STATE_MACHINE;
5194 *MsgType = MT2_PEER_BEACON;
5197 *Machine = SYNC_STATE_MACHINE;
5198 *MsgType = MT2_PEER_ATIM;
5200 case SUBTYPE_DISASSOC:
5201 *Machine = ASSOC_STATE_MACHINE;
5202 *MsgType = MT2_PEER_DISASSOC_REQ;
5205 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5206 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5207 if (Seq == 1 || Seq == 3)
5209 *Machine = AUTH_RSP_STATE_MACHINE;
5210 *MsgType = MT2_PEER_AUTH_ODD;
5212 else if (Seq == 2 || Seq == 4)
5214 *Machine = AUTH_STATE_MACHINE;
5215 *MsgType = MT2_PEER_AUTH_EVEN;
5222 case SUBTYPE_DEAUTH:
5223 *Machine = AUTH_RSP_STATE_MACHINE;
5224 *MsgType = MT2_PEER_DEAUTH;
5226 case SUBTYPE_ACTION:
5227 *Machine = ACTION_STATE_MACHINE;
5228 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5229 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5231 *MsgType = MT2_ACT_INVALID;
5235 *MsgType = (pFrame->Octet[0]&0x7F);
5245 #endif // CONFIG_STA_SUPPORT //
5247 // ===========================================================================================
5249 // ===========================================================================================
5251 /*! \brief Initialize the state machine.
5252 * \param *S pointer to the state machine
5253 * \param Trans State machine transition function
5254 * \param StNr number of states
5255 * \param MsgNr number of messages
5256 * \param DefFunc default function, when there is invalid state/message combination
5257 * \param InitState initial state of the state machine
5258 * \param Base StateMachine base, internal use only
5259 * \pre p_sm should be a legal pointer
5262 IRQL = PASSIVE_LEVEL
5265 VOID StateMachineInit(
5266 IN STATE_MACHINE *S,
5267 IN STATE_MACHINE_FUNC Trans[],
5270 IN STATE_MACHINE_FUNC DefFunc,
5276 // set number of states and messages
5281 S->TransFunc = Trans;
5283 // init all state transition to default function
5284 for (i = 0; i < StNr; i++)
5286 for (j = 0; j < MsgNr; j++)
5288 S->TransFunc[i * MsgNr + j] = DefFunc;
5292 // set the starting state
5293 S->CurrState = InitState;
5296 /*! \brief This function fills in the function pointer into the cell in the state machine
5297 * \param *S pointer to the state machine
5299 * \param Msg incoming message
5300 * \param f the function to be executed when (state, message) combination occurs at the state machine
5301 * \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
5304 IRQL = PASSIVE_LEVEL
5307 VOID StateMachineSetAction(
5308 IN STATE_MACHINE *S,
5311 IN STATE_MACHINE_FUNC Func)
5315 MsgIdx = Msg - S->Base;
5317 if (St < S->NrState && MsgIdx < S->NrMsg)
5319 // boundary checking before setting the action
5320 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5324 /*! \brief This function does the state transition
5325 * \param *Adapter the NIC adapter pointer
5326 * \param *S the state machine
5327 * \param *Elem the message to be executed
5330 IRQL = DISPATCH_LEVEL
5333 VOID StateMachinePerformAction(
5334 IN PRTMP_ADAPTER pAd,
5335 IN STATE_MACHINE *S,
5336 IN MLME_QUEUE_ELEM *Elem)
5338 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5342 ==========================================================================
5344 The drop function, when machine executes this, the message is simply
5345 ignored. This function does nothing, the message is freed in
5346 StateMachinePerformAction()
5347 ==========================================================================
5350 IN PRTMP_ADAPTER pAd,
5351 IN MLME_QUEUE_ELEM *Elem)
5355 // ===========================================================================================
5357 // ===========================================================================================
5360 ==========================================================================
5363 IRQL = PASSIVE_LEVEL
5365 ==========================================================================
5368 IN PRTMP_ADAPTER pAd,
5372 pAd->Mlme.ShiftReg = 1;
5374 pAd->Mlme.ShiftReg = Seed;
5378 ==========================================================================
5380 ==========================================================================
5383 IN PRTMP_ADAPTER pAd)
5390 if (pAd->Mlme.ShiftReg == 0)
5391 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5393 for (i = 0; i < 8; i++)
5395 if (pAd->Mlme.ShiftReg & 0x00000001)
5397 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5402 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5405 R = (R << 1) | Result;
5411 VOID AsicUpdateAutoFallBackTable(
5412 IN PRTMP_ADAPTER pAd,
5413 IN PUCHAR pRateTable)
5416 HT_FBK_CFG0_STRUC HtCfg0;
5417 HT_FBK_CFG1_STRUC HtCfg1;
5418 LG_FBK_CFG0_STRUC LgCfg0;
5419 LG_FBK_CFG1_STRUC LgCfg1;
5420 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5422 // set to initial value
5423 HtCfg0.word = 0x65432100;
5424 HtCfg1.word = 0xedcba988;
5425 LgCfg0.word = 0xedcba988;
5426 LgCfg1.word = 0x00002100;
5428 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5429 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5431 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5432 switch (pCurrTxRate->Mode)
5438 switch(pCurrTxRate->CurrMCS)
5441 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5444 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5447 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5450 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5453 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5456 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5459 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5462 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5467 #ifdef DOT11_N_SUPPORT
5471 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5473 switch(pCurrTxRate->CurrMCS)
5476 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5479 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5482 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5485 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5488 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5491 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5494 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5497 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5500 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5503 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5506 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5509 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5512 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5515 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5518 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5521 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5524 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5529 #endif // DOT11_N_SUPPORT //
5532 pNextTxRate = pCurrTxRate;
5535 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5536 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5537 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5538 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5542 ========================================================================
5544 Routine Description:
5545 Set MAC register value according operation mode.
5546 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5547 If MM or GF mask is not set, those passing argument doesn't not take effect.
5549 Operation mode meaning:
5550 = 0 : Pure HT, no preotection.
5551 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5552 = 0x10: No Transmission in 40M is protected.
5553 = 0x11: Transmission in both 40M and 20M shall be protected
5555 we should choose not to use GF. But still set correct ASIC registers.
5556 ========================================================================
5558 VOID AsicUpdateProtect(
5559 IN PRTMP_ADAPTER pAd,
5560 IN USHORT OperationMode,
5562 IN BOOLEAN bDisableBGProtect,
5563 IN BOOLEAN bNonGFExist)
5565 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5574 #endif // RALINK_ATE //
5576 #ifdef DOT11_N_SUPPORT
5577 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5582 if (pAd->BATable.numAsOriginator)
5585 // enable the RTS/CTS to avoid channel collision
5587 SetMask = ALLN_SETPROTECT;
5590 #endif // DOT11_N_SUPPORT //
5592 // Config ASIC RTS threshold register
5593 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5594 MacReg &= 0xFF0000FF;
5596 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5598 // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5600 #ifdef DOT11_N_SUPPORT
5601 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5602 #endif // DOT11_N_SUPPORT //
5603 (pAd->CommonCfg.bAggregationCapable == TRUE))
5604 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5606 MacReg |= (0x1000 << 8);
5610 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5614 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5616 // Initial common protection settings
5617 RTMPZeroMemory(Protect, sizeof(Protect));
5620 ProtCfg.field.TxopAllowGF40 = 1;
5621 ProtCfg.field.TxopAllowGF20 = 1;
5622 ProtCfg.field.TxopAllowMM40 = 1;
5623 ProtCfg.field.TxopAllowMM20 = 1;
5624 ProtCfg.field.TxopAllowOfdm = 1;
5625 ProtCfg.field.TxopAllowCck = 1;
5626 ProtCfg.field.RTSThEn = 1;
5627 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5629 // update PHY mode and rate
5630 if (pAd->CommonCfg.Channel > 14)
5631 ProtCfg.field.ProtectRate = 0x4000;
5632 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5634 // Handle legacy(B/G) protection
5635 if (bDisableBGProtect)
5637 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5638 ProtCfg.field.ProtectCtrl = 0;
5639 Protect[0] = ProtCfg.word;
5640 Protect[1] = ProtCfg.word;
5644 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5645 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5646 Protect[0] = ProtCfg.word;
5647 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5648 Protect[1] = ProtCfg.word;
5651 #ifdef DOT11_N_SUPPORT
5652 // Decide HT frame protection.
5653 if ((SetMask & ALLN_SETPROTECT) != 0)
5655 switch(OperationMode)
5659 // 1.All STAs in the BSS are 20/40 MHz HT
5660 // 2. in ai 20/40MHz BSS
5661 // 3. all STAs are 20MHz in a 20MHz BSS
5662 // Pure HT. no protection.
5666 // PROT_TXOP(25:20) -- 010111
5667 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5668 // PROT_CTRL(17:16) -- 00 (None)
5669 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5670 Protect[2] = 0x01744004;
5674 // PROT_TXOP(25:20) -- 111111
5675 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5676 // PROT_CTRL(17:16) -- 00 (None)
5677 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5678 Protect[3] = 0x03f44084;
5682 // PROT_TXOP(25:20) -- 010111
5683 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5684 // PROT_CTRL(17:16) -- 00 (None)
5685 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5686 Protect[4] = 0x01744004;
5690 // PROT_TXOP(25:20) -- 111111
5691 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5692 // PROT_CTRL(17:16) -- 00 (None)
5693 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5694 Protect[5] = 0x03f44084;
5698 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5699 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5700 Protect[4] = 0x01754004;
5701 Protect[5] = 0x03f54084;
5703 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5707 // This is "HT non-member protection mode."
5708 // If there may be non-HT STAs my BSS
5709 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5710 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5711 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5713 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5714 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5716 //Assign Protection method for 20&40 MHz packets
5717 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5718 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5719 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5720 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5721 Protect[2] = ProtCfg.word;
5722 Protect[3] = ProtCfg4.word;
5723 Protect[4] = ProtCfg.word;
5724 Protect[5] = ProtCfg4.word;
5725 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5729 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5730 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5731 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5733 //Assign Protection method for 40MHz packets
5734 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5735 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5736 Protect[2] = ProtCfg.word;
5737 Protect[3] = ProtCfg4.word;
5740 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5741 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5743 Protect[4] = ProtCfg.word;
5744 Protect[5] = ProtCfg4.word;
5746 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5750 // HT mixed mode. PROTECT ALL!
5752 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5753 ProtCfg4.word = 0x03f44084;
5754 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5755 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5757 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5758 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5760 //Assign Protection method for 20&40 MHz packets
5761 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5762 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5763 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5764 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5765 Protect[2] = ProtCfg.word;
5766 Protect[3] = ProtCfg4.word;
5767 Protect[4] = ProtCfg.word;
5768 Protect[5] = ProtCfg4.word;
5769 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5773 // Special on for Atheros problem n chip.
5774 Protect[2] = 0x01754004;
5775 Protect[3] = 0x03f54084;
5776 Protect[4] = 0x01754004;
5777 Protect[5] = 0x03f54084;
5778 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5782 #endif // DOT11_N_SUPPORT //
5784 offset = CCK_PROT_CFG;
5785 for (i = 0;i < 6;i++)
5787 if ((SetMask & (1<< i)))
5789 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5795 ==========================================================================
5798 IRQL = PASSIVE_LEVEL
5799 IRQL = DISPATCH_LEVEL
5801 ==========================================================================
5803 VOID AsicSwitchChannel(
5804 IN PRTMP_ADAPTER pAd,
5808 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5809 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5811 UINT32 Value = 0; //BbpReg, Value;
5812 RTMP_RF_REGS *RFRegTable;
5814 // Search Tx power value
5815 for (index = 0; index < pAd->ChannelListNum; index++)
5817 if (Channel == pAd->ChannelList[index].Channel)
5819 TxPwer = pAd->ChannelList[index].Power;
5820 TxPwer2 = pAd->ChannelList[index].Power2;
5825 if (index == MAX_NUM_OF_CHANNELS)
5827 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5831 RFRegTable = RF2850RegTable;
5833 switch (pAd->RfIcType)
5840 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5842 if (Channel == RFRegTable[index].Channel)
5844 R2 = RFRegTable[index].R2;
5845 if (pAd->Antenna.field.TxPath == 1)
5847 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5850 if (pAd->Antenna.field.RxPath == 2)
5852 R2 |= 0x40; // write 1 to off Rxpath.
5854 else if (pAd->Antenna.field.RxPath == 1)
5856 R2 |= 0x20040; // write 1 to off RxPath
5861 // initialize R3, R4
5862 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5863 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5865 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5867 if ((TxPwer >= -7) && (TxPwer < 0))
5869 TxPwer = (7+TxPwer);
5870 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5871 R3 |= (TxPwer << 10);
5872 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5876 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5877 R3 |= (TxPwer << 10) | (1 << 9);
5881 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5883 TxPwer2 = (7+TxPwer2);
5884 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5885 R4 |= (TxPwer2 << 7);
5886 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5890 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5891 R4 |= (TxPwer2 << 7) | (1 << 6);
5896 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5897 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5900 // Based on BBP current mode before changing RF channel.
5901 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5907 pAd->LatchRfRegs.Channel = Channel;
5908 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5909 pAd->LatchRfRegs.R2 = R2;
5910 pAd->LatchRfRegs.R3 = R3;
5911 pAd->LatchRfRegs.R4 = R4;
5913 // Set RF value 1's set R3[bit2] = [0]
5914 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5915 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5916 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5917 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5921 // Set RF value 2's set R3[bit2] = [1]
5922 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5923 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5924 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5925 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5929 // Set RF value 3's set R3[bit2] = [0]
5930 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5931 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5932 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5933 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5945 // Change BBP setting during siwtch from a->g, g->a
5948 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5950 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5951 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5952 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5953 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.
5954 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5956 // Rx High power VGA offset for LNA select
5957 if (pAd->NicConfig2.field.ExternalLNAForG)
5959 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5960 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5964 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5965 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5968 // 5G band selection PIN, bit1 and bit2 are complement
5969 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5972 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5974 // Turn off unused PA or LNA when only 1T or 1R
5975 if (pAd->Antenna.field.TxPath == 1)
5977 TxPinCfg &= 0xFFFFFFF3;
5979 if (pAd->Antenna.field.RxPath == 1)
5981 TxPinCfg &= 0xFFFFF3FF;
5984 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5988 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5990 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5991 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5992 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5993 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.
5994 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5996 // Rx High power VGA offset for LNA select
5997 if (pAd->NicConfig2.field.ExternalLNAForA)
5999 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6003 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6006 // 5G band selection PIN, bit1 and bit2 are complement
6007 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6010 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6012 // Turn off unused PA or LNA when only 1T or 1R
6013 if (pAd->Antenna.field.TxPath == 1)
6015 TxPinCfg &= 0xFFFFFFF3;
6017 if (pAd->Antenna.field.RxPath == 1)
6019 TxPinCfg &= 0xFFFFF3FF;
6022 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6025 // R66 should be set according to Channel and use 20MHz when scanning
6026 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6028 RTMPSetAGCInitValue(pAd, BW_20);
6030 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6033 // On 11A, We should delay and wait RF/BBP to be stable
6034 // and the appropriate time should be 1000 micro seconds
6035 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6037 RTMPusecDelay(1000);
6039 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",
6042 (R3 & 0x00003e00) >> 9,
6043 (R4 & 0x000007c0) >> 6,
6044 pAd->Antenna.field.TxPath,
6045 pAd->LatchRfRegs.R1,
6046 pAd->LatchRfRegs.R2,
6047 pAd->LatchRfRegs.R3,
6048 pAd->LatchRfRegs.R4));
6052 ==========================================================================
6054 This function is required for 2421 only, and should not be used during
6055 site survey. It's only required after NIC decided to stay at a channel
6056 for a longer period.
6057 When this function is called, it's always after AsicSwitchChannel().
6059 IRQL = PASSIVE_LEVEL
6060 IRQL = DISPATCH_LEVEL
6062 ==========================================================================
6064 VOID AsicLockChannel(
6065 IN PRTMP_ADAPTER pAd,
6071 ==========================================================================
6074 IRQL = PASSIVE_LEVEL
6075 IRQL = DISPATCH_LEVEL
6077 ==========================================================================
6079 VOID AsicAntennaSelect(
6080 IN PRTMP_ADAPTER pAd,
6086 ========================================================================
6088 Routine Description:
6089 Antenna miscellaneous setting.
6092 pAd Pointer to our adapter
6093 BandState Indicate current Band State.
6098 IRQL <= DISPATCH_LEVEL
6101 1.) Frame End type control
6102 only valid for G only (RF_2527 & RF_2529)
6103 0: means DPDT, set BBP R4 bit 5 to 1
6104 1: means SPDT, set BBP R4 bit 5 to 0
6107 ========================================================================
6109 VOID AsicAntennaSetting(
6110 IN PRTMP_ADAPTER pAd,
6111 IN ABGBAND_STATE BandState)
6115 VOID AsicRfTuningExec(
6116 IN PVOID SystemSpecific1,
6117 IN PVOID FunctionContext,
6118 IN PVOID SystemSpecific2,
6119 IN PVOID SystemSpecific3)
6124 ==========================================================================
6126 Gives CCK TX rate 2 more dB TX power.
6127 This routine works only in LINK UP in INFRASTRUCTURE mode.
6129 calculate desired Tx power in RF R3.Tx0~5, should consider -
6130 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6131 1. TxPowerPercentage
6132 2. auto calibration based on TSSI feedback
6133 3. extra 2 db for CCK
6134 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6136 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6137 it should be called AFTER MlmeDynamicTxRatSwitching()
6138 ==========================================================================
6140 VOID AsicAdjustTxPower(
6141 IN PRTMP_ADAPTER pAd)
6145 BOOLEAN bAutoTxAgc = FALSE;
6146 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6147 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6148 PCHAR pTxAgcCompensate;
6152 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6154 if (pAd->CommonCfg.CentralChannel > 14)
6156 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6157 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6158 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6159 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6160 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6164 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6165 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6166 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6167 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6168 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6173 if (pAd->CommonCfg.Channel > 14)
6175 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6176 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6177 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6178 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6179 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6183 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6184 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6185 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6186 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6187 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6191 // TX power compensation for temperature variation based on TSSI. try every 4 second
6192 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6194 if (pAd->CommonCfg.Channel <= 14)
6197 bAutoTxAgc = pAd->bAutoTxAgcG;
6198 TssiRef = pAd->TssiRefG;
6199 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6200 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6201 TxAgcStep = pAd->TxAgcStepG;
6202 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6207 bAutoTxAgc = pAd->bAutoTxAgcA;
6208 TssiRef = pAd->TssiRefA;
6209 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6210 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6211 TxAgcStep = pAd->TxAgcStepA;
6212 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6217 /* BbpR1 is unsigned char */
6218 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6220 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6221 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6222 /* step value is defined in pAd->TxAgcStepG for tx power value */
6224 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6225 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6226 above value are examined in mass factory production */
6227 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6229 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6230 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6231 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6233 if (BbpR49 > pTssiMinusBoundary[1])
6235 // Reading is larger than the reference value
6236 // check for how large we need to decrease the Tx power
6237 for (idx = 1; idx < 5; idx++)
6239 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6242 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6243 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6245 DeltaPwr += (*pTxAgcCompensate);
6246 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6247 BbpR49, TssiRef, TxAgcStep, idx-1));
6249 else if (BbpR49 < pTssiPlusBoundary[1])
6251 // Reading is smaller than the reference value
6252 // check for how large we need to increase the Tx power
6253 for (idx = 1; idx < 5; idx++)
6255 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6258 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6259 *pTxAgcCompensate = TxAgcStep * (idx-1);
6260 DeltaPwr += (*pTxAgcCompensate);
6261 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6262 BbpR49, TssiRef, TxAgcStep, idx-1));
6266 *pTxAgcCompensate = 0;
6267 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6268 BbpR49, TssiRef, TxAgcStep, 0));
6274 if (pAd->CommonCfg.Channel <= 14)
6276 bAutoTxAgc = pAd->bAutoTxAgcG;
6277 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6281 bAutoTxAgc = pAd->bAutoTxAgcA;
6282 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6286 DeltaPwr += (*pTxAgcCompensate);
6289 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6293 // Handle regulatory max tx power constrain
6296 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6297 UCHAR AdjustMaxTxPwr[40];
6299 if (pAd->CommonCfg.Channel > 14) // 5G band
6300 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6302 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6303 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6305 // error handling, range check
6306 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6308 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6312 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6314 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6316 // Adjust max tx power according to the relationship of tx power in E2PROM
6319 // CCK will have 4dBm larger than OFDM
6320 // Therefore, we should separate to parse the tx power field
6325 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6329 // CCK will have 4dBm larger than OFDM
6330 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6334 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6336 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6343 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6345 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6346 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6351 // Adjust tx power according to the relationship
6354 if (TxPwr[i] != 0xffffffff)
6358 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6360 // The system tx power is larger than the regulatory, the power should be restrain
6361 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6363 // decrease to zero and don't need to take care BBPR1
6364 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6365 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6369 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6372 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6374 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6379 #endif // SINGLE_SKU //
6381 /* calculate delta power based on the percentage specified from UI */
6382 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6383 // We lower TX power here according to the percentage specified from UI
6384 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6386 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6388 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6392 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6396 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6400 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6405 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6410 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6412 /* reset different new tx power for different TX rate */
6415 if (TxPwr[i] != 0xffffffff)
6419 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6421 if ((Value + DeltaPwr) < 0)
6423 Value = 0; /* min */
6425 else if ((Value + DeltaPwr) > 0xF)
6427 Value = 0xF; /* max */
6431 Value += DeltaPwr; /* temperature compensation */
6434 /* fill new value to CSR offset */
6435 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6438 /* write tx power value to CSR */
6439 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6440 TX power for OFDM 6M/9M
6441 TX power for CCK5.5M/11M
6442 TX power for CCK1M/2M */
6443 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6444 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6450 #ifdef CONFIG_STA_SUPPORT
6452 ==========================================================================
6454 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6455 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6456 the wakeup timer timeout. Driver has to issue a separate command to wake
6459 IRQL = DISPATCH_LEVEL
6461 ==========================================================================
6463 VOID AsicSleepThenAutoWakeup(
6464 IN PRTMP_ADAPTER pAd,
6465 IN USHORT TbttNumToNextWakeUp)
6467 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6471 ==========================================================================
6473 AsicForceWakeup() is used whenever manual wakeup is required
6474 AsicForceSleep() should only be used when not in INFRA BSS. When
6475 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6476 ==========================================================================
6478 VOID AsicForceSleep(
6479 IN PRTMP_ADAPTER pAd)
6485 ==========================================================================
6487 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6490 IRQL = PASSIVE_LEVEL
6491 IRQL = DISPATCH_LEVEL
6492 ==========================================================================
6494 VOID AsicForceWakeup(
6495 IN PRTMP_ADAPTER pAd,
6498 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6499 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6501 #endif // CONFIG_STA_SUPPORT //
6503 ==========================================================================
6507 IRQL = DISPATCH_LEVEL
6509 ==========================================================================
6512 IN PRTMP_ADAPTER pAd,
6516 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6517 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6519 Addr4 = (ULONG)(pBssid[0]) |
6520 (ULONG)(pBssid[1] << 8) |
6521 (ULONG)(pBssid[2] << 16) |
6522 (ULONG)(pBssid[3] << 24);
6523 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6526 // always one BSSID in STA mode
6527 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6529 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6532 VOID AsicSetMcastWC(
6533 IN PRTMP_ADAPTER pAd)
6535 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6538 pEntry->Sst = SST_ASSOC;
6539 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6540 pEntry->PsMode = PWR_ACTIVE;
6541 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6542 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6546 ==========================================================================
6549 IRQL = DISPATCH_LEVEL
6551 ==========================================================================
6553 VOID AsicDelWcidTab(
6554 IN PRTMP_ADAPTER pAd,
6557 ULONG Addr0 = 0x0, Addr1 = 0x0;
6560 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6561 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6562 RTMP_IO_WRITE32(pAd, offset, Addr0);
6564 RTMP_IO_WRITE32(pAd, offset, Addr1);
6568 ==========================================================================
6571 IRQL = DISPATCH_LEVEL
6573 ==========================================================================
6576 IN PRTMP_ADAPTER pAd)
6578 TX_LINK_CFG_STRUC TxLinkCfg;
6581 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6582 TxLinkCfg.field.TxRDGEn = 1;
6583 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6585 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6588 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6590 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6594 ==========================================================================
6597 IRQL = DISPATCH_LEVEL
6599 ==========================================================================
6601 VOID AsicDisableRDG(
6602 IN PRTMP_ADAPTER pAd)
6604 TX_LINK_CFG_STRUC TxLinkCfg;
6608 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6609 TxLinkCfg.field.TxRDGEn = 0;
6610 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6612 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6615 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6616 #ifdef DOT11_N_SUPPORT
6617 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6618 #endif // DOT11_N_SUPPORT //
6621 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6622 if (pAd->CommonCfg.bEnableTxBurst)
6625 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6629 ==========================================================================
6632 IRQL = PASSIVE_LEVEL
6633 IRQL = DISPATCH_LEVEL
6635 ==========================================================================
6637 VOID AsicDisableSync(
6638 IN PRTMP_ADAPTER pAd)
6640 BCN_TIME_CFG_STRUC csr;
6642 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6644 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6645 // that NIC will never wakes up because TSF stops and no more
6647 pAd->TbttTickCount = 0;
6648 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6649 csr.field.bBeaconGen = 0;
6650 csr.field.bTBTTEnable = 0;
6651 csr.field.TsfSyncMode = 0;
6652 csr.field.bTsfTicking = 0;
6653 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6658 ==========================================================================
6661 IRQL = DISPATCH_LEVEL
6663 ==========================================================================
6665 VOID AsicEnableBssSync(
6666 IN PRTMP_ADAPTER pAd)
6668 BCN_TIME_CFG_STRUC csr;
6670 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6672 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6673 #ifdef CONFIG_STA_SUPPORT
6674 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6676 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6677 csr.field.bTsfTicking = 1;
6678 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6679 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6680 csr.field.bTBTTEnable = 1;
6682 #endif // CONFIG_STA_SUPPORT //
6683 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6687 ==========================================================================
6690 BEACON frame in shared memory should be built ok before this routine
6691 can be called. Otherwise, a garbage frame maybe transmitted out every
6694 IRQL = DISPATCH_LEVEL
6696 ==========================================================================
6698 VOID AsicEnableIbssSync(
6699 IN PRTMP_ADAPTER pAd)
6701 BCN_TIME_CFG_STRUC csr9;
6705 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6707 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6708 csr9.field.bBeaconGen = 0;
6709 csr9.field.bTBTTEnable = 0;
6710 csr9.field.bTsfTicking = 0;
6711 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6714 // move BEACON TXD and frame content to on-chip memory
6715 ptr = (PUCHAR)&pAd->BeaconTxWI;
6716 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6718 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6719 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6723 // start right after the 16-byte TXWI field
6724 ptr = pAd->BeaconBuf;
6725 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6727 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6728 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6733 // start sending BEACON
6734 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6735 csr9.field.bTsfTicking = 1;
6736 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6737 csr9.field.bTBTTEnable = 1;
6738 csr9.field.bBeaconGen = 1;
6739 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6743 ==========================================================================
6746 IRQL = PASSIVE_LEVEL
6747 IRQL = DISPATCH_LEVEL
6749 ==========================================================================
6751 VOID AsicSetEdcaParm(
6752 IN PRTMP_ADAPTER pAd,
6753 IN PEDCA_PARM pEdcaParm)
6755 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6756 AC_TXOP_CSR0_STRUC csr0;
6757 AC_TXOP_CSR1_STRUC csr1;
6758 AIFSN_CSR_STRUC AifsnCsr;
6759 CWMIN_CSR_STRUC CwminCsr;
6760 CWMAX_CSR_STRUC CwmaxCsr;
6767 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6769 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6770 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6771 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6773 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6774 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6777 //========================================================
6778 // MAC Register has a copy .
6779 //========================================================
6780 if( pAd->CommonCfg.bEnableTxBurst )
6782 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6783 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6786 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6787 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6788 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6789 Ac0Cfg.field.Aifsn = 2;
6790 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6792 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6793 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6794 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6795 Ac1Cfg.field.Aifsn = 2;
6796 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6798 if (pAd->CommonCfg.PhyMode == PHY_11B)
6800 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6801 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6805 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6806 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6808 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6809 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6810 Ac2Cfg.field.Aifsn = 2;
6811 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6812 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6813 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6814 Ac3Cfg.field.Aifsn = 2;
6815 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6817 //========================================================
6818 // DMA Register has a copy too.
6819 //========================================================
6820 csr0.field.Ac0Txop = 0; // QID_AC_BE
6821 csr0.field.Ac1Txop = 0; // QID_AC_BK
6822 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6823 if (pAd->CommonCfg.PhyMode == PHY_11B)
6825 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6826 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6830 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6831 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6833 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6836 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6837 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6838 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6839 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6840 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6843 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6844 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6845 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6846 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6847 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6849 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6851 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6855 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6856 //========================================================
6857 // MAC Register has a copy.
6858 //========================================================
6860 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6861 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6863 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6865 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6866 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6867 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6868 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6870 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6871 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6872 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6873 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6875 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6876 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6877 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6878 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6879 #ifdef CONFIG_STA_SUPPORT
6880 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6882 // Tuning for Wi-Fi WMM S06
6883 if (pAd->CommonCfg.bWiFiTest &&
6884 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6885 Ac2Cfg.field.Aifsn -= 1;
6887 // Tuning for TGn Wi-Fi 5.2.32
6888 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6889 if (STA_TGN_WIFI_ON(pAd) &&
6890 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6892 Ac0Cfg.field.Aifsn = 3;
6893 Ac2Cfg.field.AcTxop = 5;
6896 #endif // CONFIG_STA_SUPPORT //
6898 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6899 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6900 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6901 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6904 if (pAd->CommonCfg.bWiFiTest)
6906 if (Ac3Cfg.field.AcTxop == 102)
6908 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6909 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6910 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6911 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6912 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6915 //#endif // WIFI_TEST //
6917 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6918 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6919 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6920 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6923 //========================================================
6924 // DMA Register has a copy too.
6925 //========================================================
6926 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6927 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6928 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6930 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6931 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6932 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6935 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6936 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6937 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6938 #ifdef CONFIG_STA_SUPPORT
6939 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6940 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6941 #endif // CONFIG_STA_SUPPORT //
6942 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6945 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6946 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6947 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6948 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6949 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6952 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6953 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6954 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6955 #ifdef CONFIG_STA_SUPPORT
6956 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6958 // Tuning for Wi-Fi WMM S06
6959 if (pAd->CommonCfg.bWiFiTest &&
6960 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6961 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6963 // Tuning for TGn Wi-Fi 5.2.32
6964 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6965 if (STA_TGN_WIFI_ON(pAd) &&
6966 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6968 AifsnCsr.field.Aifsn0 = 3;
6969 AifsnCsr.field.Aifsn2 = 7;
6972 #endif // CONFIG_STA_SUPPORT //
6974 #ifdef CONFIG_STA_SUPPORT
6975 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6976 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6977 #endif // CONFIG_STA_SUPPORT //
6978 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6980 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6983 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6984 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6985 pEdcaParm->Aifsn[0],
6986 pEdcaParm->Cwmin[0],
6987 pEdcaParm->Cwmax[0],
6988 pEdcaParm->Txop[0]<<5,
6989 pEdcaParm->bACM[0]));
6990 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6991 pEdcaParm->Aifsn[1],
6992 pEdcaParm->Cwmin[1],
6993 pEdcaParm->Cwmax[1],
6994 pEdcaParm->Txop[1]<<5,
6995 pEdcaParm->bACM[1]));
6996 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6997 pEdcaParm->Aifsn[2],
6998 pEdcaParm->Cwmin[2],
6999 pEdcaParm->Cwmax[2],
7000 pEdcaParm->Txop[2]<<5,
7001 pEdcaParm->bACM[2]));
7002 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7003 pEdcaParm->Aifsn[3],
7004 pEdcaParm->Cwmin[3],
7005 pEdcaParm->Cwmax[3],
7006 pEdcaParm->Txop[3]<<5,
7007 pEdcaParm->bACM[3]));
7013 ==========================================================================
7016 IRQL = PASSIVE_LEVEL
7017 IRQL = DISPATCH_LEVEL
7019 ==========================================================================
7021 VOID AsicSetSlotTime(
7022 IN PRTMP_ADAPTER pAd,
7023 IN BOOLEAN bUseShortSlotTime)
7026 UINT32 RegValue = 0;
7028 #ifdef CONFIG_STA_SUPPORT
7029 if (pAd->CommonCfg.Channel > 14)
7030 bUseShortSlotTime = TRUE;
7031 #endif // CONFIG_STA_SUPPORT //
7033 if (bUseShortSlotTime)
7034 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7036 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7038 SlotTime = (bUseShortSlotTime)? 9 : 20;
7040 #ifdef CONFIG_STA_SUPPORT
7041 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7043 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7044 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7045 #ifdef DOT11_N_SUPPORT
7046 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7047 #endif // DOT11_N_SUPPORT //
7050 // In this case, we will think it is doing Wi-Fi test
7051 // And we will not set to short slot when bEnableTxBurst is TRUE.
7053 else if (pAd->CommonCfg.bEnableTxBurst)
7056 #endif // CONFIG_STA_SUPPORT //
7059 // For some reasons, always set it to short slot time.
7061 // ToDo: Should consider capability with 11B
7063 #ifdef CONFIG_STA_SUPPORT
7064 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7066 if (pAd->StaCfg.BssType == BSS_ADHOC)
7069 #endif // CONFIG_STA_SUPPORT //
7071 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7072 RegValue = RegValue & 0xFFFFFF00;
7074 RegValue |= SlotTime;
7076 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7080 ========================================================================
7082 Add Shared key information into ASIC.
7083 Update shared key, TxMic and RxMic to Asic Shared key table
7084 Update its cipherAlg to Asic Shared key Mode.
7087 ========================================================================
7089 VOID AsicAddSharedKeyEntry(
7090 IN PRTMP_ADAPTER pAd,
7098 ULONG offset; //, csr0;
7099 SHAREDKEY_MODE_STRUC csr1;
7104 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7105 //============================================================================================
7107 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7108 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7109 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]));
7112 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7113 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7117 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7118 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7120 //============================================================================================
7122 // fill key material - key + TX MIC + RX MIC
7125 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7126 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7128 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7131 offset += MAX_LEN_OF_SHARE_KEY;
7136 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7145 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7152 // Update cipher algorithm. WSTA always use BSS0
7154 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7155 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7156 if ((BssIndex%2) == 0)
7159 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7160 else if (KeyIdx == 1)
7161 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7162 else if (KeyIdx == 2)
7163 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7165 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7170 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7171 else if (KeyIdx == 1)
7172 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7173 else if (KeyIdx == 2)
7174 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7176 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7178 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7179 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7183 // IRQL = DISPATCH_LEVEL
7184 VOID AsicRemoveSharedKeyEntry(
7185 IN PRTMP_ADAPTER pAd,
7190 SHAREDKEY_MODE_STRUC csr1;
7192 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7194 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7195 if ((BssIndex%2) == 0)
7198 csr1.field.Bss0Key0CipherAlg = 0;
7199 else if (KeyIdx == 1)
7200 csr1.field.Bss0Key1CipherAlg = 0;
7201 else if (KeyIdx == 2)
7202 csr1.field.Bss0Key2CipherAlg = 0;
7204 csr1.field.Bss0Key3CipherAlg = 0;
7209 csr1.field.Bss1Key0CipherAlg = 0;
7210 else if (KeyIdx == 1)
7211 csr1.field.Bss1Key1CipherAlg = 0;
7212 else if (KeyIdx == 2)
7213 csr1.field.Bss1Key2CipherAlg = 0;
7215 csr1.field.Bss1Key3CipherAlg = 0;
7217 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7218 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7219 ASSERT(BssIndex < 4);
7225 VOID AsicUpdateWCIDAttribute(
7226 IN PRTMP_ADAPTER pAd,
7230 IN BOOLEAN bUsePairewiseKeyTable)
7232 ULONG WCIDAttri = 0, offset;
7235 // Update WCID attribute.
7236 // Only TxKey could update WCID attribute.
7238 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7239 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7240 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7243 VOID AsicUpdateWCIDIVEIV(
7244 IN PRTMP_ADAPTER pAd,
7251 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7253 RTMP_IO_WRITE32(pAd, offset, uIV);
7254 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7257 VOID AsicUpdateRxWCIDTable(
7258 IN PRTMP_ADAPTER pAd,
7265 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7266 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7267 RTMP_IO_WRITE32(pAd, offset, Addr);
7268 Addr = pAddr[4] + (pAddr[5] << 8);
7269 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7274 ========================================================================
7276 Routine Description:
7277 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7280 pAd Pointer to our adapter
7281 WCID WCID Entry number.
7282 BssIndex BSSID index, station or none multiple BSSID support
7283 this value should be 0.
7284 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7285 pCipherKey Pointer to Cipher Key.
7286 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7287 otherwise PairewiseKey table
7288 bTxKey This is the transmit key if enabled.
7294 This routine will set the relative key stuff to Asic including WCID attribute,
7295 Cipher Key, Cipher algorithm and IV/EIV.
7297 IV/EIV will be update if this CipherKey is the transmission key because
7298 ASIC will base on IV's KeyID value to select Cipher Key.
7300 If bTxKey sets to FALSE, this is not the TX key, but it could be
7303 For AP mode bTxKey must be always set to TRUE.
7304 ========================================================================
7306 VOID AsicAddKeyEntry(
7307 IN PRTMP_ADAPTER pAd,
7311 IN PCIPHER_KEY pCipherKey,
7312 IN BOOLEAN bUsePairewiseKeyTable,
7317 PUCHAR pKey = pCipherKey->Key;
7318 PUCHAR pTxMic = pCipherKey->TxMic;
7319 PUCHAR pRxMic = pCipherKey->RxMic;
7320 PUCHAR pTxtsc = pCipherKey->TxTsc;
7321 UCHAR CipherAlg = pCipherKey->CipherAlg;
7322 SHAREDKEY_MODE_STRUC csr1;
7327 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7329 // 1.) decide key table offset
7331 if (bUsePairewiseKeyTable)
7332 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7334 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7337 // 2.) Set Key to Asic
7339 //for (i = 0; i < KeyLen; i++)
7341 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7343 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7345 offset += MAX_LEN_OF_PEER_KEY;
7348 // 3.) Set MIC key if available
7352 for (i = 0; i < 8; i++)
7354 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7357 offset += LEN_TKIP_TXMICK;
7361 for (i = 0; i < 8; i++)
7363 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7370 // 4.) Modify IV/EIV if needs
7371 // This will force Asic to use this key ID by setting IV.
7376 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7380 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7381 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7382 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7384 IV4 = (KeyIdx << 6);
7385 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7386 IV4 |= 0x20; // turn on extension bit means EIV existence
7388 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7394 for (i = 0; i < 4; i++)
7396 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7400 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7403 if (!bUsePairewiseKeyTable)
7406 // Only update the shared key security mode
7408 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7409 if ((BssIndex % 2) == 0)
7412 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7413 else if (KeyIdx == 1)
7414 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7415 else if (KeyIdx == 2)
7416 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7418 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7423 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7424 else if (KeyIdx == 1)
7425 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7426 else if (KeyIdx == 2)
7427 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7429 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7431 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7434 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7439 ========================================================================
7441 Add Pair-wise key material into ASIC.
7442 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7445 ========================================================================
7447 VOID AsicAddPairwiseKeyEntry(
7448 IN PRTMP_ADAPTER pAd,
7451 IN CIPHER_KEY *pCipherKey)
7455 PUCHAR pKey = pCipherKey->Key;
7456 PUCHAR pTxMic = pCipherKey->TxMic;
7457 PUCHAR pRxMic = pCipherKey->RxMic;
7459 UCHAR CipherAlg = pCipherKey->CipherAlg;
7463 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7465 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7467 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7470 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7473 RTMP_IO_READ32(pAd, offset + i, &Value);
7476 offset += MAX_LEN_OF_PEER_KEY;
7484 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7494 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7499 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7500 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7501 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]));
7504 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7505 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7509 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7510 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7514 ========================================================================
7516 Remove Pair-wise key material from ASIC.
7519 ========================================================================
7521 VOID AsicRemovePairwiseKeyEntry(
7522 IN PRTMP_ADAPTER pAd,
7529 // re-set the entry's WCID attribute as OPEN-NONE.
7530 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7531 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7532 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7535 BOOLEAN AsicSendCommandToMcu(
7536 IN PRTMP_ADAPTER pAd,
7542 HOST_CMD_CSR_STRUC H2MCmd;
7543 H2M_MAILBOX_STRUC H2MMailbox;
7547 static UINT32 j = 0;
7548 #endif // RALINK_ATE //
7552 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7553 if (H2MMailbox.field.Owner == 0)
7563 if (pAd->ate.bFWLoading == TRUE)
7565 /* reloading firmware when received iwpriv cmd "ATE=ATESTOP" */
7570 DBGPRINT(RT_DEBUG_ERROR, ("#"));
7574 DBGPRINT(RT_DEBUG_ERROR, ("\n"));
7580 DBGPRINT(RT_DEBUG_ERROR, ("Loading firmware. Please wait for a moment...\n"));
7585 #endif // RALINK_ATE //
7588 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7595 else if (pAd->ate.bFWLoading == TRUE)
7597 /* reloading of firmware is completed */
7598 pAd->ate.bFWLoading = FALSE;
7599 DBGPRINT(RT_DEBUG_ERROR, ("\n"));
7602 #endif // RALINK_ATE //
7605 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7606 H2MMailbox.field.CmdToken = Token;
7607 H2MMailbox.field.HighByte = Arg1;
7608 H2MMailbox.field.LowByte = Arg0;
7609 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7612 H2MCmd.field.HostCommand = Command;
7613 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7615 if (Command != 0x80)
7623 BOOLEAN AsicCheckCommanOk(
7624 IN PRTMP_ADAPTER pAd,
7627 UINT32 CmdStatus = 0, CID = 0, i;
7628 UINT32 ThisCIDMask = 0;
7633 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7634 // Find where the command is. Because this is randomly specified by firmware.
7635 if ((CID & CID0MASK) == Command)
7637 ThisCIDMask = CID0MASK;
7640 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7642 ThisCIDMask = CID1MASK;
7645 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7647 ThisCIDMask = CID2MASK;
7650 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7652 ThisCIDMask = CID3MASK;
7660 // Get CommandStatus Value
7661 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7663 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7666 // If Status is 1, the comamnd is success.
7667 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7668 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7670 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7671 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7672 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7675 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7679 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7681 // Clear Command and Status.
7682 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7683 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7690 ========================================================================
7692 Routine Description:
7693 Verify the support rate for different PHY type
7696 pAd Pointer to our adapter
7701 IRQL = PASSIVE_LEVEL
7703 ========================================================================
7705 VOID RTMPCheckRates(
7706 IN PRTMP_ADAPTER pAd,
7707 IN OUT UCHAR SupRate[],
7708 IN OUT UCHAR *SupRateLen)
7710 UCHAR RateIdx, i, j;
7711 UCHAR NewRate[12], NewRateLen;
7715 if (pAd->CommonCfg.PhyMode == PHY_11B)
7720 // Check for support rates exclude basic rate bit
7721 for (i = 0; i < *SupRateLen; i++)
7722 for (j = 0; j < RateIdx; j++)
7723 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7724 NewRate[NewRateLen++] = SupRate[i];
7726 *SupRateLen = NewRateLen;
7727 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7730 #ifdef CONFIG_STA_SUPPORT
7731 #ifdef DOT11_N_SUPPORT
7732 BOOLEAN RTMPCheckChannel(
7733 IN PRTMP_ADAPTER pAd,
7734 IN UCHAR CentralChannel,
7738 UCHAR UpperChannel = 0, LowerChannel = 0;
7739 UCHAR NoEffectChannelinList = 0;
7741 // Find upper and lower channel according to 40MHz current operation.
7742 if (CentralChannel < Channel)
7744 UpperChannel = Channel;
7745 if (CentralChannel > 2)
7746 LowerChannel = CentralChannel - 2;
7750 else if (CentralChannel > Channel)
7752 UpperChannel = CentralChannel + 2;
7753 LowerChannel = Channel;
7756 for (k = 0;k < pAd->ChannelListNum;k++)
7758 if (pAd->ChannelList[k].Channel == UpperChannel)
7760 NoEffectChannelinList ++;
7762 if (pAd->ChannelList[k].Channel == LowerChannel)
7764 NoEffectChannelinList ++;
7768 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7769 if (NoEffectChannelinList == 2)
7776 ========================================================================
7778 Routine Description:
7779 Verify the support rate for HT phy type
7782 pAd Pointer to our adapter
7785 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7787 IRQL = PASSIVE_LEVEL
7789 ========================================================================
7791 BOOLEAN RTMPCheckHt(
7792 IN PRTMP_ADAPTER pAd,
7794 IN HT_CAPABILITY_IE *pHtCapability,
7795 IN ADD_HT_INFO_IE *pAddHtInfo)
7797 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7800 // If use AMSDU, set flag.
7801 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7802 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7803 // Save Peer Capability
7804 if (pHtCapability->HtCapInfo.ShortGIfor20)
7805 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7806 if (pHtCapability->HtCapInfo.ShortGIfor40)
7807 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7808 if (pHtCapability->HtCapInfo.TxSTBC)
7809 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7810 if (pHtCapability->HtCapInfo.RxSTBC)
7811 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7812 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7814 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7817 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7819 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7822 // Will check ChannelWidth for MCSSet[4] below
7823 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7824 switch (pAd->CommonCfg.RxStream)
7827 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7828 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7829 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7830 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7833 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7834 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7835 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7836 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7839 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7840 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7841 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7842 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7846 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7848 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7849 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7850 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7852 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7854 // Send Assoc Req with my HT capability.
7855 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7856 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7857 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7858 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7859 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7860 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7861 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7862 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7863 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7864 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7865 if (pAd->CommonCfg.bRdg)
7867 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7868 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7871 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7872 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7874 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7877 #endif // DOT11_N_SUPPORT //
7878 #endif // CONFIG_STA_SUPPORT //
7881 ========================================================================
7883 Routine Description:
7884 Verify the support rate for different PHY type
7887 pAd Pointer to our adapter
7892 IRQL = PASSIVE_LEVEL
7894 ========================================================================
7896 VOID RTMPUpdateMlmeRate(
7897 IN PRTMP_ADAPTER pAd)
7900 UCHAR ProperMlmeRate; //= RATE_54;
7901 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7902 BOOLEAN bMatch = FALSE;
7904 switch (pAd->CommonCfg.PhyMode)
7907 ProperMlmeRate = RATE_11;
7908 MinimumRate = RATE_1;
7910 case PHY_11BG_MIXED:
7911 #ifdef DOT11_N_SUPPORT
7912 case PHY_11ABGN_MIXED:
7913 case PHY_11BGN_MIXED:
7914 #endif // DOT11_N_SUPPORT //
7915 if ((pAd->MlmeAux.SupRateLen == 4) &&
7916 (pAd->MlmeAux.ExtRateLen == 0))
7918 ProperMlmeRate = RATE_11;
7920 ProperMlmeRate = RATE_24;
7922 if (pAd->MlmeAux.Channel <= 14)
7923 MinimumRate = RATE_1;
7925 MinimumRate = RATE_6;
7928 #ifdef DOT11_N_SUPPORT
7929 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7930 case PHY_11GN_MIXED:
7931 case PHY_11AGN_MIXED:
7932 case PHY_11AN_MIXED:
7934 #endif // DOT11_N_SUPPORT //
7935 ProperMlmeRate = RATE_24;
7936 MinimumRate = RATE_6;
7938 case PHY_11ABG_MIXED:
7939 ProperMlmeRate = RATE_24;
7940 if (pAd->MlmeAux.Channel <= 14)
7941 MinimumRate = RATE_1;
7943 MinimumRate = RATE_6;
7946 ProperMlmeRate = RATE_1;
7947 MinimumRate = RATE_1;
7951 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7953 for (j = 0; j < RateIdx; j++)
7955 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7957 if (j == ProperMlmeRate)
7969 if (bMatch == FALSE)
7971 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7973 for (j = 0; j < RateIdx; j++)
7975 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7977 if (j == ProperMlmeRate)
7990 if (bMatch == FALSE)
7992 ProperMlmeRate = MinimumRate;
7995 pAd->CommonCfg.MlmeRate = MinimumRate;
7996 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7997 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7999 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8000 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8001 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8002 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8006 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8007 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8008 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8009 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8012 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8016 IN PRTMP_ADAPTER pAd,
8023 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8028 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8030 larger = max(Rssi0, Rssi1);
8033 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8035 larger = max(larger, Rssi2);
8045 ========================================================================
8046 Routine Description:
8047 Periodic evaluate antenna link status
8050 pAd - Adapter pointer
8055 ========================================================================
8057 VOID AsicEvaluateRxAnt(
8058 IN PRTMP_ADAPTER pAd)
8065 #endif // RALINK_ATE //
8068 #ifdef CONFIG_STA_SUPPORT
8069 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8071 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8072 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8073 fRTMP_ADAPTER_RADIO_OFF |
8074 fRTMP_ADAPTER_NIC_NOT_EXIST |
8075 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
8078 if (pAd->StaCfg.Psm == PWR_SAVE)
8081 #endif // CONFIG_STA_SUPPORT //
8083 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8085 if(pAd->Antenna.field.RxPath == 3)
8089 else if(pAd->Antenna.field.RxPath == 2)
8093 else if(pAd->Antenna.field.RxPath == 1)
8097 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8098 #ifdef CONFIG_STA_SUPPORT
8100 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8101 pAd->StaCfg.BBPR3 = BBPR3;
8103 #endif // CONFIG_STA_SUPPORT //
8104 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8107 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8108 pAd->RalinkCounters.OneSecTxRetryOkCount +
8109 pAd->RalinkCounters.OneSecTxFailCount;
8111 if (TxTotalCnt > 50)
8113 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8114 pAd->Mlme.bLowThroughput = FALSE;
8118 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8119 pAd->Mlme.bLowThroughput = TRUE;
8125 ========================================================================
8126 Routine Description:
8127 After evaluation, check antenna link status
8130 pAd - Adapter pointer
8135 ========================================================================
8137 VOID AsicRxAntEvalTimeout(
8138 IN PVOID SystemSpecific1,
8139 IN PVOID FunctionContext,
8140 IN PVOID SystemSpecific2,
8141 IN PVOID SystemSpecific3)
8143 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8144 #ifdef CONFIG_STA_SUPPORT
8146 CHAR larger = -127, rssi0, rssi1, rssi2;
8147 #endif // CONFIG_STA_SUPPORT //
8152 #endif // RALINK_ATE //
8155 #ifdef CONFIG_STA_SUPPORT
8156 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8158 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8159 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8160 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8161 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8164 if (pAd->StaCfg.Psm == PWR_SAVE)
8168 // if the traffic is low, use average rssi as the criteria
8169 if (pAd->Mlme.bLowThroughput == TRUE)
8171 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8172 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8173 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8177 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8178 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8179 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8182 if(pAd->Antenna.field.RxPath == 3)
8184 larger = max(rssi0, rssi1);
8186 if (larger > (rssi2 + 20))
8187 pAd->Mlme.RealRxPath = 2;
8189 pAd->Mlme.RealRxPath = 3;
8191 else if(pAd->Antenna.field.RxPath == 2)
8193 if (rssi0 > (rssi1 + 20))
8194 pAd->Mlme.RealRxPath = 1;
8196 pAd->Mlme.RealRxPath = 2;
8199 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8201 if(pAd->Mlme.RealRxPath == 3)
8205 else if(pAd->Mlme.RealRxPath == 2)
8209 else if(pAd->Mlme.RealRxPath == 1)
8213 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8215 pAd->StaCfg.BBPR3 = BBPR3;
8219 #endif // CONFIG_STA_SUPPORT //
8225 VOID APSDPeriodicExec(
8226 IN PVOID SystemSpecific1,
8227 IN PVOID FunctionContext,
8228 IN PVOID SystemSpecific2,
8229 IN PVOID SystemSpecific3)
8231 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8233 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8236 pAd->CommonCfg.TriggerTimerCount++;
8241 ========================================================================
8242 Routine Description:
8243 Set/reset MAC registers according to bPiggyBack parameter
8246 pAd - Adapter pointer
8247 bPiggyBack - Enable / Disable Piggy-Back
8252 ========================================================================
8254 VOID RTMPSetPiggyBack(
8255 IN PRTMP_ADAPTER pAd,
8256 IN BOOLEAN bPiggyBack)
8258 TX_LINK_CFG_STRUC TxLinkCfg;
8260 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8262 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8263 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8267 ========================================================================
8268 Routine Description:
8269 check if this entry need to switch rate automatically
8279 ========================================================================
8281 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8282 IN PRTMP_ADAPTER pAd,
8283 IN PMAC_TABLE_ENTRY pEntry)
8285 BOOLEAN result = TRUE;
8288 #ifdef CONFIG_STA_SUPPORT
8289 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8291 // only associated STA counts
8292 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8294 result = pAd->StaCfg.bAutoTxRateSwitch;
8299 #ifdef QOS_DLS_SUPPORT
8300 if (pEntry && (pEntry->ValidAsDls))
8301 result = pAd->StaCfg.bAutoTxRateSwitch;
8302 #endif // QOS_DLS_SUPPORT //
8304 #endif // CONFIG_STA_SUPPORT //
8312 BOOLEAN RTMPAutoRateSwitchCheck(
8313 IN PRTMP_ADAPTER pAd)
8316 #ifdef CONFIG_STA_SUPPORT
8317 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8319 if (pAd->StaCfg.bAutoTxRateSwitch)
8322 #endif // CONFIG_STA_SUPPORT //
8328 ========================================================================
8329 Routine Description:
8330 check if this entry need to fix tx legacy rate
8340 ========================================================================
8342 UCHAR RTMPStaFixedTxMode(
8343 IN PRTMP_ADAPTER pAd,
8344 IN PMAC_TABLE_ENTRY pEntry)
8346 UCHAR tx_mode = FIXED_TXMODE_HT;
8349 #ifdef CONFIG_STA_SUPPORT
8350 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8352 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8354 #endif // CONFIG_STA_SUPPORT //
8360 ========================================================================
8361 Routine Description:
8362 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8372 ========================================================================
8374 VOID RTMPUpdateLegacyTxSetting(
8375 UCHAR fixed_tx_mode,
8376 PMAC_TABLE_ENTRY pEntry)
8378 HTTRANSMIT_SETTING TransmitSetting;
8380 if (fixed_tx_mode == FIXED_TXMODE_HT)
8383 TransmitSetting.word = 0;
8385 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8386 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8388 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8390 TransmitSetting.field.MODE = MODE_CCK;
8391 // CCK mode allow MCS 0~3
8392 if (TransmitSetting.field.MCS > MCS_3)
8393 TransmitSetting.field.MCS = MCS_3;
8397 TransmitSetting.field.MODE = MODE_OFDM;
8398 // OFDM mode allow MCS 0~7
8399 if (TransmitSetting.field.MCS > MCS_7)
8400 TransmitSetting.field.MCS = MCS_7;
8403 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8405 pEntry->HTPhyMode.word = TransmitSetting.word;
8406 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8407 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8411 #ifdef CONFIG_STA_SUPPORT
8413 ==========================================================================
8415 dynamic tune BBP R66 to find a balance between sensibility and
8418 IRQL = DISPATCH_LEVEL
8420 ==========================================================================
8422 VOID AsicStaBbpTuning(
8423 IN PRTMP_ADAPTER pAd)
8425 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8428 // 2860C did not support Fase CCA, therefore can't tune
8429 if (pAd->MACVersion == 0x28600100)
8435 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8438 if ((pAd->OpMode == OPMODE_STA)
8439 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8441 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8443 && (pAd->bPCIclkOff == FALSE)
8447 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8450 if (pAd->Antenna.field.RxPath > 1)
8451 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8453 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8455 if (pAd->LatchRfRegs.Channel <= 14)
8458 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8460 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8461 if (OrigR66Value != R66)
8463 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8468 R66 = 0x2E + GET_LNA_GAIN(pAd);
8469 if (OrigR66Value != R66)
8471 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8478 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8480 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8482 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8483 if (OrigR66Value != R66)
8485 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8490 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8491 if (OrigR66Value != R66)
8493 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8499 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8501 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8502 if (OrigR66Value != R66)
8504 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8509 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8510 if (OrigR66Value != R66)
8512 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8521 #endif // CONFIG_STA_SUPPORT //
8523 VOID RTMPSetAGCInitValue(
8524 IN PRTMP_ADAPTER pAd,
8529 if (pAd->LatchRfRegs.Channel <= 14)
8531 R66 = 0x2E + GET_LNA_GAIN(pAd);
8532 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8536 if (BandWidth == BW_20)
8538 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8539 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8541 #ifdef DOT11_N_SUPPORT
8544 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8545 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8547 #endif // DOT11_N_SUPPORT //
8552 VOID AsicTurnOffRFClk(
8553 IN PRTMP_ADAPTER pAd,
8558 UINT32 R1 = 0, R2 = 0, R3 = 0;
8560 RTMP_RF_REGS *RFRegTable;
8562 RFRegTable = RF2850RegTable;
8564 switch (pAd->RfIcType)
8571 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8573 if (Channel == RFRegTable[index].Channel)
8575 R1 = RFRegTable[index].R1 & 0xffffdfff;
8576 R2 = RFRegTable[index].R2 & 0xfffbffff;
8577 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8579 RTMP_RF_IO_WRITE32(pAd, R1);
8580 RTMP_RF_IO_WRITE32(pAd, R2);
8582 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8583 // Set RF R2 bit18=0, R3 bit[18:19]=0
8584 //if (pAd->StaCfg.bRadio == FALSE)
8587 RTMP_RF_IO_WRITE32(pAd, R3);
8589 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8590 Channel, pAd->RfIcType, R2, R3));
8593 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8594 Channel, pAd->RfIcType, R2));
8606 VOID AsicTurnOnRFClk(
8607 IN PRTMP_ADAPTER pAd,
8612 UINT32 R1 = 0, R2 = 0, R3 = 0;
8614 RTMP_RF_REGS *RFRegTable;
8616 RFRegTable = RF2850RegTable;
8618 switch (pAd->RfIcType)
8625 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8627 if (Channel == RFRegTable[index].Channel)
8629 R3 = pAd->LatchRfRegs.R3;
8632 RTMP_RF_IO_WRITE32(pAd, R3);
8634 R1 = RFRegTable[index].R1;
8635 RTMP_RF_IO_WRITE32(pAd, R1);
8637 R2 = RFRegTable[index].R2;
8638 if (pAd->Antenna.field.TxPath == 1)
8640 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8643 if (pAd->Antenna.field.RxPath == 2)
8645 R2 |= 0x40; // write 1 to off Rxpath.
8647 else if (pAd->Antenna.field.RxPath == 1)
8649 R2 |= 0x20040; // write 1 to off RxPath
8651 RTMP_RF_IO_WRITE32(pAd, R2);
8662 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",