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;
812 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
813 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
814 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
815 if(pAd->StaCfg.WepStatus<2)
817 pAd->StaCfg.WpaSupplicantUP = 0;
821 pAd->StaCfg.WpaSupplicantUP = 1;
824 #ifdef CONFIG_STA_SUPPORT
826 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
828 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
829 // Move code to here, because following code will return when radio is off
830 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
831 (pAd->StaCfg.bHardwareRadio == TRUE) &&
832 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
833 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
834 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
838 // Read GPIO pin2 as Hardware controlled radio state
839 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
842 pAd->StaCfg.bHwRadio = TRUE;
846 pAd->StaCfg.bHwRadio = FALSE;
848 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
850 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
851 if (pAd->StaCfg.bRadio == TRUE)
854 // Update extra information
855 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
860 // Update extra information
861 pAd->ExtraInfo = HW_RADIO_OFF;
867 #endif // CONFIG_STA_SUPPORT //
869 // Do nothing if the driver is starting halt state.
870 // This might happen when timer already been fired before cancel timer with mlmehalt
871 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
872 fRTMP_ADAPTER_RADIO_OFF |
873 fRTMP_ADAPTER_RADIO_MEASUREMENT |
874 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
877 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
879 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
881 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
882 pAd->SameRxByteCount++;
885 pAd->SameRxByteCount = 0;
887 // If after BBP, still not work...need to check to reset PBF&MAC.
888 if (pAd->SameRxByteCount == 702)
890 pAd->SameRxByteCount = 0;
895 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
896 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
898 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
900 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
901 pAd->SameRxByteCount = 700;
906 // Update lastReceiveByteCount.
907 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
909 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
911 pAd->CheckDmaBusyCount = 0;
912 AsicResetFromDMABusy(pAd);
916 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
919 /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */
922 if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1))
924 pAd->Mlme.PeriodicRound ++;
928 #endif // RALINK_ATE //
930 #ifdef CONFIG_STA_SUPPORT
931 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
933 // Do nothing if monitor mode is on
937 if (pAd->Mlme.PeriodicRound & 0x1)
939 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
940 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
941 (STA_TGN_WIFI_ON(pAd)) &&
942 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
945 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
946 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
948 else if ((STA_TGN_WIFI_ON(pAd)) &&
949 ((pAd->MACVersion & 0xffff) == 0x0101))
951 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
952 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
956 #endif // CONFIG_STA_SUPPORT //
958 pAd->bUpdateBcnCntDone = FALSE;
960 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
961 pAd->Mlme.PeriodicRound ++;
963 // execute every 500ms
964 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
966 #ifdef CONFIG_STA_SUPPORT
967 // perform dynamic tx rate switching based on past TX history
968 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
970 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
972 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
973 MlmeDynamicTxRateSwitching(pAd);
975 #endif // CONFIG_STA_SUPPORT //
978 // Normal 1 second Mlme PeriodicExec.
979 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
981 pAd->Mlme.OneSecPeriodicRound ++;
986 /* request from Baron : move this routine from later to here */
987 /* for showing Rx error count in ATE RXFRAME */
988 NICUpdateRawCounters(pAd);
989 if (pAd->ate.bRxFer == 1)
991 pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec;
992 ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt);
993 pAd->ate.RxCntPerSec = 0;
995 if (pAd->ate.RxAntennaSel == 0)
996 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n",
997 pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2);
999 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0);
1001 MlmeResetRalinkCounters(pAd);
1004 #endif // RALINK_ATE //
1015 // Media status changed, report to NDIS
1016 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
1018 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
1019 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1021 pAd->IndicateMediaState = NdisMediaStateConnected;
1022 RTMP_IndicateMediaState(pAd);
1027 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1028 RTMP_IndicateMediaState(pAd);
1032 NdisGetSystemUpTime(&pAd->Mlme.Now32);
1034 // add the most up-to-date h/w raw counters into software variable, so that
1035 // the dynamic tuning mechanism below are based on most up-to-date information
1036 NICUpdateRawCounters(pAd);
1039 #ifdef DOT11_N_SUPPORT
1040 // Need statistics after read counter. So put after NICUpdateRawCounters
1041 ORIBATimerTimeout(pAd);
1042 #endif // DOT11_N_SUPPORT //
1045 // The time period for checking antenna is according to traffic
1046 if (pAd->Mlme.bEnableAutoAntennaCheck)
1048 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1049 pAd->RalinkCounters.OneSecTxRetryOkCount +
1050 pAd->RalinkCounters.OneSecTxFailCount;
1052 if (TxTotalCnt > 50)
1054 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
1056 AsicEvaluateRxAnt(pAd);
1061 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
1063 AsicEvaluateRxAnt(pAd);
1068 #ifdef CONFIG_STA_SUPPORT
1069 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1070 STAMlmePeriodicExec(pAd);
1071 #endif // CONFIG_STA_SUPPORT //
1073 MlmeResetRalinkCounters(pAd);
1075 #ifdef CONFIG_STA_SUPPORT
1076 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1079 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1082 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1083 // and sending CTS-to-self over and over.
1084 // Software Patch Solution:
1085 // 1. Polling debug state register 0x10F4 every one second.
1086 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1087 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1091 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1092 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1094 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1096 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1098 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1102 #endif // CONFIG_STA_SUPPORT //
1104 RT28XX_MLME_HANDLER(pAd);
1108 pAd->bUpdateBcnCntDone = FALSE;
1111 #ifdef CONFIG_STA_SUPPORT
1112 VOID STAMlmePeriodicExec(
1118 // We return here in ATE mode, because the statistics
1119 // that ATE needs are not collected via this routine.
1122 // It is supposed that we will never reach here in ATE mode.
1123 ASSERT(!(ATE_ON(pAd)));
1126 #endif // RALINK_ATE //
1128 #ifdef WPA_SUPPLICANT_SUPPORT
1129 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1130 #endif // WPA_SUPPLICANT_SUPPORT //
1132 // WPA MIC error should block association attempt for 60 seconds
1133 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1134 pAd->StaCfg.bBlockAssoc = FALSE;
1138 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1139 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1140 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1141 if(pAd->StaCfg.WepStatus<2)
1143 pAd->StaCfg.WpaSupplicantUP = 0;
1147 pAd->StaCfg.WpaSupplicantUP = 1;
1150 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1152 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1154 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1156 pAd->PreMediaState = pAd->IndicateMediaState;
1159 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1160 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1161 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1162 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1163 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1164 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1166 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1171 AsicStaBbpTuning(pAd);
1173 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1174 pAd->RalinkCounters.OneSecTxRetryOkCount +
1175 pAd->RalinkCounters.OneSecTxFailCount;
1177 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1179 // update channel quality for Roaming and UI LinkQuality display
1180 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1183 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1184 // Radio is currently in noisy environment
1185 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1186 AsicAdjustTxPower(pAd);
1190 #ifdef QOS_DLS_SUPPORT
1191 // Check DLS time out, then tear down those session
1192 RTMPCheckDLSTimeOut(pAd);
1193 #endif // QOS_DLS_SUPPORT //
1195 // Is PSM bit consistent with user power management policy?
1196 // This is the only place that will set PSM bit ON.
1197 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1198 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1200 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1202 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1203 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1204 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1206 RTMPSetAGCInitValue(pAd, BW_20);
1207 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1211 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1213 // When APSD is enabled, the period changes as 20 sec
1214 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1215 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1219 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1220 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1222 if (pAd->CommonCfg.bWmmCapable)
1223 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1225 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1230 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1232 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1233 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1234 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1236 // Lost AP, send disconnect & link down event
1237 LinkDown(pAd, FALSE);
1239 #ifdef WPA_SUPPLICANT_SUPPORT
1240 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1241 if (pAd->StaCfg.WpaSupplicantUP)
1243 union iwreq_data wrqu;
1244 //send disassociate event to wpa_supplicant
1245 memset(&wrqu, 0, sizeof(wrqu));
1246 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1247 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1249 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1250 #endif // WPA_SUPPLICANT_SUPPORT //
1252 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1254 union iwreq_data wrqu;
1255 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1256 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1258 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1260 MlmeAutoReconnectLastSSID(pAd);
1262 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1264 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1265 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1266 MlmeAutoReconnectLastSSID(pAd);
1269 // Add auto seamless roaming
1270 if (pAd->StaCfg.bFastRoaming)
1272 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1274 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));
1276 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1278 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1282 else if (ADHOC_ON(pAd))
1284 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1285 // the "TX BEACON competition" for the entire past 1 sec.
1286 // So that even when ASIC's BEACONgen engine been blocked
1287 // by peer's BEACON due to slower system clock, this STA still can send out
1288 // minimum BEACON to tell the peer I'm alive.
1289 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1290 // EnqueueBeaconFrame(pAd); // software send BEACON
1292 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1293 // restore outgoing BEACON to support B/G-mixed mode
1294 if ((pAd->CommonCfg.Channel <= 14) &&
1295 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1296 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1297 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1299 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1300 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1301 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1302 MlmeUpdateTxRates(pAd, FALSE, 0);
1303 MakeIbssBeacon(pAd); // re-build BEACON frame
1304 AsicEnableIbssSync(pAd); // copy to on-chip memory
1305 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1308 #ifdef DOT11_N_SUPPORT
1309 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1311 if ((pAd->StaCfg.AdhocBGJoined) &&
1312 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1314 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1315 pAd->StaCfg.AdhocBGJoined = FALSE;
1318 if ((pAd->StaCfg.Adhoc20NJoined) &&
1319 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1321 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1322 pAd->StaCfg.Adhoc20NJoined = FALSE;
1325 #endif // DOT11_N_SUPPORT //
1328 if ((pAd->CommonCfg.Channel > 14)
1329 && (pAd->CommonCfg.bIEEE80211H == 1)
1330 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1332 RadarDetectPeriodic(pAd);
1335 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1336 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1338 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1339 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1341 MLME_START_REQ_STRUCT StartReq;
1343 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1344 LinkDown(pAd, FALSE);
1346 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1347 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1348 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1351 else // no INFRA nor ADHOC connection
1354 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1355 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1356 goto SKIP_AUTO_SCAN_CONN;
1358 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1360 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1361 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1362 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1364 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1366 MLME_SCAN_REQ_STRUCT ScanReq;
1368 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1370 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1371 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1372 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1373 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1374 // Reset Missed scan number
1375 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1377 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1378 MlmeAutoReconnectLastSSID(pAd);
1380 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1382 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1385 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1389 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1390 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1392 if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1)
1393 MlmeAutoReconnectLastSSID(pAd);
1396 #endif // CARRIER_DETECTION_SUPPORT //
1397 MlmeAutoReconnectLastSSID(pAd);
1403 SKIP_AUTO_SCAN_CONN:
1405 #ifdef DOT11_N_SUPPORT
1406 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1408 pAd->MacTab.fAnyBASession = TRUE;
1409 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1411 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1413 pAd->MacTab.fAnyBASession = FALSE;
1414 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1416 #endif // DOT11_N_SUPPORT //
1419 #ifdef DOT11_N_SUPPORT
1420 #ifdef DOT11N_DRAFT3
1421 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1422 TriEventCounterMaintenance(pAd);
1423 #endif // DOT11N_DRAFT3 //
1424 #endif // DOT11_N_SUPPORT //
1431 IN PVOID SystemSpecific1,
1432 IN PVOID FunctionContext,
1433 IN PVOID SystemSpecific2,
1434 IN PVOID SystemSpecific3)
1437 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1439 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1440 RTMP_IndicateMediaState(pAd);
1441 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1444 // IRQL = DISPATCH_LEVEL
1446 IN PRTMP_ADAPTER pAd)
1448 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1449 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1451 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1453 MLME_CNTL_STATE_MACHINE,
1454 OID_802_11_BSSID_LIST_SCAN,
1457 RT28XX_MLME_HANDLER(pAd);
1461 // IRQL = DISPATCH_LEVEL
1462 VOID MlmeAutoReconnectLastSSID(
1463 IN PRTMP_ADAPTER pAd)
1467 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1468 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1469 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1471 NDIS_802_11_SSID OidSsid;
1472 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1473 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1475 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1477 MLME_CNTL_STATE_MACHINE,
1479 sizeof(NDIS_802_11_SSID),
1481 RT28XX_MLME_HANDLER(pAd);
1484 #endif // CONFIG_STA_SUPPORT //
1487 ==========================================================================
1488 Validate SSID for connection try and rescan purpose
1489 Valid SSID will have visible chars only.
1490 The valid length is from 0 to 32.
1491 IRQL = DISPATCH_LEVEL
1492 ==========================================================================
1494 BOOLEAN MlmeValidateSSID(
1500 if (SsidLen > MAX_LEN_OF_SSID)
1503 // Check each character value
1504 for (index = 0; index < SsidLen; index++)
1506 if (pSsid[index] < 0x20)
1514 VOID MlmeSelectTxRateTable(
1515 IN PRTMP_ADAPTER pAd,
1516 IN PMAC_TABLE_ENTRY pEntry,
1518 IN PUCHAR pTableSize,
1519 IN PUCHAR pInitTxRateIdx)
1523 // decide the rate table for tuning
1524 if (pAd->CommonCfg.TxRateTableSize > 0)
1526 *ppTable = RateSwitchTable;
1527 *pTableSize = RateSwitchTable[0];
1528 *pInitTxRateIdx = RateSwitchTable[1];
1533 #ifdef CONFIG_STA_SUPPORT
1534 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1536 #ifdef DOT11_N_SUPPORT
1537 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1538 !pAd->StaCfg.AdhocBOnlyJoined &&
1539 !pAd->StaCfg.AdhocBGJoined &&
1540 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1541 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1543 *ppTable = RateSwitchTable11N1S;
1544 *pTableSize = RateSwitchTable11N1S[0];
1545 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1548 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1549 !pAd->StaCfg.AdhocBOnlyJoined &&
1550 !pAd->StaCfg.AdhocBGJoined &&
1551 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1552 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1553 (pAd->Antenna.field.TxPath == 2))
1555 if (pAd->LatchRfRegs.Channel <= 14)
1557 *ppTable = RateSwitchTable11N2S;
1558 *pTableSize = RateSwitchTable11N2S[0];
1559 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1563 *ppTable = RateSwitchTable11N2SForABand;
1564 *pTableSize = RateSwitchTable11N2SForABand[0];
1565 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1570 #endif // DOT11_N_SUPPORT //
1571 if (pAd->CommonCfg.PhyMode == PHY_11B)
1573 *ppTable = RateSwitchTable11B;
1574 *pTableSize = RateSwitchTable11B[0];
1575 *pInitTxRateIdx = RateSwitchTable11B[1];
1578 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1580 // USe B Table when Only b-only Station in my IBSS .
1581 *ppTable = RateSwitchTable11B;
1582 *pTableSize = RateSwitchTable11B[0];
1583 *pInitTxRateIdx = RateSwitchTable11B[1];
1586 else if (pAd->LatchRfRegs.Channel <= 14)
1588 *ppTable = RateSwitchTable11BG;
1589 *pTableSize = RateSwitchTable11BG[0];
1590 *pInitTxRateIdx = RateSwitchTable11BG[1];
1595 *ppTable = RateSwitchTable11G;
1596 *pTableSize = RateSwitchTable11G[0];
1597 *pInitTxRateIdx = RateSwitchTable11G[1];
1602 #endif // CONFIG_STA_SUPPORT //
1604 #ifdef DOT11_N_SUPPORT
1605 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1606 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1608 *ppTable = RateSwitchTable11BGN1S;
1609 *pTableSize = RateSwitchTable11BGN1S[0];
1610 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1615 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1616 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1618 if (pAd->LatchRfRegs.Channel <= 14)
1620 *ppTable = RateSwitchTable11BGN2S;
1621 *pTableSize = RateSwitchTable11BGN2S[0];
1622 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1627 *ppTable = RateSwitchTable11BGN2SForABand;
1628 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1629 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1635 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1637 *ppTable = RateSwitchTable11N1S;
1638 *pTableSize = RateSwitchTable11N1S[0];
1639 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1644 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1646 if (pAd->LatchRfRegs.Channel <= 14)
1648 *ppTable = RateSwitchTable11N2S;
1649 *pTableSize = RateSwitchTable11N2S[0];
1650 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1654 *ppTable = RateSwitchTable11N2SForABand;
1655 *pTableSize = RateSwitchTable11N2SForABand[0];
1656 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1661 #endif // DOT11_N_SUPPORT //
1662 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1663 if ((pEntry->RateLen == 4)
1664 #ifdef DOT11_N_SUPPORT
1665 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1666 #endif // DOT11_N_SUPPORT //
1669 *ppTable = RateSwitchTable11B;
1670 *pTableSize = RateSwitchTable11B[0];
1671 *pInitTxRateIdx = RateSwitchTable11B[1];
1676 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1677 if ((pEntry->RateLen > 8)
1678 #ifdef DOT11_N_SUPPORT
1679 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1680 #endif // DOT11_N_SUPPORT //
1683 *ppTable = RateSwitchTable11BG;
1684 *pTableSize = RateSwitchTable11BG[0];
1685 *pInitTxRateIdx = RateSwitchTable11BG[1];
1690 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1691 if ((pEntry->RateLen == 8)
1692 #ifdef DOT11_N_SUPPORT
1693 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1694 #endif // DOT11_N_SUPPORT //
1697 *ppTable = RateSwitchTable11G;
1698 *pTableSize = RateSwitchTable11G[0];
1699 *pInitTxRateIdx = RateSwitchTable11G[1];
1703 #ifdef DOT11_N_SUPPORT
1704 #endif // DOT11_N_SUPPORT //
1706 #ifdef CONFIG_STA_SUPPORT
1707 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1709 #ifdef DOT11_N_SUPPORT
1710 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1711 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1712 #endif // DOT11_N_SUPPORT //
1714 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1716 *ppTable = RateSwitchTable11B;
1717 *pTableSize = RateSwitchTable11B[0];
1718 *pInitTxRateIdx = RateSwitchTable11B[1];
1720 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1722 *ppTable = RateSwitchTable11G;
1723 *pTableSize = RateSwitchTable11G[0];
1724 *pInitTxRateIdx = RateSwitchTable11G[1];
1729 *ppTable = RateSwitchTable11BG;
1730 *pTableSize = RateSwitchTable11BG[0];
1731 *pInitTxRateIdx = RateSwitchTable11BG[1];
1735 #ifdef DOT11_N_SUPPORT
1736 if (pAd->LatchRfRegs.Channel <= 14)
1738 if (pAd->CommonCfg.TxStream == 1)
1740 *ppTable = RateSwitchTable11N1S;
1741 *pTableSize = RateSwitchTable11N1S[0];
1742 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1743 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1747 *ppTable = RateSwitchTable11N2S;
1748 *pTableSize = RateSwitchTable11N2S[0];
1749 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1750 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1755 if (pAd->CommonCfg.TxStream == 1)
1757 *ppTable = RateSwitchTable11N1S;
1758 *pTableSize = RateSwitchTable11N1S[0];
1759 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1760 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1764 *ppTable = RateSwitchTable11N2SForABand;
1765 *pTableSize = RateSwitchTable11N2SForABand[0];
1766 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1767 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1770 #endif // DOT11_N_SUPPORT //
1771 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1772 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1774 #endif // CONFIG_STA_SUPPORT //
1778 #ifdef CONFIG_STA_SUPPORT
1780 ==========================================================================
1782 This routine checks if there're other APs out there capable for
1783 roaming. Caller should call this routine only when Link up in INFRA mode
1784 and channel quality is below CQI_GOOD_THRESHOLD.
1786 IRQL = DISPATCH_LEVEL
1789 ==========================================================================
1791 VOID MlmeCheckForRoaming(
1792 IN PRTMP_ADAPTER pAd,
1796 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1799 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1800 // put all roaming candidates into RoamTab, and sort in RSSI order
1801 BssTableInit(pRoamTab);
1802 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1804 pBss = &pAd->ScanTab.BssEntry[i];
1806 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1807 continue; // AP disappear
1808 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1809 continue; // RSSI too weak. forget it.
1810 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1811 continue; // skip current AP
1812 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1813 continue; // only AP with stronger RSSI is eligible for roaming
1815 // AP passing all above rules is put into roaming candidate table
1816 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1817 pRoamTab->BssNr += 1;
1820 if (pRoamTab->BssNr > 0)
1822 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1823 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1825 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1826 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1827 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1828 RT28XX_MLME_HANDLER(pAd);
1831 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1835 ==========================================================================
1837 This routine checks if there're other APs out there capable for
1838 roaming. Caller should call this routine only when link up in INFRA mode
1839 and channel quality is below CQI_GOOD_THRESHOLD.
1841 IRQL = DISPATCH_LEVEL
1844 ==========================================================================
1846 VOID MlmeCheckForFastRoaming(
1847 IN PRTMP_ADAPTER pAd,
1851 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1854 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1855 // put all roaming candidates into RoamTab, and sort in RSSI order
1856 BssTableInit(pRoamTab);
1857 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1859 pBss = &pAd->ScanTab.BssEntry[i];
1861 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1862 continue; // RSSI too weak. forget it.
1863 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1864 continue; // skip current AP
1865 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1866 continue; // skip different SSID
1867 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1868 continue; // skip AP without better RSSI
1870 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));
1871 // AP passing all above rules is put into roaming candidate table
1872 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1873 pRoamTab->BssNr += 1;
1876 if (pRoamTab->BssNr > 0)
1878 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1879 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1881 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1882 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1883 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1884 RT28XX_MLME_HANDLER(pAd);
1887 // Maybe site survey required
1890 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1892 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1893 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1894 pAd->StaCfg.ScanCnt = 2;
1895 pAd->StaCfg.LastScanTime = Now;
1900 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1904 ==========================================================================
1906 This routine calculates TxPER, RxPER of the past N-sec period. And
1907 according to the calculation result, ChannelQuality is calculated here
1908 to decide if current AP is still doing the job.
1910 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1912 StaCfg.ChannelQuality - 0..100
1914 IRQL = DISPATCH_LEVEL
1916 NOTE: This routine decide channle quality based on RX CRC error ratio.
1917 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1918 is performed right before this routine, so that this routine can decide
1919 channel quality based on the most up-to-date information
1920 ==========================================================================
1922 VOID MlmeCalculateChannelQuality(
1923 IN PRTMP_ADAPTER pAd,
1926 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1930 ULONG BeaconLostTime = BEACON_LOST_TIME;
1932 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1933 // longer beacon lost time when carrier detection enabled
1934 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1936 BeaconLostTime = BEACON_LOST_TIME + BEACON_LOST_TIME/2;
1938 #endif // CARRIER_DETECTION_SUPPORT //
1940 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1943 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1945 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1946 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1954 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1955 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1959 // calculate RX PER - don't take RxPER into consideration if too few sample
1961 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1965 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1968 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1970 if (INFRA_ON(pAd) &&
1971 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1972 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1974 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1975 pAd->Mlme.ChannelQuality = 0;
1982 else if (MaxRssi < -90)
1985 NorRssi = (MaxRssi + 90) * 2;
1987 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1988 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1989 TX_WEIGHTING * (100 - TxPRR) +
1990 RX_WEIGHTING* (100 - RxPER)) / 100;
1991 if (pAd->Mlme.ChannelQuality >= 100)
1992 pAd->Mlme.ChannelQuality = 100;
1998 IN PRTMP_ADAPTER pAd,
1999 IN PMAC_TABLE_ENTRY pEntry,
2000 IN PRTMP_TX_RATE_SWITCH pTxRate)
2002 UCHAR MaxMode = MODE_OFDM;
2004 #ifdef DOT11_N_SUPPORT
2005 MaxMode = MODE_HTGREENFIELD;
2007 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
2008 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
2010 #endif // DOT11_N_SUPPORT //
2011 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
2013 if (pTxRate->CurrMCS < MCS_AUTO)
2014 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
2016 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
2017 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
2021 // If peer adhoc is b-only mode, we can't send 11g rate.
2022 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
2023 pEntry->HTPhyMode.field.STBC = STBC_NONE;
2026 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
2028 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
2029 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
2030 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
2032 // Patch speed error in status page
2033 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
2037 if (pTxRate->Mode <= MaxMode)
2038 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
2040 #ifdef DOT11_N_SUPPORT
2041 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
2042 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
2044 #endif // DOT11_N_SUPPORT //
2045 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
2047 #ifdef DOT11_N_SUPPORT
2048 // Reexam each bandwidth's SGI support.
2049 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
2051 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
2052 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
2053 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
2054 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
2057 // Turn RTS/CTS rate to 6Mbps.
2058 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
2060 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
2061 if (pAd->MacTab.fAnyBASession)
2063 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2067 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2070 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
2072 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
2073 if (pAd->MacTab.fAnyBASession)
2075 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2079 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2082 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
2084 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2087 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
2089 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2091 #endif // DOT11_N_SUPPORT //
2093 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
2094 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
2095 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
2096 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
2097 #ifdef DOT11_N_SUPPORT
2098 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
2099 pAd->WIFItestbed.bGreenField)
2100 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
2101 #endif // DOT11_N_SUPPORT //
2104 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
2108 ==========================================================================
2110 This routine calculates the acumulated TxPER of eaxh TxRate. And
2111 according to the calculation result, change CommonCfg.TxRate which
2112 is the stable TX Rate we expect the Radio situation could sustained.
2114 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
2118 IRQL = DISPATCH_LEVEL
2121 call this routine every second
2122 ==========================================================================
2124 VOID MlmeDynamicTxRateSwitching(
2125 IN PRTMP_ADAPTER pAd)
2127 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2128 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2129 ULONG TxErrorRatio = 0;
2130 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2131 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2133 UCHAR TableSize = 0;
2134 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2135 CHAR Rssi, RssiOffset = 0;
2136 TX_STA_CNT1_STRUC StaTx1;
2137 TX_STA_CNT0_STRUC TxStaCnt0;
2138 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2139 MAC_TABLE_ENTRY *pEntry;
2146 #endif // RALINK_ATE //
2148 /*if (pAd->Antenna.field.RxPath > 1)
2149 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2151 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
2154 // walk through MAC table, see if need to change AP's TX rate toward each entry
2156 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2158 pEntry = &pAd->MacTab.Content[i];
2160 // check if this entry need to switch rate automatically
2161 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2164 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2166 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2168 // Update statistic counter
2169 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2170 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2171 pAd->bUpdateBcnCntDone = TRUE;
2172 TxRetransmit = StaTx1.field.TxRetransmit;
2173 TxSuccess = StaTx1.field.TxSuccess;
2174 TxFailCount = TxStaCnt0.field.TxFailCount;
2175 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2177 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2178 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2179 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2180 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2181 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2182 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2184 // if no traffic in the past 1-sec period, don't change TX rate,
2185 // but clear all bad history. because the bad history may affect the next
2186 // Chariot throughput test
2187 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2188 pAd->RalinkCounters.OneSecTxRetryOkCount +
2189 pAd->RalinkCounters.OneSecTxFailCount;
2192 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2196 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2198 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2199 pEntry->OneSecTxRetryOkCount +
2200 pEntry->OneSecTxFailCount;
2203 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2206 CurrRateIdx = pEntry->CurrTxRateIndex;
2208 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2210 if (CurrRateIdx >= TableSize)
2212 CurrRateIdx = TableSize - 1;
2215 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2216 // So need to sync here.
2217 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2218 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2219 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2223 // Need to sync Real Tx rate and our record.
2224 // Then return for next DRS.
2225 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2226 pEntry->CurrTxRateIndex = InitTxRateIdx;
2227 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2229 // reset all OneSecTx counters
2230 RESET_ONE_SEC_TX_CNT(pEntry);
2234 // decide the next upgrade rate and downgrade rate, if any
2235 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2237 UpRateIdx = CurrRateIdx + 1;
2238 DownRateIdx = CurrRateIdx -1;
2240 else if (CurrRateIdx == 0)
2242 UpRateIdx = CurrRateIdx + 1;
2243 DownRateIdx = CurrRateIdx;
2245 else if (CurrRateIdx == (TableSize - 1))
2247 UpRateIdx = CurrRateIdx;
2248 DownRateIdx = CurrRateIdx - 1;
2251 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2253 #ifdef DOT11_N_SUPPORT
2254 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2256 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2257 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2260 #endif // DOT11_N_SUPPORT //
2262 TrainUp = pCurrTxRate->TrainUp;
2263 TrainDown = pCurrTxRate->TrainDown;
2266 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2269 // Keep the last time TxRateChangeAction status.
2271 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2276 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2277 // (criteria copied from RT2500 for Netopia case)
2279 if (TxTotalCnt <= 15)
2283 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2284 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2285 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2286 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2288 // check the existence and index of each needed MCS
2289 while (idx < pTable[0])
2291 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2293 if (pCurrTxRate->CurrMCS == MCS_0)
2297 else if (pCurrTxRate->CurrMCS == MCS_1)
2301 else if (pCurrTxRate->CurrMCS == MCS_2)
2305 else if (pCurrTxRate->CurrMCS == MCS_3)
2309 else if (pCurrTxRate->CurrMCS == MCS_4)
2313 else if (pCurrTxRate->CurrMCS == MCS_5)
2317 else if (pCurrTxRate->CurrMCS == MCS_6)
2321 //else if (pCurrTxRate->CurrMCS == MCS_7)
2322 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2326 else if (pCurrTxRate->CurrMCS == MCS_12)
2330 else if (pCurrTxRate->CurrMCS == MCS_13)
2334 else if (pCurrTxRate->CurrMCS == MCS_14)
2338 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2339 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
2343 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2347 else if (pCurrTxRate->CurrMCS == MCS_21)
2351 else if (pCurrTxRate->CurrMCS == MCS_22)
2355 else if (pCurrTxRate->CurrMCS == MCS_23)
2362 if (pAd->LatchRfRegs.Channel <= 14)
2364 if (pAd->NicConfig2.field.ExternalLNAForG)
2375 if (pAd->NicConfig2.field.ExternalLNAForA)
2384 #ifdef DOT11_N_SUPPORT
2386 if ((pTable == RateSwitchTable11BGN3S) ||
2387 (pTable == RateSwitchTable11N3S) ||
2388 (pTable == RateSwitchTable))
2389 {// N mode with 3 stream // 3*3
2390 if (MCS23 && (Rssi >= -70))
2392 else if (MCS22 && (Rssi >= -72))
2394 else if (MCS21 && (Rssi >= -76))
2396 else if (MCS20 && (Rssi >= -78))
2398 else if (MCS4 && (Rssi >= -82))
2400 else if (MCS3 && (Rssi >= -84))
2402 else if (MCS2 && (Rssi >= -86))
2404 else if (MCS1 && (Rssi >= -88))
2409 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2410 {// N mode with 2 stream
2411 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2413 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2415 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2417 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2419 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2421 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2423 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2425 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2430 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2431 {// N mode with 1 stream
2432 if (MCS7 && (Rssi > (-72+RssiOffset)))
2434 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2436 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2438 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2440 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2442 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2444 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2450 #endif // DOT11_N_SUPPORT //
2452 if (MCS7 && (Rssi > -70))
2454 else if (MCS6 && (Rssi > -74))
2456 else if (MCS5 && (Rssi > -78))
2458 else if (MCS4 && (Rssi > -82))
2460 else if (MCS4 == 0) // for B-only mode
2462 else if (MCS3 && (Rssi > -85))
2464 else if (MCS2 && (Rssi > -87))
2466 else if (MCS1 && (Rssi > -90))
2473 pEntry->CurrTxRateIndex = TxRateIdx;
2474 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2475 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2478 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2479 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2480 pEntry->fLastSecAccordingRSSI = TRUE;
2481 // reset all OneSecTx counters
2482 RESET_ONE_SEC_TX_CNT(pEntry);
2487 if (pEntry->fLastSecAccordingRSSI == TRUE)
2489 pEntry->fLastSecAccordingRSSI = FALSE;
2490 pEntry->LastSecTxRateChangeAction = 0;
2491 // reset all OneSecTx counters
2492 RESET_ONE_SEC_TX_CNT(pEntry);
2499 BOOLEAN bTrainUpDown = FALSE;
2501 pEntry->CurrTxRateStableTime ++;
2503 // downgrade TX quality if PER >= Rate-Down threshold
2504 if (TxErrorRatio >= TrainDown)
2506 bTrainUpDown = TRUE;
2507 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2509 // upgrade TX quality if PER <= Rate-Up threshold
2510 else if (TxErrorRatio <= TrainUp)
2512 bTrainUpDown = TRUE;
2513 bUpgradeQuality = TRUE;
2514 if (pEntry->TxQuality[CurrRateIdx])
2515 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2517 if (pEntry->TxRateUpPenalty)
2518 pEntry->TxRateUpPenalty --;
2519 else if (pEntry->TxQuality[UpRateIdx])
2520 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2523 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2527 // perform DRS - consider TxRate Down first, then rate up.
2528 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2530 pEntry->CurrTxRateIndex = DownRateIdx;
2532 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2534 pEntry->CurrTxRateIndex = UpRateIdx;
2539 // if rate-up happen, clear all bad history of all TX rates
2540 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2542 pEntry->CurrTxRateStableTime = 0;
2543 pEntry->TxRateUpPenalty = 0;
2544 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2545 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2546 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2549 // For TxRate fast train up
2551 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2553 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2555 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2557 bTxRateChanged = TRUE;
2559 // if rate-down happen, only clear DownRate's bad history
2560 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2562 pEntry->CurrTxRateStableTime = 0;
2563 pEntry->TxRateUpPenalty = 0; // no penalty
2564 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2565 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2566 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2569 // For TxRate fast train down
2571 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2573 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2575 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2577 bTxRateChanged = TRUE;
2581 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2582 bTxRateChanged = FALSE;
2585 pEntry->LastTxOkCount = TxSuccess;
2587 // reset all OneSecTx counters
2588 RESET_ONE_SEC_TX_CNT(pEntry);
2590 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2591 if (bTxRateChanged && pNextTxRate)
2593 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2599 ========================================================================
2600 Routine Description:
2601 Station side, Auto TxRate faster train up timer call back function.
2604 SystemSpecific1 - Not used.
2605 FunctionContext - Pointer to our Adapter context.
2606 SystemSpecific2 - Not used.
2607 SystemSpecific3 - Not used.
2612 ========================================================================
2614 VOID StaQuickResponeForRateUpExec(
2615 IN PVOID SystemSpecific1,
2616 IN PVOID FunctionContext,
2617 IN PVOID SystemSpecific2,
2618 IN PVOID SystemSpecific3)
2620 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2621 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2623 ULONG TxErrorRatio = 0;
2624 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2625 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2627 UCHAR TableSize = 0;
2628 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2629 TX_STA_CNT1_STRUC StaTx1;
2630 TX_STA_CNT0_STRUC TxStaCnt0;
2632 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2633 MAC_TABLE_ENTRY *pEntry;
2636 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2639 // walk through MAC table, see if need to change AP's TX rate toward each entry
2641 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2643 pEntry = &pAd->MacTab.Content[i];
2645 // check if this entry need to switch rate automatically
2646 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2649 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2650 if (pAd->Antenna.field.TxPath > 1)
2651 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2653 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2655 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2657 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2659 // decide the next upgrade rate and downgrade rate, if any
2660 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2662 UpRateIdx = CurrRateIdx + 1;
2663 DownRateIdx = CurrRateIdx -1;
2665 else if (CurrRateIdx == 0)
2667 UpRateIdx = CurrRateIdx + 1;
2668 DownRateIdx = CurrRateIdx;
2670 else if (CurrRateIdx == (TableSize - 1))
2672 UpRateIdx = CurrRateIdx;
2673 DownRateIdx = CurrRateIdx - 1;
2676 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2678 #ifdef DOT11_N_SUPPORT
2679 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2681 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2682 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2685 #endif // DOT11_N_SUPPORT //
2687 TrainUp = pCurrTxRate->TrainUp;
2688 TrainDown = pCurrTxRate->TrainDown;
2691 if (pAd->MacTab.Size == 1)
2693 // Update statistic counter
2694 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2695 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2697 TxRetransmit = StaTx1.field.TxRetransmit;
2698 TxSuccess = StaTx1.field.TxSuccess;
2699 TxFailCount = TxStaCnt0.field.TxFailCount;
2700 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2702 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2703 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2704 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2705 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2706 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2707 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2710 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2714 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2715 pEntry->OneSecTxRetryOkCount +
2716 pEntry->OneSecTxFailCount;
2719 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2724 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2725 // (criteria copied from RT2500 for Netopia case)
2727 if (TxTotalCnt <= 12)
2729 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2730 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2732 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2734 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2735 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2737 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2739 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2742 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2748 ULONG OneSecTxNoRetryOKRationCount;
2750 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2755 // downgrade TX quality if PER >= Rate-Down threshold
2756 if (TxErrorRatio >= TrainDown)
2758 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2761 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2763 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2765 // perform DRS - consider TxRate Down first, then rate up.
2766 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2768 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2770 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2771 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2776 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2778 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2782 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2784 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2789 // if rate-up happen, clear all bad history of all TX rates
2790 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2792 pAd->DrsCounters.TxRateUpPenalty = 0;
2793 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2794 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2796 // if rate-down happen, only clear DownRate's bad history
2797 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2799 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2801 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2802 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2803 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2807 bTxRateChanged = FALSE;
2810 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2811 if (bTxRateChanged && pNextTxRate)
2813 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2819 ==========================================================================
2821 This routine is executed periodically inside MlmePeriodicExec() after
2822 association with an AP.
2823 It checks if StaCfg.Psm is consistent with user policy (recorded in
2824 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2825 there're some conditions to consider:
2826 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2827 the time when Mibss==TRUE
2828 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2829 if outgoing traffic available in TxRing or MgmtRing.
2831 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2833 IRQL = DISPATCH_LEVEL
2835 ==========================================================================
2837 VOID MlmeCheckPsmChange(
2838 IN PRTMP_ADAPTER pAd,
2844 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2845 // 2. user wants either MAX_PSP or FAST_PSP
2846 // 3. but current psm is not in PWR_SAVE
2847 // 4. CNTL state machine is not doing SCANning
2848 // 5. no TX SUCCESS event for the past 1-sec period
2849 #ifdef NDIS51_MINIPORT
2850 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2851 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2854 PowerMode = pAd->StaCfg.WindowsPowerMode;
2856 if (INFRA_ON(pAd) &&
2857 (PowerMode != Ndis802_11PowerModeCAM) &&
2858 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2859 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2861 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2862 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2863 MlmeSetPsmBit(pAd, PWR_SAVE);
2864 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2866 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2870 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2875 // IRQL = PASSIVE_LEVEL
2876 // IRQL = DISPATCH_LEVEL
2878 IN PRTMP_ADAPTER pAd,
2881 AUTO_RSP_CFG_STRUC csr4;
2883 pAd->StaCfg.Psm = psm;
2884 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2885 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2886 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2887 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2889 #endif // CONFIG_STA_SUPPORT //
2892 // IRQL = DISPATCH_LEVEL
2893 VOID MlmeSetTxPreamble(
2894 IN PRTMP_ADAPTER pAd,
2895 IN USHORT TxPreamble)
2897 AUTO_RSP_CFG_STRUC csr4;
2900 // Always use Long preamble before verifiation short preamble functionality works well.
2901 // Todo: remove the following line if short preamble functionality works
2903 //TxPreamble = Rt802_11PreambleLong;
2905 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2906 if (TxPreamble == Rt802_11PreambleLong)
2908 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2909 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2910 csr4.field.AutoResponderPreamble = 0;
2914 // NOTE: 1Mbps should always use long preamble
2915 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2916 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2917 csr4.field.AutoResponderPreamble = 1;
2920 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2924 ==========================================================================
2926 Update basic rate bitmap
2927 ==========================================================================
2930 VOID UpdateBasicRateBitmap(
2931 IN PRTMP_ADAPTER pAdapter)
2934 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2935 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2936 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2937 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2938 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2941 /* if A mode, always use fix BasicRateBitMap */
2942 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2943 if (pAdapter->CommonCfg.Channel > 14)
2944 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2947 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2949 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2953 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2959 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2961 if (bitmap & (1 << i))
2963 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2965 if (sup_p[j] == rate[i])
2970 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2972 if (ext_p[j] == rate[i])
2978 } /* End of UpdateBasicRateBitmap */
2980 // IRQL = PASSIVE_LEVEL
2981 // IRQL = DISPATCH_LEVEL
2982 // bLinkUp is to identify the inital link speed.
2983 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2984 VOID MlmeUpdateTxRates(
2985 IN PRTMP_ADAPTER pAd,
2990 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2991 UCHAR MinSupport = RATE_54;
2992 ULONG BasicRateBitmap = 0;
2993 UCHAR CurrBasicRate = RATE_1;
2994 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2995 PHTTRANSMIT_SETTING pHtPhy = NULL;
2996 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2997 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2998 BOOLEAN *auto_rate_cur_p;
2999 UCHAR HtMcs = MCS_AUTO;
3001 // find max desired rate
3002 UpdateBasicRateBitmap(pAd);
3005 auto_rate_cur_p = NULL;
3006 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3008 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
3010 case 2: Rate = RATE_1; num++; break;
3011 case 4: Rate = RATE_2; num++; break;
3012 case 11: Rate = RATE_5_5; num++; break;
3013 case 22: Rate = RATE_11; num++; break;
3014 case 12: Rate = RATE_6; num++; break;
3015 case 18: Rate = RATE_9; num++; break;
3016 case 24: Rate = RATE_12; num++; break;
3017 case 36: Rate = RATE_18; num++; break;
3018 case 48: Rate = RATE_24; num++; break;
3019 case 72: Rate = RATE_36; num++; break;
3020 case 96: Rate = RATE_48; num++; break;
3021 case 108: Rate = RATE_54; num++; break;
3022 //default: Rate = RATE_1; break;
3024 if (MaxDesire < Rate) MaxDesire = Rate;
3027 //===========================================================================
3028 //===========================================================================
3030 #ifdef CONFIG_STA_SUPPORT
3031 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3033 pHtPhy = &pAd->StaCfg.HTPhyMode;
3034 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3035 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3037 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3038 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
3040 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
3041 (pAd->CommonCfg.PhyMode == PHY_11B) &&
3042 (MaxDesire > RATE_11))
3044 MaxDesire = RATE_11;
3047 #endif // CONFIG_STA_SUPPORT //
3049 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
3050 pMinHtPhy->word = 0;
3051 pMaxHtPhy->word = 0;
3054 // Auto rate switching is enabled only if more than one DESIRED RATES are
3055 // specified; otherwise disabled
3058 *auto_rate_cur_p = FALSE;
3062 *auto_rate_cur_p = TRUE;
3066 if (HtMcs != MCS_AUTO)
3068 *auto_rate_cur_p = FALSE;
3072 *auto_rate_cur_p = TRUE;
3076 #ifdef CONFIG_STA_SUPPORT
3077 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3079 pSupRate = &pAd->StaActive.SupRate[0];
3080 pExtRate = &pAd->StaActive.ExtRate[0];
3081 SupRateLen = pAd->StaActive.SupRateLen;
3082 ExtRateLen = pAd->StaActive.ExtRateLen;
3085 #endif // CONFIG_STA_SUPPORT //
3087 pSupRate = &pAd->CommonCfg.SupRate[0];
3088 pExtRate = &pAd->CommonCfg.ExtRate[0];
3089 SupRateLen = pAd->CommonCfg.SupRateLen;
3090 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3093 // find max supported rate
3094 for (i=0; i<SupRateLen; i++)
3096 switch (pSupRate[i] & 0x7f)
3098 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3099 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3100 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3101 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3102 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3103 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3104 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3105 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3106 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3107 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3108 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3109 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3110 default: Rate = RATE_1; break;
3112 if (MaxSupport < Rate) MaxSupport = Rate;
3114 if (MinSupport > Rate) MinSupport = Rate;
3117 for (i=0; i<ExtRateLen; i++)
3119 switch (pExtRate[i] & 0x7f)
3121 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3122 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3123 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3124 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3125 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3126 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3127 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3128 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3129 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3130 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3131 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3132 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3133 default: Rate = RATE_1; break;
3135 if (MaxSupport < Rate) MaxSupport = Rate;
3137 if (MinSupport > Rate) MinSupport = Rate;
3140 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3142 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3143 // the DURATION field of outgoing uniicast DATA/MGMT frame
3144 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3146 if (BasicRateBitmap & (0x01 << i))
3147 CurrBasicRate = (UCHAR)i;
3148 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3151 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3152 // max tx rate = min {max desire rate, max supported rate}
3153 if (MaxSupport < MaxDesire)
3154 pAd->CommonCfg.MaxTxRate = MaxSupport;
3156 pAd->CommonCfg.MaxTxRate = MaxDesire;
3158 pAd->CommonCfg.MinTxRate = MinSupport;
3159 if (*auto_rate_cur_p)
3162 #ifdef CONFIG_STA_SUPPORT
3163 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3164 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3165 #endif // CONFIG_STA_SUPPORT //
3166 if (bLinkUp == TRUE)
3167 pAd->CommonCfg.TxRate = RATE_24;
3169 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3172 pAd->CommonCfg.TxRate = RATE_11;
3174 pAd->CommonCfg.TxRate = RATE_24;
3176 // should never exceed MaxTxRate (consider 11B-only mode)
3177 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3178 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3180 pAd->CommonCfg.TxRateIndex = 0;
3184 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3185 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3186 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3188 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3189 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3190 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3191 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3194 if (pAd->CommonCfg.TxRate <= RATE_11)
3196 pMaxHtPhy->field.MODE = MODE_CCK;
3197 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3198 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3202 pMaxHtPhy->field.MODE = MODE_OFDM;
3203 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3204 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3205 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3207 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3210 pHtPhy->word = (pMaxHtPhy->word);
3211 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3213 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3214 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3215 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3219 switch (pAd->CommonCfg.PhyMode)
3221 case PHY_11BG_MIXED:
3223 #ifdef DOT11_N_SUPPORT
3224 case PHY_11BGN_MIXED:
3225 #endif // DOT11_N_SUPPORT //
3226 pAd->CommonCfg.MlmeRate = RATE_1;
3227 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3228 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3229 pAd->CommonCfg.RtsRate = RATE_11;
3233 #ifdef DOT11_N_SUPPORT
3234 case PHY_11AGN_MIXED:
3235 case PHY_11GN_MIXED:
3237 case PHY_11AN_MIXED:
3239 #endif // DOT11_N_SUPPORT //
3240 pAd->CommonCfg.MlmeRate = RATE_6;
3241 pAd->CommonCfg.RtsRate = RATE_6;
3242 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3243 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3245 case PHY_11ABG_MIXED:
3246 #ifdef DOT11_N_SUPPORT
3247 case PHY_11ABGN_MIXED:
3248 #endif // DOT11_N_SUPPORT //
3249 if (pAd->CommonCfg.Channel <= 14)
3251 pAd->CommonCfg.MlmeRate = RATE_1;
3252 pAd->CommonCfg.RtsRate = RATE_1;
3253 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3254 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3258 pAd->CommonCfg.MlmeRate = RATE_6;
3259 pAd->CommonCfg.RtsRate = RATE_6;
3260 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3261 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3265 pAd->CommonCfg.MlmeRate = RATE_6;
3266 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3267 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3268 pAd->CommonCfg.RtsRate = RATE_1;
3272 // Keep Basic Mlme Rate.
3274 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3275 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3276 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3278 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3279 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3282 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3283 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3284 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3285 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3286 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3287 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3288 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 ));
3291 #ifdef DOT11_N_SUPPORT
3293 ==========================================================================
3295 This function update HT Rate setting.
3296 Input Wcid value is valid for 2 case :
3297 1. it's used for Station in infra mode that copy AP rate to Mactable.
3298 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3300 IRQL = DISPATCH_LEVEL
3302 ==========================================================================
3304 VOID MlmeUpdateHtTxRates(
3305 IN PRTMP_ADAPTER pAd,
3308 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3310 RT_HT_CAPABILITY *pRtHtCap = NULL;
3311 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3314 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3315 PHTTRANSMIT_SETTING pHtPhy = NULL;
3316 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3317 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3318 BOOLEAN *auto_rate_cur_p;
3320 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3322 auto_rate_cur_p = NULL;
3324 #ifdef CONFIG_STA_SUPPORT
3325 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3327 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3328 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3329 pHtPhy = &pAd->StaCfg.HTPhyMode;
3330 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3331 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3333 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3335 #endif // CONFIG_STA_SUPPORT //
3337 #ifdef CONFIG_STA_SUPPORT
3338 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3340 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3343 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3344 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3345 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3346 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3347 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3348 pMaxHtPhy->field.STBC = STBC_USE;
3350 pMaxHtPhy->field.STBC = STBC_NONE;
3353 #endif // CONFIG_STA_SUPPORT //
3355 if (pDesireHtPhy->bHtEnable == FALSE)
3358 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3359 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3360 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3361 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3362 pMaxHtPhy->field.STBC = STBC_USE;
3364 pMaxHtPhy->field.STBC = STBC_NONE;
3367 // Decide MAX ht rate.
3368 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3369 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3371 pMaxHtPhy->field.MODE = MODE_HTMIX;
3373 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3374 pMaxHtPhy->field.BW = BW_40;
3376 pMaxHtPhy->field.BW = BW_20;
3378 if (pMaxHtPhy->field.BW == BW_20)
3379 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3381 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3383 for (i=23; i>=0; i--) // 3*3
3386 bitmask = (1<<(i-(j*8)));
3388 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3390 pMaxHtPhy->field.MCS = i;
3398 // Copy MIN ht rate. rt2860???
3399 pMinHtPhy->field.BW = BW_20;
3400 pMinHtPhy->field.MCS = 0;
3401 pMinHtPhy->field.STBC = 0;
3402 pMinHtPhy->field.ShortGI = 0;
3403 //If STA assigns fixed rate. update to fixed here.
3404 #ifdef CONFIG_STA_SUPPORT
3405 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3407 if (pDesireHtPhy->MCSSet[4] != 0)
3409 pMaxHtPhy->field.MCS = 32;
3410 pMinHtPhy->field.MCS = 32;
3411 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3414 for (i=23; (CHAR)i >= 0; i--) // 3*3
3417 bitmask = (1<<(i-(j*8)));
3418 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3420 pMaxHtPhy->field.MCS = i;
3421 pMinHtPhy->field.MCS = i;
3428 #endif // CONFIG_STA_SUPPORT //
3432 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3433 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3434 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3435 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3436 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3438 // use default now. rt2860
3439 if (pDesireHtPhy->MCSSet[0] != 0xff)
3440 *auto_rate_cur_p = FALSE;
3442 *auto_rate_cur_p = TRUE;
3444 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3445 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3446 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3447 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3449 #endif // DOT11_N_SUPPORT //
3451 // IRQL = DISPATCH_LEVEL
3453 IN PRTMP_ADAPTER pAd)
3455 RT28XX_MLME_RADIO_OFF(pAd);
3458 // IRQL = DISPATCH_LEVEL
3460 IN PRTMP_ADAPTER pAd)
3462 RT28XX_MLME_RADIO_ON(pAd);
3465 // ===========================================================================================
3467 // ===========================================================================================
3470 /*! \brief initialize BSS table
3471 * \param p_tab pointer to the table
3476 IRQL = PASSIVE_LEVEL
3477 IRQL = DISPATCH_LEVEL
3486 Tab->BssOverlapNr = 0;
3487 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3489 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3490 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3494 #ifdef DOT11_N_SUPPORT
3496 IN PRTMP_ADAPTER pAd,
3501 Tab->numAsOriginator = 0;
3502 Tab->numAsRecipient = 0;
3503 NdisAllocateSpinLock(&pAd->BATabLock);
3504 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3506 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3507 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3509 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3511 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3514 #endif // DOT11_N_SUPPORT //
3516 /*! \brief search the BSS table by SSID
3517 * \param p_tab pointer to the bss table
3518 * \param ssid SSID string
3519 * \return index of the table, BSS_NOT_FOUND if not in the table
3522 * \note search by sequential search
3524 IRQL = DISPATCH_LEVEL
3527 ULONG BssTableSearch(
3534 for (i = 0; i < Tab->BssNr; i++)
3537 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3538 // We should distinguish this case.
3540 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3541 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3542 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3547 return (ULONG)BSS_NOT_FOUND;
3550 ULONG BssSsidTableSearch(
3559 for (i = 0; i < Tab->BssNr; i++)
3562 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3563 // We should distinguish this case.
3565 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3566 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3567 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3568 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3573 return (ULONG)BSS_NOT_FOUND;
3576 ULONG BssTableSearchWithSSID(
3585 for (i = 0; i < Tab->BssNr; i++)
3587 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3588 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3589 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3590 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3591 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3592 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3597 return (ULONG)BSS_NOT_FOUND;
3600 // IRQL = DISPATCH_LEVEL
3601 VOID BssTableDeleteEntry(
3602 IN OUT BSS_TABLE *Tab,
3608 for (i = 0; i < Tab->BssNr; i++)
3610 if ((Tab->BssEntry[i].Channel == Channel) &&
3611 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3613 for (j = i; j < Tab->BssNr - 1; j++)
3615 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3617 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3624 #ifdef DOT11_N_SUPPORT
3626 ========================================================================
3627 Routine Description:
3628 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3631 // IRQL = DISPATCH_LEVEL
3632 ========================================================================
3634 VOID BATableDeleteORIEntry(
3635 IN OUT PRTMP_ADAPTER pAd,
3636 IN BA_ORI_ENTRY *pBAORIEntry)
3639 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3641 NdisAcquireSpinLock(&pAd->BATabLock);
3642 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3644 pAd->BATable.numAsOriginator -= 1;
3645 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3646 // Erase Bitmap flag.
3648 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3649 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3650 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3651 pBAORIEntry->Token = 1;
3652 // Not clear Sequence here.
3653 NdisReleaseSpinLock(&pAd->BATabLock);
3656 #endif // DOT11_N_SUPPORT //
3664 IRQL = DISPATCH_LEVEL
3668 IN PRTMP_ADAPTER pAd,
3669 OUT BSS_ENTRY *pBss,
3674 IN USHORT BeaconPeriod,
3675 IN PCF_PARM pCfParm,
3677 IN USHORT CapabilityInfo,
3679 IN UCHAR SupRateLen,
3681 IN UCHAR ExtRateLen,
3682 IN HT_CAPABILITY_IE *pHtCapability,
3683 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3684 IN UCHAR HtCapabilityLen,
3685 IN UCHAR AddHtInfoLen,
3686 IN UCHAR NewExtChanOffset,
3689 IN LARGE_INTEGER TimeStamp,
3691 IN PEDCA_PARM pEdcaParm,
3692 IN PQOS_CAPABILITY_PARM pQosCapability,
3693 IN PQBSS_LOAD_PARM pQbssLoad,
3694 IN USHORT LengthVIE,
3695 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3697 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3698 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3702 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3703 // Or send beacon /probe response with SSID len matching real SSID length,
3704 // but SSID is all zero. such as "00-00-00-00" with length 4.
3705 // We have to prevent this case overwrite correct table
3706 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3708 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3709 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3710 pBss->SsidLen = SsidLen;
3716 pBss->BssType = BssType;
3717 pBss->BeaconPeriod = BeaconPeriod;
3718 if (BssType == BSS_INFRA)
3720 if (pCfParm->bValid)
3722 pBss->CfpCount = pCfParm->CfpCount;
3723 pBss->CfpPeriod = pCfParm->CfpPeriod;
3724 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3725 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3730 pBss->AtimWin = AtimWin;
3733 pBss->CapabilityInfo = CapabilityInfo;
3734 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3735 // Combine with AuthMode, they will decide the connection methods.
3736 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3737 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3738 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3739 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3741 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3742 pBss->SupRateLen = SupRateLen;
3743 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3744 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3745 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3746 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3747 pBss->NewExtChanOffset = NewExtChanOffset;
3748 pBss->ExtRateLen = ExtRateLen;
3749 pBss->Channel = Channel;
3750 pBss->CentralChannel = Channel;
3752 // Update CkipFlag. if not exists, the value is 0x0
3753 pBss->CkipFlag = CkipFlag;
3755 // New for microsoft Fixed IEs
3756 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3757 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3758 pBss->FixIEs.Capabilities = CapabilityInfo;
3760 // New for microsoft Variable IEs
3763 pBss->VarIELen = LengthVIE;
3764 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3771 pBss->AddHtInfoLen = 0;
3772 pBss->HtCapabilityLen = 0;
3773 #ifdef DOT11_N_SUPPORT
3774 if (HtCapabilityLen> 0)
3776 pBss->HtCapabilityLen = HtCapabilityLen;
3777 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3778 if (AddHtInfoLen > 0)
3780 pBss->AddHtInfoLen = AddHtInfoLen;
3781 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3783 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3785 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3787 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3789 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3793 #endif // DOT11_N_SUPPORT //
3795 BssCipherParse(pBss);
3799 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3801 pBss->EdcaParm.bValid = FALSE;
3803 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3805 pBss->QosCapability.bValid = FALSE;
3807 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3809 pBss->QbssLoad.bValid = FALSE;
3811 #ifdef CONFIG_STA_SUPPORT
3812 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3818 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3819 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3820 #ifdef EXT_BUILD_CHANNEL_LIST
3821 NdisZeroMemory(&pBss->CountryString[0], 3);
3822 pBss->bHasCountryIE = FALSE;
3823 #endif // EXT_BUILD_CHANNEL_LIST //
3824 pEid = (PEID_STRUCT) pVIE;
3825 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3830 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3832 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3834 pBss->WpaIE.IELen = 0;
3837 pBss->WpaIE.IELen = pEid->Len + 2;
3838 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3842 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3844 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3846 pBss->RsnIE.IELen = 0;
3849 pBss->RsnIE.IELen = pEid->Len + 2;
3850 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3853 #ifdef EXT_BUILD_CHANNEL_LIST
3855 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3856 pBss->bHasCountryIE = TRUE;
3858 #endif // EXT_BUILD_CHANNEL_LIST //
3860 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3861 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3864 #endif // CONFIG_STA_SUPPORT //
3868 * \brief insert an entry into the bss table
3869 * \param p_tab The BSS table
3870 * \param Bssid BSSID
3872 * \param ssid_len Length of SSID
3874 * \param beacon_period
3881 * \param channel_idx
3885 * \note If SSID is identical, the old entry will be replaced by the new one
3887 IRQL = DISPATCH_LEVEL
3890 ULONG BssTableSetEntry(
3891 IN PRTMP_ADAPTER pAd,
3897 IN USHORT BeaconPeriod,
3900 IN USHORT CapabilityInfo,
3902 IN UCHAR SupRateLen,
3904 IN UCHAR ExtRateLen,
3905 IN HT_CAPABILITY_IE *pHtCapability,
3906 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3907 IN UCHAR HtCapabilityLen,
3908 IN UCHAR AddHtInfoLen,
3909 IN UCHAR NewExtChanOffset,
3912 IN LARGE_INTEGER TimeStamp,
3914 IN PEDCA_PARM pEdcaParm,
3915 IN PQOS_CAPABILITY_PARM pQosCapability,
3916 IN PQBSS_LOAD_PARM pQbssLoad,
3917 IN USHORT LengthVIE,
3918 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3922 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3923 if (Idx == BSS_NOT_FOUND)
3925 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3928 // It may happen when BSS Table was full.
3929 // The desired AP will not be added into BSS Table
3930 // In this case, if we found the desired AP then overwrite BSS Table.
3932 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3934 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3935 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3937 Idx = Tab->BssOverlapNr;
3938 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3939 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3940 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3941 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3947 return BSS_NOT_FOUND;
3951 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3952 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3953 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3958 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3959 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3960 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3966 #ifdef CONFIG_STA_SUPPORT
3967 #ifdef DOT11_N_SUPPORT
3968 #ifdef DOT11N_DRAFT3
3970 IN PRTMP_ADAPTER pAd)
3974 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3975 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3977 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3978 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3981 ULONG TriEventTableSetEntry(
3982 IN PRTMP_ADAPTER pAd,
3983 OUT TRIGGER_EVENT_TAB *Tab,
3985 IN HT_CAPABILITY_IE *pHtCapability,
3986 IN UCHAR HtCapabilityLen,
3991 if (HtCapabilityLen == 0)
3993 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3995 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3996 Tab->EventA[Tab->EventANo].bValid = TRUE;
3997 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3998 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
4001 // Beacon has Regulatory class IE. So use beacon's
4002 Tab->EventA[Tab->EventANo].RegClass = RegClass;
4006 // Use Station's Regulatory class instead.
4007 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
4009 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
4011 Tab->EventA[Tab->EventANo].RegClass = 32;
4013 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
4014 Tab->EventA[Tab->EventANo].RegClass = 33;
4017 Tab->EventA[Tab->EventANo].RegClass = ??;
4024 else if (pHtCapability->HtCapInfo.Intolerant40)
4026 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
4032 ========================================================================
4033 Routine Description:
4034 Trigger Event table Maintainence called once every second.
4037 // IRQL = DISPATCH_LEVEL
4038 ========================================================================
4040 VOID TriEventCounterMaintenance(
4041 IN PRTMP_ADAPTER pAd)
4044 BOOLEAN bNotify = FALSE;
4045 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
4047 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
4049 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
4050 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
4052 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
4053 pAd->CommonCfg.TriggerEventTab.EventANo --;
4054 // Need to send 20/40 Coexistence Notify frame if has status change.
4059 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
4061 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
4062 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
4066 if (bNotify == TRUE)
4067 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
4069 #endif // DOT11N_DRAFT3 //
4070 #endif // DOT11_N_SUPPORT //
4072 // IRQL = DISPATCH_LEVEL
4073 VOID BssTableSsidSort(
4074 IN PRTMP_ADAPTER pAd,
4075 OUT BSS_TABLE *OutTab,
4080 BssTableInit(OutTab);
4082 for (i = 0; i < pAd->ScanTab.BssNr; i++)
4084 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
4085 BOOLEAN bIsHiddenApIncluded = FALSE;
4087 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
4088 (pAd->MlmeAux.Channel > 14) &&
4089 RadarChannelCheck(pAd, pInBss->Channel))
4090 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
4091 || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
4092 #endif // CARRIER_DETECTION_SUPPORT //
4096 bIsHiddenApIncluded = TRUE;
4099 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
4100 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
4102 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4105 #ifdef EXT_BUILD_CHANNEL_LIST
4106 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
4107 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
4108 (pInBss->bHasCountryIE == FALSE))
4110 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
4113 #endif // EXT_BUILD_CHANNEL_LIST //
4115 #ifdef DOT11_N_SUPPORT
4116 // 2.4G/5G N only mode
4117 if ((pInBss->HtCapabilityLen == 0) &&
4118 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4120 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4123 #endif // DOT11_N_SUPPORT //
4126 // Check the Authmode first
4127 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4129 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4130 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4134 // Check cipher suite, AP must have more secured cipher than station setting
4135 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4137 // If it's not mixed mode, we should only let BSS pass with the same encryption
4138 if (pInBss->WPA.bMixMode == FALSE)
4139 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4142 // check group cipher
4143 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4144 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4145 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
4148 // check pairwise cipher, skip if none matched
4149 // If profile set to AES, let it pass without question.
4150 // If profile set to TKIP, we must find one mateched
4151 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4152 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4153 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4156 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4158 // If it's not mixed mode, we should only let BSS pass with the same encryption
4159 if (pInBss->WPA2.bMixMode == FALSE)
4160 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4163 // check group cipher
4164 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4165 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4166 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
4169 // check pairwise cipher, skip if none matched
4170 // If profile set to AES, let it pass without question.
4171 // If profile set to TKIP, we must find one mateched
4172 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4173 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4174 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4178 // Bss Type matched, SSID matched.
4179 // We will check wepstatus for qualification Bss
4180 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4182 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4184 // For the SESv2 case, we will not qualify WepStatus.
4190 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4191 // It definitely will fail. So, skip it.
4192 // CCX also require not even try to connect it!!
4196 #ifdef DOT11_N_SUPPORT
4197 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4198 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4199 if ((pInBss->CentralChannel != pInBss->Channel) &&
4200 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4202 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4204 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4206 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4210 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4216 #endif // DOT11_N_SUPPORT //
4218 // copy matching BSS from InTab to OutTab
4219 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4223 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4225 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4228 #ifdef DOT11_N_SUPPORT
4229 // 2.4G/5G N only mode
4230 if ((pInBss->HtCapabilityLen == 0) &&
4231 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4233 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4236 #endif // DOT11_N_SUPPORT //
4239 // Check the Authmode first
4240 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4242 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4243 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4247 // Check cipher suite, AP must have more secured cipher than station setting
4248 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4250 // If it's not mixed mode, we should only let BSS pass with the same encryption
4251 if (pInBss->WPA.bMixMode == FALSE)
4252 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4255 // check group cipher
4256 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4259 // check pairwise cipher, skip if none matched
4260 // If profile set to AES, let it pass without question.
4261 // If profile set to TKIP, we must find one mateched
4262 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4263 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4264 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4267 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4269 // If it's not mixed mode, we should only let BSS pass with the same encryption
4270 if (pInBss->WPA2.bMixMode == FALSE)
4271 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4274 // check group cipher
4275 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4278 // check pairwise cipher, skip if none matched
4279 // If profile set to AES, let it pass without question.
4280 // If profile set to TKIP, we must find one mateched
4281 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4282 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4283 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4287 // Bss Type matched, SSID matched.
4288 // We will check wepstatus for qualification Bss
4289 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4292 #ifdef DOT11_N_SUPPORT
4293 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4294 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4295 if ((pInBss->CentralChannel != pInBss->Channel) &&
4296 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4298 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4300 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4302 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4305 #endif // DOT11_N_SUPPORT //
4307 // copy matching BSS from InTab to OutTab
4308 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4313 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4317 BssTableSortByRssi(OutTab);
4321 // IRQL = DISPATCH_LEVEL
4322 VOID BssTableSortByRssi(
4323 IN OUT BSS_TABLE *OutTab)
4328 for (i = 0; i < OutTab->BssNr - 1; i++)
4330 for (j = i+1; j < OutTab->BssNr; j++)
4332 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4334 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4335 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4336 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4341 #endif // CONFIG_STA_SUPPORT //
4344 VOID BssCipherParse(
4345 IN OUT PBSS_ENTRY pBss)
4349 PRSN_IE_HEADER_STRUCT pRsnHeader;
4350 PCIPHER_SUITE_STRUCT pCipher;
4351 PAKM_SUITE_STRUCT pAKM;
4354 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4357 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4361 pBss->WepStatus = Ndis802_11WEPEnabled;
4365 pBss->WepStatus = Ndis802_11WEPDisabled;
4367 // Set default to disable & open authentication before parsing variable IE
4368 pBss->AuthMode = Ndis802_11AuthModeOpen;
4369 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4372 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4373 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4374 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4375 pBss->WPA.RsnCapability = 0;
4376 pBss->WPA.bMixMode = FALSE;
4378 // Init WPA2 setting
4379 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4380 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4381 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4382 pBss->WPA2.RsnCapability = 0;
4383 pBss->WPA2.bMixMode = FALSE;
4386 Length = (INT) pBss->VarIELen;
4390 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4391 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4392 pEid = (PEID_STRUCT) pTmp;
4396 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4397 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4403 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4404 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4405 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4406 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4409 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4410 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4411 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4414 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4415 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4416 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4422 // if Cisco IE_WPA, break
4425 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4430 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4432 // if unsupported vendor specific IE
4435 // Skip OUI, version, and multicast suite
4436 // This part should be improved in the future when AP supported multiple cipher suite.
4437 // For now, it's OK since almost all APs have fixed cipher suite supported.
4438 // pTmp = (PUCHAR) pEid->Octet;
4441 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4449 // Parse group cipher
4453 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4456 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4459 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4462 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4467 // number of unicast suite
4470 // skip all unicast cipher suites
4471 //Count = *(PUSHORT) pTmp;
4472 Count = (pTmp[1]<<8) + pTmp[0];
4473 pTmp += sizeof(USHORT);
4475 // Parsing all unicast cipher suite
4480 TmpCipher = Ndis802_11WEPDisabled;
4484 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4485 TmpCipher = Ndis802_11Encryption1Enabled;
4488 TmpCipher = Ndis802_11Encryption2Enabled;
4491 TmpCipher = Ndis802_11Encryption3Enabled;
4496 if (TmpCipher > pBss->WPA.PairCipher)
4498 // Move the lower cipher suite to PairCipherAux
4499 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4500 pBss->WPA.PairCipher = TmpCipher;
4504 pBss->WPA.PairCipherAux = TmpCipher;
4510 // 4. get AKM suite counts
4511 //Count = *(PUSHORT) pTmp;
4512 Count = (pTmp[1]<<8) + pTmp[0];
4513 pTmp += sizeof(USHORT);
4519 // Set AP support WPA mode
4520 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4521 pBss->AuthMode = Ndis802_11AuthModeWPA;
4523 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4526 // Set AP support WPA mode
4527 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4528 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4530 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4537 // Fixed for WPA-None
4538 if (pBss->BssType == BSS_ADHOC)
4540 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4541 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4542 pBss->WepStatus = pBss->WPA.GroupCipher;
4543 // Patched bugs for old driver
4544 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4545 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4548 pBss->WepStatus = pBss->WPA.PairCipher;
4550 // Check the Pair & Group, if different, turn on mixed mode flag
4551 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4552 pBss->WPA.bMixMode = TRUE;
4557 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4559 // 0. Version must be 1
4560 if (le2cpu16(pRsnHeader->Version) != 1)
4562 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4564 // 1. Check group cipher
4565 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4566 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4569 // Parse group cipher
4570 switch (pCipher->Type)
4573 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4576 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4579 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4582 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4587 // set to correct offset for next parsing
4588 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4590 // 2. Get pairwise cipher counts
4591 //Count = *(PUSHORT) pTmp;
4592 Count = (pTmp[1]<<8) + pTmp[0];
4593 pTmp += sizeof(USHORT);
4595 // 3. Get pairwise cipher
4596 // Parsing all unicast cipher suite
4600 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4601 TmpCipher = Ndis802_11WEPDisabled;
4602 switch (pCipher->Type)
4605 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4606 TmpCipher = Ndis802_11Encryption1Enabled;
4609 TmpCipher = Ndis802_11Encryption2Enabled;
4612 TmpCipher = Ndis802_11Encryption3Enabled;
4617 if (TmpCipher > pBss->WPA2.PairCipher)
4619 // Move the lower cipher suite to PairCipherAux
4620 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4621 pBss->WPA2.PairCipher = TmpCipher;
4625 pBss->WPA2.PairCipherAux = TmpCipher;
4627 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4631 // 4. get AKM suite counts
4632 //Count = *(PUSHORT) pTmp;
4633 Count = (pTmp[1]<<8) + pTmp[0];
4634 pTmp += sizeof(USHORT);
4636 // 5. Get AKM ciphers
4637 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4638 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4644 // Set AP support WPA mode
4645 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4646 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4648 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4651 // Set AP support WPA mode
4652 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4653 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4655 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4660 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4662 // Fixed for WPA-None
4663 if (pBss->BssType == BSS_ADHOC)
4665 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4666 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4667 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4668 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4669 pBss->WepStatus = pBss->WPA.GroupCipher;
4670 // Patched bugs for old driver
4671 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4672 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4674 pBss->WepStatus = pBss->WPA2.PairCipher;
4676 // 6. Get RSN capability
4677 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4678 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4679 pTmp += sizeof(USHORT);
4681 // Check the Pair & Group, if different, turn on mixed mode flag
4682 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4683 pBss->WPA2.bMixMode = TRUE;
4689 Length -= (pEid->Len + 2);
4693 // ===========================================================================================
4695 // ===========================================================================================
4697 /*! \brief generates a random mac address value for IBSS BSSID
4698 * \param Addr the bssid location
4703 VOID MacAddrRandomBssid(
4704 IN PRTMP_ADAPTER pAd,
4709 for (i = 0; i < MAC_ADDR_LEN; i++)
4711 pAddr[i] = RandomByte(pAd);
4714 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4717 /*! \brief init the management mac frame header
4718 * \param p_hdr mac header
4719 * \param subtype subtype of the frame
4720 * \param p_ds destination address, don't care if it is a broadcast address
4722 * \pre the station has the following information in the pAd->StaCfg
4726 * \note this function initializes the following field
4728 IRQL = PASSIVE_LEVEL
4729 IRQL = DISPATCH_LEVEL
4732 VOID MgtMacHeaderInit(
4733 IN PRTMP_ADAPTER pAd,
4734 IN OUT PHEADER_802_11 pHdr80211,
4740 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4742 pHdr80211->FC.Type = BTYPE_MGMT;
4743 pHdr80211->FC.SubType = SubType;
4744 pHdr80211->FC.ToDs = ToDs;
4745 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4746 #ifdef CONFIG_STA_SUPPORT
4747 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4748 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4749 #endif // CONFIG_STA_SUPPORT //
4750 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4753 // ===========================================================================================
4755 // ===========================================================================================
4757 /*!***************************************************************************
4758 * This routine build an outgoing frame, and fill all information specified
4759 * in argument list to the frame body. The actual frame size is the summation
4762 * Buffer - pointer to a pre-allocated memory segment
4763 * args - a list of <int arg_size, arg> pairs.
4764 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4765 * function will FAIL!!!
4767 * Size of the buffer
4769 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4771 IRQL = PASSIVE_LEVEL
4772 IRQL = DISPATCH_LEVEL
4774 ****************************************************************************/
4775 ULONG MakeOutgoingFrame(
4777 OUT ULONG *FrameLen, ...)
4784 // calculates the total length
4786 va_start(Args, FrameLen);
4789 leng = va_arg(Args, int);
4790 if (leng == END_OF_ARGS)
4794 p = va_arg(Args, PVOID);
4795 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4796 TotLeng = TotLeng + leng;
4799 va_end(Args); /* clean up */
4800 *FrameLen = TotLeng;
4804 // ===========================================================================================
4806 // ===========================================================================================
4808 /*! \brief Initialize The MLME Queue, used by MLME Functions
4809 * \param *Queue The MLME Queue
4810 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4813 * \note Because this is done only once (at the init stage), no need to be locked
4815 IRQL = PASSIVE_LEVEL
4818 NDIS_STATUS MlmeQueueInit(
4819 IN MLME_QUEUE *Queue)
4823 NdisAllocateSpinLock(&Queue->Lock);
4829 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4831 Queue->Entry[i].Occupied = FALSE;
4832 Queue->Entry[i].MsgLen = 0;
4833 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4836 return NDIS_STATUS_SUCCESS;
4839 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4840 * \param *Queue The MLME Queue
4841 * \param Machine The State Machine Id
4842 * \param MsgType The Message Type
4843 * \param MsgLen The Message length
4844 * \param *Msg The message pointer
4845 * \return TRUE if enqueue is successful, FALSE if the queue is full
4848 * \note The message has to be initialized
4850 IRQL = PASSIVE_LEVEL
4851 IRQL = DISPATCH_LEVEL
4854 BOOLEAN MlmeEnqueue(
4855 IN PRTMP_ADAPTER pAd,
4862 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4864 // Do nothing if the driver is starting halt state.
4865 // This might happen when timer already been fired before cancel timer with mlmehalt
4866 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4869 // First check the size, it MUST not exceed the mlme queue size
4870 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4872 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4876 if (MlmeQueueFull(Queue))
4881 NdisAcquireSpinLock(&(Queue->Lock));
4885 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4890 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4891 Queue->Entry[Tail].Occupied = TRUE;
4892 Queue->Entry[Tail].Machine = Machine;
4893 Queue->Entry[Tail].MsgType = MsgType;
4894 Queue->Entry[Tail].MsgLen = MsgLen;
4898 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4901 NdisReleaseSpinLock(&(Queue->Lock));
4905 /*! \brief This function is used when Recv gets a MLME message
4906 * \param *Queue The MLME Queue
4907 * \param TimeStampHigh The upper 32 bit of timestamp
4908 * \param TimeStampLow The lower 32 bit of timestamp
4909 * \param Rssi The receiving RSSI strength
4910 * \param MsgLen The length of the message
4911 * \param *Msg The message pointer
4912 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4916 IRQL = DISPATCH_LEVEL
4919 BOOLEAN MlmeEnqueueForRecv(
4920 IN PRTMP_ADAPTER pAd,
4922 IN ULONG TimeStampHigh,
4923 IN ULONG TimeStampLow,
4932 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4934 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4937 /* Nothing to do in ATE mode */
4940 #endif // RALINK_ATE //
4942 // Do nothing if the driver is starting halt state.
4943 // This might happen when timer already been fired before cancel timer with mlmehalt
4944 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4946 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4950 // First check the size, it MUST not exceed the mlme queue size
4951 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4953 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4957 if (MlmeQueueFull(Queue))
4962 #ifdef CONFIG_STA_SUPPORT
4963 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4965 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4967 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4971 #endif // CONFIG_STA_SUPPORT //
4973 // OK, we got all the informations, it is time to put things into queue
4974 NdisAcquireSpinLock(&(Queue->Lock));
4978 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4982 Queue->Entry[Tail].Occupied = TRUE;
4983 Queue->Entry[Tail].Machine = Machine;
4984 Queue->Entry[Tail].MsgType = MsgType;
4985 Queue->Entry[Tail].MsgLen = MsgLen;
4986 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4987 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4988 Queue->Entry[Tail].Rssi0 = Rssi0;
4989 Queue->Entry[Tail].Rssi1 = Rssi1;
4990 Queue->Entry[Tail].Rssi2 = Rssi2;
4991 Queue->Entry[Tail].Signal = Signal;
4992 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4994 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4998 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
5001 NdisReleaseSpinLock(&(Queue->Lock));
5003 RT28XX_MLME_HANDLER(pAd);
5009 /*! \brief Dequeue a message from the MLME Queue
5010 * \param *Queue The MLME Queue
5011 * \param *Elem The message dequeued from MLME Queue
5012 * \return TRUE if the Elem contains something, FALSE otherwise
5016 IRQL = DISPATCH_LEVEL
5019 BOOLEAN MlmeDequeue(
5020 IN MLME_QUEUE *Queue,
5021 OUT MLME_QUEUE_ELEM **Elem)
5023 NdisAcquireSpinLock(&(Queue->Lock));
5024 *Elem = &(Queue->Entry[Queue->Head]);
5027 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
5031 NdisReleaseSpinLock(&(Queue->Lock));
5035 // IRQL = DISPATCH_LEVEL
5036 VOID MlmeRestartStateMachine(
5037 IN PRTMP_ADAPTER pAd)
5040 MLME_QUEUE_ELEM *Elem = NULL;
5042 #ifdef CONFIG_STA_SUPPORT
5044 #endif // CONFIG_STA_SUPPORT //
5046 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
5049 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
5050 if(pAd->Mlme.bRunning)
5052 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
5057 pAd->Mlme.bRunning = TRUE;
5059 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
5061 // Remove all Mlme queues elements
5062 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
5064 //From message type, determine which state machine I should drive
5065 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
5067 // free MLME element
5068 Elem->Occupied = FALSE;
5073 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
5078 #ifdef CONFIG_STA_SUPPORT
5079 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5081 #ifdef QOS_DLS_SUPPORT
5083 #endif // QOS_DLS_SUPPORT //
5084 // Cancel all timer events
5085 // Be careful to cancel new added timer
5086 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
5087 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
5088 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
5089 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
5090 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
5091 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
5093 #ifdef QOS_DLS_SUPPORT
5094 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
5096 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
5098 #endif // QOS_DLS_SUPPORT //
5100 #endif // CONFIG_STA_SUPPORT //
5102 // Change back to original channel in case of doing scan
5103 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
5104 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
5106 // Resume MSDU which is turned off durning scan
5107 RTMPResumeMsduTransmission(pAd);
5109 #ifdef CONFIG_STA_SUPPORT
5110 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5112 // Set all state machines back IDLE
5113 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
5114 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
5115 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
5116 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
5117 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
5118 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
5119 #ifdef QOS_DLS_SUPPORT
5120 pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
5121 #endif // QOS_DLS_SUPPORT //
5123 #endif // CONFIG_STA_SUPPORT //
5126 // Remove running state
5127 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
5128 pAd->Mlme.bRunning = FALSE;
5129 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
5133 /*! \brief test if the MLME Queue is empty
5134 * \param *Queue The MLME Queue
5135 * \return TRUE if the Queue is empty, FALSE otherwise
5139 IRQL = DISPATCH_LEVEL
5142 BOOLEAN MlmeQueueEmpty(
5143 IN MLME_QUEUE *Queue)
5147 NdisAcquireSpinLock(&(Queue->Lock));
5148 Ans = (Queue->Num == 0);
5149 NdisReleaseSpinLock(&(Queue->Lock));
5154 /*! \brief test if the MLME Queue is full
5155 * \param *Queue The MLME Queue
5156 * \return TRUE if the Queue is empty, FALSE otherwise
5160 IRQL = PASSIVE_LEVEL
5161 IRQL = DISPATCH_LEVEL
5164 BOOLEAN MlmeQueueFull(
5165 IN MLME_QUEUE *Queue)
5169 NdisAcquireSpinLock(&(Queue->Lock));
5170 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5171 NdisReleaseSpinLock(&(Queue->Lock));
5176 /*! \brief The destructor of MLME Queue
5181 * \note Clear Mlme Queue, Set Queue->Num to Zero.
5183 IRQL = PASSIVE_LEVEL
5186 VOID MlmeQueueDestroy(
5187 IN MLME_QUEUE *pQueue)
5189 NdisAcquireSpinLock(&(pQueue->Lock));
5193 NdisReleaseSpinLock(&(pQueue->Lock));
5194 NdisFreeSpinLock(&(pQueue->Lock));
5197 /*! \brief To substitute the message type if the message is coming from external
5198 * \param pFrame The frame received
5199 * \param *Machine The state machine
5200 * \param *MsgType the message type for the state machine
5201 * \return TRUE if the substitution is successful, FALSE otherwise
5205 IRQL = DISPATCH_LEVEL
5208 #ifdef CONFIG_STA_SUPPORT
5209 BOOLEAN MsgTypeSubst(
5210 IN PRTMP_ADAPTER pAd,
5211 IN PFRAME_802_11 pFrame,
5219 // Pointer to start of data frames including SNAP header
5220 pData = (PUCHAR) pFrame + LENGTH_802_11;
5222 // The only data type will pass to this function is EAPOL frame
5223 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5225 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5227 // Cisco Aironet SNAP header
5228 *Machine = AIRONET_STATE_MACHINE;
5229 *MsgType = MT2_AIRONET_MSG;
5233 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5236 *Machine = LEAP_STATE_MACHINE;
5237 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5238 return (LeapMsgTypeSubst(EAPType, MsgType));
5241 #endif // LEAP_SUPPORT //
5243 *Machine = WPA_PSK_STATE_MACHINE;
5244 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5245 return(WpaMsgTypeSubst(EAPType, MsgType));
5249 switch (pFrame->Hdr.FC.SubType)
5251 case SUBTYPE_ASSOC_REQ:
5252 *Machine = ASSOC_STATE_MACHINE;
5253 *MsgType = MT2_PEER_ASSOC_REQ;
5255 case SUBTYPE_ASSOC_RSP:
5256 *Machine = ASSOC_STATE_MACHINE;
5257 *MsgType = MT2_PEER_ASSOC_RSP;
5259 case SUBTYPE_REASSOC_REQ:
5260 *Machine = ASSOC_STATE_MACHINE;
5261 *MsgType = MT2_PEER_REASSOC_REQ;
5263 case SUBTYPE_REASSOC_RSP:
5264 *Machine = ASSOC_STATE_MACHINE;
5265 *MsgType = MT2_PEER_REASSOC_RSP;
5267 case SUBTYPE_PROBE_REQ:
5268 *Machine = SYNC_STATE_MACHINE;
5269 *MsgType = MT2_PEER_PROBE_REQ;
5271 case SUBTYPE_PROBE_RSP:
5272 *Machine = SYNC_STATE_MACHINE;
5273 *MsgType = MT2_PEER_PROBE_RSP;
5275 case SUBTYPE_BEACON:
5276 *Machine = SYNC_STATE_MACHINE;
5277 *MsgType = MT2_PEER_BEACON;
5280 *Machine = SYNC_STATE_MACHINE;
5281 *MsgType = MT2_PEER_ATIM;
5283 case SUBTYPE_DISASSOC:
5284 *Machine = ASSOC_STATE_MACHINE;
5285 *MsgType = MT2_PEER_DISASSOC_REQ;
5288 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5289 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5290 if (Seq == 1 || Seq == 3)
5292 *Machine = AUTH_RSP_STATE_MACHINE;
5293 *MsgType = MT2_PEER_AUTH_ODD;
5295 else if (Seq == 2 || Seq == 4)
5297 *Machine = AUTH_STATE_MACHINE;
5298 *MsgType = MT2_PEER_AUTH_EVEN;
5305 case SUBTYPE_DEAUTH:
5306 *Machine = AUTH_RSP_STATE_MACHINE;
5307 *MsgType = MT2_PEER_DEAUTH;
5309 case SUBTYPE_ACTION:
5310 *Machine = ACTION_STATE_MACHINE;
5311 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5312 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5314 *MsgType = MT2_ACT_INVALID;
5318 *MsgType = (pFrame->Octet[0]&0x7F);
5328 #endif // CONFIG_STA_SUPPORT //
5330 // ===========================================================================================
5332 // ===========================================================================================
5334 /*! \brief Initialize the state machine.
5335 * \param *S pointer to the state machine
5336 * \param Trans State machine transition function
5337 * \param StNr number of states
5338 * \param MsgNr number of messages
5339 * \param DefFunc default function, when there is invalid state/message combination
5340 * \param InitState initial state of the state machine
5341 * \param Base StateMachine base, internal use only
5342 * \pre p_sm should be a legal pointer
5345 IRQL = PASSIVE_LEVEL
5348 VOID StateMachineInit(
5349 IN STATE_MACHINE *S,
5350 IN STATE_MACHINE_FUNC Trans[],
5353 IN STATE_MACHINE_FUNC DefFunc,
5359 // set number of states and messages
5364 S->TransFunc = Trans;
5366 // init all state transition to default function
5367 for (i = 0; i < StNr; i++)
5369 for (j = 0; j < MsgNr; j++)
5371 S->TransFunc[i * MsgNr + j] = DefFunc;
5375 // set the starting state
5376 S->CurrState = InitState;
5379 /*! \brief This function fills in the function pointer into the cell in the state machine
5380 * \param *S pointer to the state machine
5382 * \param Msg incoming message
5383 * \param f the function to be executed when (state, message) combination occurs at the state machine
5384 * \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
5387 IRQL = PASSIVE_LEVEL
5390 VOID StateMachineSetAction(
5391 IN STATE_MACHINE *S,
5394 IN STATE_MACHINE_FUNC Func)
5398 MsgIdx = Msg - S->Base;
5400 if (St < S->NrState && MsgIdx < S->NrMsg)
5402 // boundary checking before setting the action
5403 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5407 /*! \brief This function does the state transition
5408 * \param *Adapter the NIC adapter pointer
5409 * \param *S the state machine
5410 * \param *Elem the message to be executed
5413 IRQL = DISPATCH_LEVEL
5416 VOID StateMachinePerformAction(
5417 IN PRTMP_ADAPTER pAd,
5418 IN STATE_MACHINE *S,
5419 IN MLME_QUEUE_ELEM *Elem)
5421 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5425 ==========================================================================
5427 The drop function, when machine executes this, the message is simply
5428 ignored. This function does nothing, the message is freed in
5429 StateMachinePerformAction()
5430 ==========================================================================
5433 IN PRTMP_ADAPTER pAd,
5434 IN MLME_QUEUE_ELEM *Elem)
5438 // ===========================================================================================
5440 // ===========================================================================================
5443 ==========================================================================
5446 IRQL = PASSIVE_LEVEL
5448 ==========================================================================
5451 IN PRTMP_ADAPTER pAd,
5455 pAd->Mlme.ShiftReg = 1;
5457 pAd->Mlme.ShiftReg = Seed;
5461 ==========================================================================
5463 ==========================================================================
5466 IN PRTMP_ADAPTER pAd)
5473 if (pAd->Mlme.ShiftReg == 0)
5474 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5476 for (i = 0; i < 8; i++)
5478 if (pAd->Mlme.ShiftReg & 0x00000001)
5480 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5485 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5488 R = (R << 1) | Result;
5494 VOID AsicUpdateAutoFallBackTable(
5495 IN PRTMP_ADAPTER pAd,
5496 IN PUCHAR pRateTable)
5499 HT_FBK_CFG0_STRUC HtCfg0;
5500 HT_FBK_CFG1_STRUC HtCfg1;
5501 LG_FBK_CFG0_STRUC LgCfg0;
5502 LG_FBK_CFG1_STRUC LgCfg1;
5503 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5505 // set to initial value
5506 HtCfg0.word = 0x65432100;
5507 HtCfg1.word = 0xedcba988;
5508 LgCfg0.word = 0xedcba988;
5509 LgCfg1.word = 0x00002100;
5511 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5512 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5514 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5515 switch (pCurrTxRate->Mode)
5521 switch(pCurrTxRate->CurrMCS)
5524 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5527 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5530 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5533 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5536 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5539 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5542 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5545 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5550 #ifdef DOT11_N_SUPPORT
5554 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5556 switch(pCurrTxRate->CurrMCS)
5559 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5562 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5565 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5568 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5571 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5574 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5577 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5580 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5583 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5586 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5589 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5592 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5595 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5598 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5601 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5604 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5607 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5612 #endif // DOT11_N_SUPPORT //
5615 pNextTxRate = pCurrTxRate;
5618 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5619 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5620 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5621 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5625 ========================================================================
5627 Routine Description:
5628 Set MAC register value according operation mode.
5629 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5630 If MM or GF mask is not set, those passing argument doesn't not take effect.
5632 Operation mode meaning:
5633 = 0 : Pure HT, no preotection.
5634 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5635 = 0x10: No Transmission in 40M is protected.
5636 = 0x11: Transmission in both 40M and 20M shall be protected
5638 we should choose not to use GF. But still set correct ASIC registers.
5639 ========================================================================
5641 VOID AsicUpdateProtect(
5642 IN PRTMP_ADAPTER pAd,
5643 IN USHORT OperationMode,
5645 IN BOOLEAN bDisableBGProtect,
5646 IN BOOLEAN bNonGFExist)
5648 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5657 #endif // RALINK_ATE //
5659 #ifdef DOT11_N_SUPPORT
5660 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5665 if (pAd->BATable.numAsOriginator)
5668 // enable the RTS/CTS to avoid channel collision
5670 SetMask = ALLN_SETPROTECT;
5673 #endif // DOT11_N_SUPPORT //
5675 // Config ASIC RTS threshold register
5676 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5677 MacReg &= 0xFF0000FF;
5679 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5681 // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5683 #ifdef DOT11_N_SUPPORT
5684 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5685 #endif // DOT11_N_SUPPORT //
5686 (pAd->CommonCfg.bAggregationCapable == TRUE))
5687 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5689 MacReg |= (0x1000 << 8);
5693 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5697 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5699 // Initial common protection settings
5700 RTMPZeroMemory(Protect, sizeof(Protect));
5703 ProtCfg.field.TxopAllowGF40 = 1;
5704 ProtCfg.field.TxopAllowGF20 = 1;
5705 ProtCfg.field.TxopAllowMM40 = 1;
5706 ProtCfg.field.TxopAllowMM20 = 1;
5707 ProtCfg.field.TxopAllowOfdm = 1;
5708 ProtCfg.field.TxopAllowCck = 1;
5709 ProtCfg.field.RTSThEn = 1;
5710 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5712 // update PHY mode and rate
5713 if (pAd->CommonCfg.Channel > 14)
5714 ProtCfg.field.ProtectRate = 0x4000;
5715 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5717 // Handle legacy(B/G) protection
5718 if (bDisableBGProtect)
5720 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5721 ProtCfg.field.ProtectCtrl = 0;
5722 Protect[0] = ProtCfg.word;
5723 Protect[1] = ProtCfg.word;
5727 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5728 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5729 Protect[0] = ProtCfg.word;
5730 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5731 Protect[1] = ProtCfg.word;
5734 #ifdef DOT11_N_SUPPORT
5735 // Decide HT frame protection.
5736 if ((SetMask & ALLN_SETPROTECT) != 0)
5738 switch(OperationMode)
5742 // 1.All STAs in the BSS are 20/40 MHz HT
5743 // 2. in ai 20/40MHz BSS
5744 // 3. all STAs are 20MHz in a 20MHz BSS
5745 // Pure HT. no protection.
5749 // PROT_TXOP(25:20) -- 010111
5750 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5751 // PROT_CTRL(17:16) -- 00 (None)
5752 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5753 Protect[2] = 0x01744004;
5757 // PROT_TXOP(25:20) -- 111111
5758 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5759 // PROT_CTRL(17:16) -- 00 (None)
5760 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5761 Protect[3] = 0x03f44084;
5765 // PROT_TXOP(25:20) -- 010111
5766 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5767 // PROT_CTRL(17:16) -- 00 (None)
5768 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5769 Protect[4] = 0x01744004;
5773 // PROT_TXOP(25:20) -- 111111
5774 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5775 // PROT_CTRL(17:16) -- 00 (None)
5776 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5777 Protect[5] = 0x03f44084;
5781 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5782 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5783 Protect[4] = 0x01754004;
5784 Protect[5] = 0x03f54084;
5786 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5790 // This is "HT non-member protection mode."
5791 // If there may be non-HT STAs my BSS
5792 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5793 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5794 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5796 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5797 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5799 //Assign Protection method for 20&40 MHz packets
5800 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5801 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5802 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5803 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5804 Protect[2] = ProtCfg.word;
5805 Protect[3] = ProtCfg4.word;
5806 Protect[4] = ProtCfg.word;
5807 Protect[5] = ProtCfg4.word;
5808 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5812 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5813 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5814 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5816 //Assign Protection method for 40MHz packets
5817 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5818 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5819 Protect[2] = ProtCfg.word;
5820 Protect[3] = ProtCfg4.word;
5823 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5824 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5826 Protect[4] = ProtCfg.word;
5827 Protect[5] = ProtCfg4.word;
5829 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5833 // HT mixed mode. PROTECT ALL!
5835 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5836 ProtCfg4.word = 0x03f44084;
5837 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5838 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5840 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5841 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5843 //Assign Protection method for 20&40 MHz packets
5844 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5845 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5846 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5847 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5848 Protect[2] = ProtCfg.word;
5849 Protect[3] = ProtCfg4.word;
5850 Protect[4] = ProtCfg.word;
5851 Protect[5] = ProtCfg4.word;
5852 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5856 // Special on for Atheros problem n chip.
5857 Protect[2] = 0x01754004;
5858 Protect[3] = 0x03f54084;
5859 Protect[4] = 0x01754004;
5860 Protect[5] = 0x03f54084;
5861 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5865 #endif // DOT11_N_SUPPORT //
5867 offset = CCK_PROT_CFG;
5868 for (i = 0;i < 6;i++)
5870 if ((SetMask & (1<< i)))
5872 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5878 ==========================================================================
5881 IRQL = PASSIVE_LEVEL
5882 IRQL = DISPATCH_LEVEL
5884 ==========================================================================
5886 VOID AsicSwitchChannel(
5887 IN PRTMP_ADAPTER pAd,
5891 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5892 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5894 UINT32 Value = 0; //BbpReg, Value;
5895 RTMP_RF_REGS *RFRegTable;
5897 // Search Tx power value
5898 for (index = 0; index < pAd->ChannelListNum; index++)
5900 if (Channel == pAd->ChannelList[index].Channel)
5902 TxPwer = pAd->ChannelList[index].Power;
5903 TxPwer2 = pAd->ChannelList[index].Power2;
5908 if (index == MAX_NUM_OF_CHANNELS)
5910 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5914 RFRegTable = RF2850RegTable;
5916 switch (pAd->RfIcType)
5923 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5925 if (Channel == RFRegTable[index].Channel)
5927 R2 = RFRegTable[index].R2;
5928 if (pAd->Antenna.field.TxPath == 1)
5930 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5933 if (pAd->Antenna.field.RxPath == 2)
5935 R2 |= 0x40; // write 1 to off Rxpath.
5937 else if (pAd->Antenna.field.RxPath == 1)
5939 R2 |= 0x20040; // write 1 to off RxPath
5944 // initialize R3, R4
5945 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5946 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5948 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5950 if ((TxPwer >= -7) && (TxPwer < 0))
5952 TxPwer = (7+TxPwer);
5953 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5954 R3 |= (TxPwer << 10);
5955 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5959 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5960 R3 |= (TxPwer << 10) | (1 << 9);
5964 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5966 TxPwer2 = (7+TxPwer2);
5967 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5968 R4 |= (TxPwer2 << 7);
5969 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5973 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5974 R4 |= (TxPwer2 << 7) | (1 << 6);
5979 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5980 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5983 // Based on BBP current mode before changing RF channel.
5984 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5990 pAd->LatchRfRegs.Channel = Channel;
5991 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5992 pAd->LatchRfRegs.R2 = R2;
5993 pAd->LatchRfRegs.R3 = R3;
5994 pAd->LatchRfRegs.R4 = R4;
5996 // Set RF value 1's set R3[bit2] = [0]
5997 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5998 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5999 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6000 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6004 // Set RF value 2's set R3[bit2] = [1]
6005 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6006 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6007 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
6008 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6012 // Set RF value 3's set R3[bit2] = [0]
6013 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6014 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6015 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6016 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6028 // Change BBP setting during siwtch from a->g, g->a
6031 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
6033 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6034 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6035 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6036 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.
6037 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6039 // Rx High power VGA offset for LNA select
6040 if (pAd->NicConfig2.field.ExternalLNAForG)
6042 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6043 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6047 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6048 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6051 // 5G band selection PIN, bit1 and bit2 are complement
6052 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6055 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6057 // Turn off unused PA or LNA when only 1T or 1R
6058 if (pAd->Antenna.field.TxPath == 1)
6060 TxPinCfg &= 0xFFFFFFF3;
6062 if (pAd->Antenna.field.RxPath == 1)
6064 TxPinCfg &= 0xFFFFF3FF;
6067 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6071 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6073 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6074 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6075 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6076 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.
6077 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6079 // Rx High power VGA offset for LNA select
6080 if (pAd->NicConfig2.field.ExternalLNAForA)
6082 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6086 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6089 // 5G band selection PIN, bit1 and bit2 are complement
6090 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6093 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6095 // Turn off unused PA or LNA when only 1T or 1R
6096 if (pAd->Antenna.field.TxPath == 1)
6098 TxPinCfg &= 0xFFFFFFF3;
6100 if (pAd->Antenna.field.RxPath == 1)
6102 TxPinCfg &= 0xFFFFF3FF;
6105 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6108 // R66 should be set according to Channel and use 20MHz when scanning
6109 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6111 RTMPSetAGCInitValue(pAd, BW_20);
6113 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6116 // On 11A, We should delay and wait RF/BBP to be stable
6117 // and the appropriate time should be 1000 micro seconds
6118 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6120 RTMPusecDelay(1000);
6122 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",
6125 (R3 & 0x00003e00) >> 9,
6126 (R4 & 0x000007c0) >> 6,
6127 pAd->Antenna.field.TxPath,
6128 pAd->LatchRfRegs.R1,
6129 pAd->LatchRfRegs.R2,
6130 pAd->LatchRfRegs.R3,
6131 pAd->LatchRfRegs.R4));
6135 ==========================================================================
6137 This function is required for 2421 only, and should not be used during
6138 site survey. It's only required after NIC decided to stay at a channel
6139 for a longer period.
6140 When this function is called, it's always after AsicSwitchChannel().
6142 IRQL = PASSIVE_LEVEL
6143 IRQL = DISPATCH_LEVEL
6145 ==========================================================================
6147 VOID AsicLockChannel(
6148 IN PRTMP_ADAPTER pAd,
6154 ==========================================================================
6157 IRQL = PASSIVE_LEVEL
6158 IRQL = DISPATCH_LEVEL
6160 ==========================================================================
6162 VOID AsicAntennaSelect(
6163 IN PRTMP_ADAPTER pAd,
6169 ========================================================================
6171 Routine Description:
6172 Antenna miscellaneous setting.
6175 pAd Pointer to our adapter
6176 BandState Indicate current Band State.
6181 IRQL <= DISPATCH_LEVEL
6184 1.) Frame End type control
6185 only valid for G only (RF_2527 & RF_2529)
6186 0: means DPDT, set BBP R4 bit 5 to 1
6187 1: means SPDT, set BBP R4 bit 5 to 0
6190 ========================================================================
6192 VOID AsicAntennaSetting(
6193 IN PRTMP_ADAPTER pAd,
6194 IN ABGBAND_STATE BandState)
6198 VOID AsicRfTuningExec(
6199 IN PVOID SystemSpecific1,
6200 IN PVOID FunctionContext,
6201 IN PVOID SystemSpecific2,
6202 IN PVOID SystemSpecific3)
6207 ==========================================================================
6209 Gives CCK TX rate 2 more dB TX power.
6210 This routine works only in LINK UP in INFRASTRUCTURE mode.
6212 calculate desired Tx power in RF R3.Tx0~5, should consider -
6213 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6214 1. TxPowerPercentage
6215 2. auto calibration based on TSSI feedback
6216 3. extra 2 db for CCK
6217 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6219 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6220 it should be called AFTER MlmeDynamicTxRatSwitching()
6221 ==========================================================================
6223 VOID AsicAdjustTxPower(
6224 IN PRTMP_ADAPTER pAd)
6228 BOOLEAN bAutoTxAgc = FALSE;
6229 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6230 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6231 PCHAR pTxAgcCompensate;
6235 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6236 || (pAd->bPCIclkOff == TRUE)
6237 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6238 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6241 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6243 if (pAd->CommonCfg.CentralChannel > 14)
6245 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6246 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6247 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6248 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6249 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6253 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6254 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6255 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6256 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6257 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6262 if (pAd->CommonCfg.Channel > 14)
6264 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6265 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6266 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6267 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6268 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6272 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6273 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6274 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6275 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6276 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6280 // TX power compensation for temperature variation based on TSSI. try every 4 second
6281 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6283 if (pAd->CommonCfg.Channel <= 14)
6286 bAutoTxAgc = pAd->bAutoTxAgcG;
6287 TssiRef = pAd->TssiRefG;
6288 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6289 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6290 TxAgcStep = pAd->TxAgcStepG;
6291 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6296 bAutoTxAgc = pAd->bAutoTxAgcA;
6297 TssiRef = pAd->TssiRefA;
6298 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6299 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6300 TxAgcStep = pAd->TxAgcStepA;
6301 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6306 /* BbpR1 is unsigned char */
6307 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6309 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6310 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6311 /* step value is defined in pAd->TxAgcStepG for tx power value */
6313 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6314 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6315 above value are examined in mass factory production */
6316 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6318 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6319 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6320 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6322 if (BbpR49 > pTssiMinusBoundary[1])
6324 // Reading is larger than the reference value
6325 // check for how large we need to decrease the Tx power
6326 for (idx = 1; idx < 5; idx++)
6328 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6331 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6332 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6334 DeltaPwr += (*pTxAgcCompensate);
6335 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6336 BbpR49, TssiRef, TxAgcStep, idx-1));
6338 else if (BbpR49 < pTssiPlusBoundary[1])
6340 // Reading is smaller than the reference value
6341 // check for how large we need to increase the Tx power
6342 for (idx = 1; idx < 5; idx++)
6344 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6347 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6348 *pTxAgcCompensate = TxAgcStep * (idx-1);
6349 DeltaPwr += (*pTxAgcCompensate);
6350 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6351 BbpR49, TssiRef, TxAgcStep, idx-1));
6355 *pTxAgcCompensate = 0;
6356 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6357 BbpR49, TssiRef, TxAgcStep, 0));
6363 if (pAd->CommonCfg.Channel <= 14)
6365 bAutoTxAgc = pAd->bAutoTxAgcG;
6366 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6370 bAutoTxAgc = pAd->bAutoTxAgcA;
6371 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6375 DeltaPwr += (*pTxAgcCompensate);
6378 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6382 // Handle regulatory max tx power constrain
6385 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6386 UCHAR AdjustMaxTxPwr[40];
6388 if (pAd->CommonCfg.Channel > 14) // 5G band
6389 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6391 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6392 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6394 // error handling, range check
6395 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6397 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6401 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6403 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6405 // Adjust max tx power according to the relationship of tx power in E2PROM
6408 // CCK will have 4dBm larger than OFDM
6409 // Therefore, we should separate to parse the tx power field
6414 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6418 // CCK will have 4dBm larger than OFDM
6419 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6423 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6425 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6432 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6434 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6435 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6440 // Adjust tx power according to the relationship
6443 if (TxPwr[i] != 0xffffffff)
6447 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6449 // The system tx power is larger than the regulatory, the power should be restrain
6450 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6452 // decrease to zero and don't need to take care BBPR1
6453 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6454 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6458 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6461 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6463 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6468 #endif // SINGLE_SKU //
6470 /* calculate delta power based on the percentage specified from UI */
6471 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6472 // We lower TX power here according to the percentage specified from UI
6473 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6475 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6477 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6481 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6485 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6489 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6494 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6499 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6501 /* reset different new tx power for different TX rate */
6504 if (TxPwr[i] != 0xffffffff)
6508 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6510 if ((Value + DeltaPwr) < 0)
6512 Value = 0; /* min */
6514 else if ((Value + DeltaPwr) > 0xF)
6516 Value = 0xF; /* max */
6520 Value += DeltaPwr; /* temperature compensation */
6523 /* fill new value to CSR offset */
6524 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6527 /* write tx power value to CSR */
6528 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6529 TX power for OFDM 6M/9M
6530 TX power for CCK5.5M/11M
6531 TX power for CCK1M/2M */
6532 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6533 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6539 #ifdef CONFIG_STA_SUPPORT
6541 ==========================================================================
6543 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6544 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6545 the wakeup timer timeout. Driver has to issue a separate command to wake
6548 IRQL = DISPATCH_LEVEL
6550 ==========================================================================
6552 VOID AsicSleepThenAutoWakeup(
6553 IN PRTMP_ADAPTER pAd,
6554 IN USHORT TbttNumToNextWakeUp)
6556 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6560 ==========================================================================
6562 AsicForceWakeup() is used whenever manual wakeup is required
6563 AsicForceSleep() should only be used when not in INFRA BSS. When
6564 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6565 ==========================================================================
6567 VOID AsicForceSleep(
6568 IN PRTMP_ADAPTER pAd)
6574 ==========================================================================
6576 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6579 IRQL = PASSIVE_LEVEL
6580 IRQL = DISPATCH_LEVEL
6581 ==========================================================================
6583 VOID AsicForceWakeup(
6584 IN PRTMP_ADAPTER pAd,
6587 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6588 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6590 #endif // CONFIG_STA_SUPPORT //
6592 ==========================================================================
6596 IRQL = DISPATCH_LEVEL
6598 ==========================================================================
6601 IN PRTMP_ADAPTER pAd,
6605 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6606 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6608 Addr4 = (ULONG)(pBssid[0]) |
6609 (ULONG)(pBssid[1] << 8) |
6610 (ULONG)(pBssid[2] << 16) |
6611 (ULONG)(pBssid[3] << 24);
6612 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6615 // always one BSSID in STA mode
6616 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6618 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6621 VOID AsicSetMcastWC(
6622 IN PRTMP_ADAPTER pAd)
6624 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6627 pEntry->Sst = SST_ASSOC;
6628 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6629 pEntry->PsMode = PWR_ACTIVE;
6630 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6631 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6635 ==========================================================================
6638 IRQL = DISPATCH_LEVEL
6640 ==========================================================================
6642 VOID AsicDelWcidTab(
6643 IN PRTMP_ADAPTER pAd,
6646 ULONG Addr0 = 0x0, Addr1 = 0x0;
6649 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6650 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6651 RTMP_IO_WRITE32(pAd, offset, Addr0);
6653 RTMP_IO_WRITE32(pAd, offset, Addr1);
6657 ==========================================================================
6660 IRQL = DISPATCH_LEVEL
6662 ==========================================================================
6665 IN PRTMP_ADAPTER pAd)
6667 TX_LINK_CFG_STRUC TxLinkCfg;
6670 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6671 TxLinkCfg.field.TxRDGEn = 1;
6672 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6674 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6677 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6679 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6683 ==========================================================================
6686 IRQL = DISPATCH_LEVEL
6688 ==========================================================================
6690 VOID AsicDisableRDG(
6691 IN PRTMP_ADAPTER pAd)
6693 TX_LINK_CFG_STRUC TxLinkCfg;
6697 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6698 TxLinkCfg.field.TxRDGEn = 0;
6699 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6701 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6704 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6705 #ifdef DOT11_N_SUPPORT
6706 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6707 #endif // DOT11_N_SUPPORT //
6710 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6711 if (pAd->CommonCfg.bEnableTxBurst)
6714 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6718 ==========================================================================
6721 IRQL = PASSIVE_LEVEL
6722 IRQL = DISPATCH_LEVEL
6724 ==========================================================================
6726 VOID AsicDisableSync(
6727 IN PRTMP_ADAPTER pAd)
6729 BCN_TIME_CFG_STRUC csr;
6731 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6733 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6734 // that NIC will never wakes up because TSF stops and no more
6736 pAd->TbttTickCount = 0;
6737 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6738 csr.field.bBeaconGen = 0;
6739 csr.field.bTBTTEnable = 0;
6740 csr.field.TsfSyncMode = 0;
6741 csr.field.bTsfTicking = 0;
6742 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6747 ==========================================================================
6750 IRQL = DISPATCH_LEVEL
6752 ==========================================================================
6754 VOID AsicEnableBssSync(
6755 IN PRTMP_ADAPTER pAd)
6757 BCN_TIME_CFG_STRUC csr;
6759 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6761 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6762 #ifdef CONFIG_STA_SUPPORT
6763 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6765 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6766 csr.field.bTsfTicking = 1;
6767 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6768 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6769 csr.field.bTBTTEnable = 1;
6771 #endif // CONFIG_STA_SUPPORT //
6772 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6776 ==========================================================================
6779 BEACON frame in shared memory should be built ok before this routine
6780 can be called. Otherwise, a garbage frame maybe transmitted out every
6783 IRQL = DISPATCH_LEVEL
6785 ==========================================================================
6787 VOID AsicEnableIbssSync(
6788 IN PRTMP_ADAPTER pAd)
6790 BCN_TIME_CFG_STRUC csr9;
6794 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6796 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6797 csr9.field.bBeaconGen = 0;
6798 csr9.field.bTBTTEnable = 0;
6799 csr9.field.bTsfTicking = 0;
6800 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6803 // move BEACON TXD and frame content to on-chip memory
6804 ptr = (PUCHAR)&pAd->BeaconTxWI;
6805 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6807 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6808 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6812 // start right after the 16-byte TXWI field
6813 ptr = pAd->BeaconBuf;
6814 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6816 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6817 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6822 // start sending BEACON
6823 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6824 csr9.field.bTsfTicking = 1;
6825 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6826 csr9.field.bTBTTEnable = 1;
6827 csr9.field.bBeaconGen = 1;
6828 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6832 ==========================================================================
6835 IRQL = PASSIVE_LEVEL
6836 IRQL = DISPATCH_LEVEL
6838 ==========================================================================
6840 VOID AsicSetEdcaParm(
6841 IN PRTMP_ADAPTER pAd,
6842 IN PEDCA_PARM pEdcaParm)
6844 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6845 AC_TXOP_CSR0_STRUC csr0;
6846 AC_TXOP_CSR1_STRUC csr1;
6847 AIFSN_CSR_STRUC AifsnCsr;
6848 CWMIN_CSR_STRUC CwminCsr;
6849 CWMAX_CSR_STRUC CwmaxCsr;
6856 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6858 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6859 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6860 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6862 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6863 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6866 //========================================================
6867 // MAC Register has a copy .
6868 //========================================================
6869 if( pAd->CommonCfg.bEnableTxBurst )
6871 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6872 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6875 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6876 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6877 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6878 Ac0Cfg.field.Aifsn = 2;
6879 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6881 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6882 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6883 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6884 Ac1Cfg.field.Aifsn = 2;
6885 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6887 if (pAd->CommonCfg.PhyMode == PHY_11B)
6889 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6890 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6894 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6895 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6897 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6898 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6899 Ac2Cfg.field.Aifsn = 2;
6900 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6901 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6902 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6903 Ac3Cfg.field.Aifsn = 2;
6904 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6906 //========================================================
6907 // DMA Register has a copy too.
6908 //========================================================
6909 csr0.field.Ac0Txop = 0; // QID_AC_BE
6910 csr0.field.Ac1Txop = 0; // QID_AC_BK
6911 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6912 if (pAd->CommonCfg.PhyMode == PHY_11B)
6914 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6915 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6919 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6920 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6922 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6925 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6926 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6927 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6928 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6929 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6932 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6933 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6934 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6935 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6936 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6938 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6940 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6944 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6945 //========================================================
6946 // MAC Register has a copy.
6947 //========================================================
6949 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6950 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6952 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6954 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6955 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6956 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6957 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6959 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6960 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6961 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6962 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6964 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6965 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6966 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6967 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6968 #ifdef CONFIG_STA_SUPPORT
6969 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6971 // Tuning for Wi-Fi WMM S06
6972 if (pAd->CommonCfg.bWiFiTest &&
6973 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6974 Ac2Cfg.field.Aifsn -= 1;
6976 // Tuning for TGn Wi-Fi 5.2.32
6977 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6978 if (STA_TGN_WIFI_ON(pAd) &&
6979 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6981 Ac0Cfg.field.Aifsn = 3;
6982 Ac2Cfg.field.AcTxop = 5;
6985 #endif // CONFIG_STA_SUPPORT //
6987 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6988 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6989 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6990 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6993 if (pAd->CommonCfg.bWiFiTest)
6995 if (Ac3Cfg.field.AcTxop == 102)
6997 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6998 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6999 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7000 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
7001 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
7004 //#endif // WIFI_TEST //
7006 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7007 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7008 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7009 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7012 //========================================================
7013 // DMA Register has a copy too.
7014 //========================================================
7015 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
7016 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
7017 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7019 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
7020 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
7021 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7024 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
7025 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
7026 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
7027 #ifdef CONFIG_STA_SUPPORT
7028 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7029 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
7030 #endif // CONFIG_STA_SUPPORT //
7031 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7034 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
7035 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7036 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7037 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7038 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7041 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7042 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7043 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7044 #ifdef CONFIG_STA_SUPPORT
7045 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7047 // Tuning for Wi-Fi WMM S06
7048 if (pAd->CommonCfg.bWiFiTest &&
7049 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7050 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7052 // Tuning for TGn Wi-Fi 5.2.32
7053 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
7054 if (STA_TGN_WIFI_ON(pAd) &&
7055 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7057 AifsnCsr.field.Aifsn0 = 3;
7058 AifsnCsr.field.Aifsn2 = 7;
7061 #endif // CONFIG_STA_SUPPORT //
7063 #ifdef CONFIG_STA_SUPPORT
7064 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7065 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7066 #endif // CONFIG_STA_SUPPORT //
7067 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7069 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7072 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7073 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7074 pEdcaParm->Aifsn[0],
7075 pEdcaParm->Cwmin[0],
7076 pEdcaParm->Cwmax[0],
7077 pEdcaParm->Txop[0]<<5,
7078 pEdcaParm->bACM[0]));
7079 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7080 pEdcaParm->Aifsn[1],
7081 pEdcaParm->Cwmin[1],
7082 pEdcaParm->Cwmax[1],
7083 pEdcaParm->Txop[1]<<5,
7084 pEdcaParm->bACM[1]));
7085 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7086 pEdcaParm->Aifsn[2],
7087 pEdcaParm->Cwmin[2],
7088 pEdcaParm->Cwmax[2],
7089 pEdcaParm->Txop[2]<<5,
7090 pEdcaParm->bACM[2]));
7091 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7092 pEdcaParm->Aifsn[3],
7093 pEdcaParm->Cwmin[3],
7094 pEdcaParm->Cwmax[3],
7095 pEdcaParm->Txop[3]<<5,
7096 pEdcaParm->bACM[3]));
7102 ==========================================================================
7105 IRQL = PASSIVE_LEVEL
7106 IRQL = DISPATCH_LEVEL
7108 ==========================================================================
7110 VOID AsicSetSlotTime(
7111 IN PRTMP_ADAPTER pAd,
7112 IN BOOLEAN bUseShortSlotTime)
7115 UINT32 RegValue = 0;
7117 #ifdef CONFIG_STA_SUPPORT
7118 if (pAd->CommonCfg.Channel > 14)
7119 bUseShortSlotTime = TRUE;
7120 #endif // CONFIG_STA_SUPPORT //
7122 if (bUseShortSlotTime)
7123 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7125 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7127 SlotTime = (bUseShortSlotTime)? 9 : 20;
7129 #ifdef CONFIG_STA_SUPPORT
7130 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7132 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7133 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7134 #ifdef DOT11_N_SUPPORT
7135 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7136 #endif // DOT11_N_SUPPORT //
7139 // In this case, we will think it is doing Wi-Fi test
7140 // And we will not set to short slot when bEnableTxBurst is TRUE.
7142 else if (pAd->CommonCfg.bEnableTxBurst)
7145 #endif // CONFIG_STA_SUPPORT //
7148 // For some reasons, always set it to short slot time.
7150 // ToDo: Should consider capability with 11B
7152 #ifdef CONFIG_STA_SUPPORT
7153 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7155 if (pAd->StaCfg.BssType == BSS_ADHOC)
7158 #endif // CONFIG_STA_SUPPORT //
7160 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7161 RegValue = RegValue & 0xFFFFFF00;
7163 RegValue |= SlotTime;
7165 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7169 ========================================================================
7171 Add Shared key information into ASIC.
7172 Update shared key, TxMic and RxMic to Asic Shared key table
7173 Update its cipherAlg to Asic Shared key Mode.
7176 ========================================================================
7178 VOID AsicAddSharedKeyEntry(
7179 IN PRTMP_ADAPTER pAd,
7187 ULONG offset; //, csr0;
7188 SHAREDKEY_MODE_STRUC csr1;
7193 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7194 //============================================================================================
7196 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7197 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7198 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]));
7201 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7202 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7206 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7207 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7209 //============================================================================================
7211 // fill key material - key + TX MIC + RX MIC
7214 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7215 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7217 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7220 offset += MAX_LEN_OF_SHARE_KEY;
7225 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7234 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7241 // Update cipher algorithm. WSTA always use BSS0
7243 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7244 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7245 if ((BssIndex%2) == 0)
7248 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7249 else if (KeyIdx == 1)
7250 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7251 else if (KeyIdx == 2)
7252 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7254 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7259 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7260 else if (KeyIdx == 1)
7261 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7262 else if (KeyIdx == 2)
7263 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7265 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7267 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7268 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7272 // IRQL = DISPATCH_LEVEL
7273 VOID AsicRemoveSharedKeyEntry(
7274 IN PRTMP_ADAPTER pAd,
7279 SHAREDKEY_MODE_STRUC csr1;
7281 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7283 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7284 if ((BssIndex%2) == 0)
7287 csr1.field.Bss0Key0CipherAlg = 0;
7288 else if (KeyIdx == 1)
7289 csr1.field.Bss0Key1CipherAlg = 0;
7290 else if (KeyIdx == 2)
7291 csr1.field.Bss0Key2CipherAlg = 0;
7293 csr1.field.Bss0Key3CipherAlg = 0;
7298 csr1.field.Bss1Key0CipherAlg = 0;
7299 else if (KeyIdx == 1)
7300 csr1.field.Bss1Key1CipherAlg = 0;
7301 else if (KeyIdx == 2)
7302 csr1.field.Bss1Key2CipherAlg = 0;
7304 csr1.field.Bss1Key3CipherAlg = 0;
7306 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7307 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7308 ASSERT(BssIndex < 4);
7314 VOID AsicUpdateWCIDAttribute(
7315 IN PRTMP_ADAPTER pAd,
7319 IN BOOLEAN bUsePairewiseKeyTable)
7321 ULONG WCIDAttri = 0, offset;
7324 // Update WCID attribute.
7325 // Only TxKey could update WCID attribute.
7327 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7328 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7329 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7332 VOID AsicUpdateWCIDIVEIV(
7333 IN PRTMP_ADAPTER pAd,
7340 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7342 RTMP_IO_WRITE32(pAd, offset, uIV);
7343 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7346 VOID AsicUpdateRxWCIDTable(
7347 IN PRTMP_ADAPTER pAd,
7354 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7355 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7356 RTMP_IO_WRITE32(pAd, offset, Addr);
7357 Addr = pAddr[4] + (pAddr[5] << 8);
7358 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7363 ========================================================================
7365 Routine Description:
7366 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7369 pAd Pointer to our adapter
7370 WCID WCID Entry number.
7371 BssIndex BSSID index, station or none multiple BSSID support
7372 this value should be 0.
7373 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7374 pCipherKey Pointer to Cipher Key.
7375 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7376 otherwise PairewiseKey table
7377 bTxKey This is the transmit key if enabled.
7383 This routine will set the relative key stuff to Asic including WCID attribute,
7384 Cipher Key, Cipher algorithm and IV/EIV.
7386 IV/EIV will be update if this CipherKey is the transmission key because
7387 ASIC will base on IV's KeyID value to select Cipher Key.
7389 If bTxKey sets to FALSE, this is not the TX key, but it could be
7392 For AP mode bTxKey must be always set to TRUE.
7393 ========================================================================
7395 VOID AsicAddKeyEntry(
7396 IN PRTMP_ADAPTER pAd,
7400 IN PCIPHER_KEY pCipherKey,
7401 IN BOOLEAN bUsePairewiseKeyTable,
7406 PUCHAR pKey = pCipherKey->Key;
7407 PUCHAR pTxMic = pCipherKey->TxMic;
7408 PUCHAR pRxMic = pCipherKey->RxMic;
7409 PUCHAR pTxtsc = pCipherKey->TxTsc;
7410 UCHAR CipherAlg = pCipherKey->CipherAlg;
7411 SHAREDKEY_MODE_STRUC csr1;
7416 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7418 // 1.) decide key table offset
7420 if (bUsePairewiseKeyTable)
7421 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7423 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7426 // 2.) Set Key to Asic
7428 //for (i = 0; i < KeyLen; i++)
7430 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7432 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7434 offset += MAX_LEN_OF_PEER_KEY;
7437 // 3.) Set MIC key if available
7441 for (i = 0; i < 8; i++)
7443 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7446 offset += LEN_TKIP_TXMICK;
7450 for (i = 0; i < 8; i++)
7452 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7459 // 4.) Modify IV/EIV if needs
7460 // This will force Asic to use this key ID by setting IV.
7465 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7469 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7470 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7471 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7473 IV4 = (KeyIdx << 6);
7474 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7475 IV4 |= 0x20; // turn on extension bit means EIV existence
7477 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7483 for (i = 0; i < 4; i++)
7485 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7489 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7492 if (!bUsePairewiseKeyTable)
7495 // Only update the shared key security mode
7497 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7498 if ((BssIndex % 2) == 0)
7501 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7502 else if (KeyIdx == 1)
7503 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7504 else if (KeyIdx == 2)
7505 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7507 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7512 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7513 else if (KeyIdx == 1)
7514 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7515 else if (KeyIdx == 2)
7516 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7518 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7520 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7523 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7528 ========================================================================
7530 Add Pair-wise key material into ASIC.
7531 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7534 ========================================================================
7536 VOID AsicAddPairwiseKeyEntry(
7537 IN PRTMP_ADAPTER pAd,
7540 IN CIPHER_KEY *pCipherKey)
7544 PUCHAR pKey = pCipherKey->Key;
7545 PUCHAR pTxMic = pCipherKey->TxMic;
7546 PUCHAR pRxMic = pCipherKey->RxMic;
7548 UCHAR CipherAlg = pCipherKey->CipherAlg;
7552 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7554 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7556 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7559 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7562 RTMP_IO_READ32(pAd, offset + i, &Value);
7565 offset += MAX_LEN_OF_PEER_KEY;
7573 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7583 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7588 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7589 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7590 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]));
7593 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7594 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7598 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7599 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7603 ========================================================================
7605 Remove Pair-wise key material from ASIC.
7608 ========================================================================
7610 VOID AsicRemovePairwiseKeyEntry(
7611 IN PRTMP_ADAPTER pAd,
7618 // re-set the entry's WCID attribute as OPEN-NONE.
7619 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7620 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7621 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7624 BOOLEAN AsicSendCommandToMcu(
7625 IN PRTMP_ADAPTER pAd,
7631 HOST_CMD_CSR_STRUC H2MCmd;
7632 H2M_MAILBOX_STRUC H2MMailbox;
7636 static UINT32 j = 0;
7637 #endif // RALINK_ATE //
7641 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7642 if (H2MMailbox.field.Owner == 0)
7652 if (pAd->ate.bFWLoading == TRUE)
7654 /* reloading firmware when received iwpriv cmd "ATE=ATESTOP" */
7659 DBGPRINT(RT_DEBUG_ERROR, ("#"));
7663 DBGPRINT(RT_DEBUG_ERROR, ("\n"));
7669 DBGPRINT(RT_DEBUG_ERROR, ("Loading firmware. Please wait for a moment...\n"));
7674 #endif // RALINK_ATE //
7680 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7682 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7684 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7685 // Reset DMA/CPU ring index
7686 RTMPRingCleanUp(pAd, QID_AC_BK);
7687 RTMPRingCleanUp(pAd, QID_AC_BE);
7688 RTMPRingCleanUp(pAd, QID_AC_VI);
7689 RTMPRingCleanUp(pAd, QID_AC_VO);
7690 RTMPRingCleanUp(pAd, QID_HCCA);
7691 RTMPRingCleanUp(pAd, QID_MGMT);
7692 RTMPRingCleanUp(pAd, QID_RX);
7695 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7697 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7698 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7705 else if (pAd->ate.bFWLoading == TRUE)
7707 /* reloading of firmware is completed */
7708 pAd->ate.bFWLoading = FALSE;
7709 DBGPRINT(RT_DEBUG_ERROR, ("\n"));
7712 #endif // RALINK_ATE //
7715 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7716 H2MMailbox.field.CmdToken = Token;
7717 H2MMailbox.field.HighByte = Arg1;
7718 H2MMailbox.field.LowByte = Arg0;
7719 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7722 H2MCmd.field.HostCommand = Command;
7723 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7725 if (Command != 0x80)
7733 BOOLEAN AsicCheckCommanOk(
7734 IN PRTMP_ADAPTER pAd,
7737 UINT32 CmdStatus = 0, CID = 0, i;
7738 UINT32 ThisCIDMask = 0;
7743 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7744 // Find where the command is. Because this is randomly specified by firmware.
7745 if ((CID & CID0MASK) == Command)
7747 ThisCIDMask = CID0MASK;
7750 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7752 ThisCIDMask = CID1MASK;
7755 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7757 ThisCIDMask = CID2MASK;
7760 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7762 ThisCIDMask = CID3MASK;
7770 // Get CommandStatus Value
7771 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7773 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7776 // If Status is 1, the comamnd is success.
7777 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7778 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7780 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7781 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7782 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7785 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7789 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7791 // Clear Command and Status.
7792 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7793 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7800 ========================================================================
7802 Routine Description:
7803 Verify the support rate for different PHY type
7806 pAd Pointer to our adapter
7811 IRQL = PASSIVE_LEVEL
7813 ========================================================================
7815 VOID RTMPCheckRates(
7816 IN PRTMP_ADAPTER pAd,
7817 IN OUT UCHAR SupRate[],
7818 IN OUT UCHAR *SupRateLen)
7820 UCHAR RateIdx, i, j;
7821 UCHAR NewRate[12], NewRateLen;
7825 if (pAd->CommonCfg.PhyMode == PHY_11B)
7830 // Check for support rates exclude basic rate bit
7831 for (i = 0; i < *SupRateLen; i++)
7832 for (j = 0; j < RateIdx; j++)
7833 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7834 NewRate[NewRateLen++] = SupRate[i];
7836 *SupRateLen = NewRateLen;
7837 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7840 #ifdef CONFIG_STA_SUPPORT
7841 #ifdef DOT11_N_SUPPORT
7842 BOOLEAN RTMPCheckChannel(
7843 IN PRTMP_ADAPTER pAd,
7844 IN UCHAR CentralChannel,
7848 UCHAR UpperChannel = 0, LowerChannel = 0;
7849 UCHAR NoEffectChannelinList = 0;
7851 // Find upper and lower channel according to 40MHz current operation.
7852 if (CentralChannel < Channel)
7854 UpperChannel = Channel;
7855 if (CentralChannel > 2)
7856 LowerChannel = CentralChannel - 2;
7860 else if (CentralChannel > Channel)
7862 UpperChannel = CentralChannel + 2;
7863 LowerChannel = Channel;
7866 for (k = 0;k < pAd->ChannelListNum;k++)
7868 if (pAd->ChannelList[k].Channel == UpperChannel)
7870 NoEffectChannelinList ++;
7872 if (pAd->ChannelList[k].Channel == LowerChannel)
7874 NoEffectChannelinList ++;
7878 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7879 if (NoEffectChannelinList == 2)
7886 ========================================================================
7888 Routine Description:
7889 Verify the support rate for HT phy type
7892 pAd Pointer to our adapter
7895 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7897 IRQL = PASSIVE_LEVEL
7899 ========================================================================
7901 BOOLEAN RTMPCheckHt(
7902 IN PRTMP_ADAPTER pAd,
7904 IN HT_CAPABILITY_IE *pHtCapability,
7905 IN ADD_HT_INFO_IE *pAddHtInfo)
7907 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7910 // If use AMSDU, set flag.
7911 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7912 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7913 // Save Peer Capability
7914 if (pHtCapability->HtCapInfo.ShortGIfor20)
7915 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7916 if (pHtCapability->HtCapInfo.ShortGIfor40)
7917 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7918 if (pHtCapability->HtCapInfo.TxSTBC)
7919 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7920 if (pHtCapability->HtCapInfo.RxSTBC)
7921 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7922 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7924 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7927 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7929 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7932 // Will check ChannelWidth for MCSSet[4] below
7933 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7934 switch (pAd->CommonCfg.RxStream)
7937 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7938 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7939 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7940 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7943 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7944 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7945 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7946 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7949 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7950 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7951 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7952 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7956 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7958 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7959 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7960 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7962 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7964 // Send Assoc Req with my HT capability.
7965 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7966 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7967 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7968 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7969 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7970 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7971 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7972 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7973 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7974 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7975 if (pAd->CommonCfg.bRdg)
7977 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7978 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7981 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7982 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7984 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7987 #endif // DOT11_N_SUPPORT //
7988 #endif // CONFIG_STA_SUPPORT //
7991 ========================================================================
7993 Routine Description:
7994 Verify the support rate for different PHY type
7997 pAd Pointer to our adapter
8002 IRQL = PASSIVE_LEVEL
8004 ========================================================================
8006 VOID RTMPUpdateMlmeRate(
8007 IN PRTMP_ADAPTER pAd)
8010 UCHAR ProperMlmeRate; //= RATE_54;
8011 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
8012 BOOLEAN bMatch = FALSE;
8014 switch (pAd->CommonCfg.PhyMode)
8017 ProperMlmeRate = RATE_11;
8018 MinimumRate = RATE_1;
8020 case PHY_11BG_MIXED:
8021 #ifdef DOT11_N_SUPPORT
8022 case PHY_11ABGN_MIXED:
8023 case PHY_11BGN_MIXED:
8024 #endif // DOT11_N_SUPPORT //
8025 if ((pAd->MlmeAux.SupRateLen == 4) &&
8026 (pAd->MlmeAux.ExtRateLen == 0))
8028 ProperMlmeRate = RATE_11;
8030 ProperMlmeRate = RATE_24;
8032 if (pAd->MlmeAux.Channel <= 14)
8033 MinimumRate = RATE_1;
8035 MinimumRate = RATE_6;
8038 #ifdef DOT11_N_SUPPORT
8039 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
8040 case PHY_11GN_MIXED:
8041 case PHY_11AGN_MIXED:
8042 case PHY_11AN_MIXED:
8044 #endif // DOT11_N_SUPPORT //
8045 ProperMlmeRate = RATE_24;
8046 MinimumRate = RATE_6;
8048 case PHY_11ABG_MIXED:
8049 ProperMlmeRate = RATE_24;
8050 if (pAd->MlmeAux.Channel <= 14)
8051 MinimumRate = RATE_1;
8053 MinimumRate = RATE_6;
8056 ProperMlmeRate = RATE_1;
8057 MinimumRate = RATE_1;
8061 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8063 for (j = 0; j < RateIdx; j++)
8065 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8067 if (j == ProperMlmeRate)
8079 if (bMatch == FALSE)
8081 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8083 for (j = 0; j < RateIdx; j++)
8085 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8087 if (j == ProperMlmeRate)
8100 if (bMatch == FALSE)
8102 ProperMlmeRate = MinimumRate;
8105 pAd->CommonCfg.MlmeRate = MinimumRate;
8106 pAd->CommonCfg.RtsRate = ProperMlmeRate;
8107 if (pAd->CommonCfg.MlmeRate >= RATE_6)
8109 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8110 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8111 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8112 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8116 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8117 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8118 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8119 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8122 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8126 IN PRTMP_ADAPTER pAd,
8133 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8138 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8140 larger = max(Rssi0, Rssi1);
8143 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8145 larger = max(larger, Rssi2);
8155 ========================================================================
8156 Routine Description:
8157 Periodic evaluate antenna link status
8160 pAd - Adapter pointer
8165 ========================================================================
8167 VOID AsicEvaluateRxAnt(
8168 IN PRTMP_ADAPTER pAd)
8175 #endif // RALINK_ATE //
8178 #ifdef CONFIG_STA_SUPPORT
8179 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8181 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8182 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8183 fRTMP_ADAPTER_RADIO_OFF |
8184 fRTMP_ADAPTER_NIC_NOT_EXIST |
8185 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
8188 if (pAd->StaCfg.Psm == PWR_SAVE)
8191 #endif // CONFIG_STA_SUPPORT //
8193 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8195 if(pAd->Antenna.field.RxPath == 3)
8199 else if(pAd->Antenna.field.RxPath == 2)
8203 else if(pAd->Antenna.field.RxPath == 1)
8207 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8208 #ifdef CONFIG_STA_SUPPORT
8210 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8211 pAd->StaCfg.BBPR3 = BBPR3;
8213 #endif // CONFIG_STA_SUPPORT //
8214 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8217 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8218 pAd->RalinkCounters.OneSecTxRetryOkCount +
8219 pAd->RalinkCounters.OneSecTxFailCount;
8221 if (TxTotalCnt > 50)
8223 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8224 pAd->Mlme.bLowThroughput = FALSE;
8228 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8229 pAd->Mlme.bLowThroughput = TRUE;
8235 ========================================================================
8236 Routine Description:
8237 After evaluation, check antenna link status
8240 pAd - Adapter pointer
8245 ========================================================================
8247 VOID AsicRxAntEvalTimeout(
8248 IN PVOID SystemSpecific1,
8249 IN PVOID FunctionContext,
8250 IN PVOID SystemSpecific2,
8251 IN PVOID SystemSpecific3)
8253 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8254 #ifdef CONFIG_STA_SUPPORT
8256 CHAR larger = -127, rssi0, rssi1, rssi2;
8257 #endif // CONFIG_STA_SUPPORT //
8262 #endif // RALINK_ATE //
8265 #ifdef CONFIG_STA_SUPPORT
8266 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8268 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8269 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8270 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8271 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8274 if (pAd->StaCfg.Psm == PWR_SAVE)
8278 // if the traffic is low, use average rssi as the criteria
8279 if (pAd->Mlme.bLowThroughput == TRUE)
8281 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8282 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8283 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8287 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8288 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8289 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8292 if(pAd->Antenna.field.RxPath == 3)
8294 larger = max(rssi0, rssi1);
8296 if (larger > (rssi2 + 20))
8297 pAd->Mlme.RealRxPath = 2;
8299 pAd->Mlme.RealRxPath = 3;
8301 else if(pAd->Antenna.field.RxPath == 2)
8303 if (rssi0 > (rssi1 + 20))
8304 pAd->Mlme.RealRxPath = 1;
8306 pAd->Mlme.RealRxPath = 2;
8309 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8311 if(pAd->Mlme.RealRxPath == 3)
8315 else if(pAd->Mlme.RealRxPath == 2)
8319 else if(pAd->Mlme.RealRxPath == 1)
8323 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8325 pAd->StaCfg.BBPR3 = BBPR3;
8329 #endif // CONFIG_STA_SUPPORT //
8335 VOID APSDPeriodicExec(
8336 IN PVOID SystemSpecific1,
8337 IN PVOID FunctionContext,
8338 IN PVOID SystemSpecific2,
8339 IN PVOID SystemSpecific3)
8341 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8343 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8346 pAd->CommonCfg.TriggerTimerCount++;
8351 ========================================================================
8352 Routine Description:
8353 Set/reset MAC registers according to bPiggyBack parameter
8356 pAd - Adapter pointer
8357 bPiggyBack - Enable / Disable Piggy-Back
8362 ========================================================================
8364 VOID RTMPSetPiggyBack(
8365 IN PRTMP_ADAPTER pAd,
8366 IN BOOLEAN bPiggyBack)
8368 TX_LINK_CFG_STRUC TxLinkCfg;
8370 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8372 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8373 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8377 ========================================================================
8378 Routine Description:
8379 check if this entry need to switch rate automatically
8389 ========================================================================
8391 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8392 IN PRTMP_ADAPTER pAd,
8393 IN PMAC_TABLE_ENTRY pEntry)
8395 BOOLEAN result = TRUE;
8398 #ifdef CONFIG_STA_SUPPORT
8399 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8401 // only associated STA counts
8402 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8404 result = pAd->StaCfg.bAutoTxRateSwitch;
8409 #ifdef QOS_DLS_SUPPORT
8410 if (pEntry && (pEntry->ValidAsDls))
8411 result = pAd->StaCfg.bAutoTxRateSwitch;
8412 #endif // QOS_DLS_SUPPORT //
8414 #endif // CONFIG_STA_SUPPORT //
8422 BOOLEAN RTMPAutoRateSwitchCheck(
8423 IN PRTMP_ADAPTER pAd)
8426 #ifdef CONFIG_STA_SUPPORT
8427 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8429 if (pAd->StaCfg.bAutoTxRateSwitch)
8432 #endif // CONFIG_STA_SUPPORT //
8438 ========================================================================
8439 Routine Description:
8440 check if this entry need to fix tx legacy rate
8450 ========================================================================
8452 UCHAR RTMPStaFixedTxMode(
8453 IN PRTMP_ADAPTER pAd,
8454 IN PMAC_TABLE_ENTRY pEntry)
8456 UCHAR tx_mode = FIXED_TXMODE_HT;
8459 #ifdef CONFIG_STA_SUPPORT
8460 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8462 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8464 #endif // CONFIG_STA_SUPPORT //
8470 ========================================================================
8471 Routine Description:
8472 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8482 ========================================================================
8484 VOID RTMPUpdateLegacyTxSetting(
8485 UCHAR fixed_tx_mode,
8486 PMAC_TABLE_ENTRY pEntry)
8488 HTTRANSMIT_SETTING TransmitSetting;
8490 if (fixed_tx_mode == FIXED_TXMODE_HT)
8493 TransmitSetting.word = 0;
8495 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8496 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8498 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8500 TransmitSetting.field.MODE = MODE_CCK;
8501 // CCK mode allow MCS 0~3
8502 if (TransmitSetting.field.MCS > MCS_3)
8503 TransmitSetting.field.MCS = MCS_3;
8507 TransmitSetting.field.MODE = MODE_OFDM;
8508 // OFDM mode allow MCS 0~7
8509 if (TransmitSetting.field.MCS > MCS_7)
8510 TransmitSetting.field.MCS = MCS_7;
8513 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8515 pEntry->HTPhyMode.word = TransmitSetting.word;
8516 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8517 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8521 #ifdef CONFIG_STA_SUPPORT
8523 ==========================================================================
8525 dynamic tune BBP R66 to find a balance between sensibility and
8528 IRQL = DISPATCH_LEVEL
8530 ==========================================================================
8532 VOID AsicStaBbpTuning(
8533 IN PRTMP_ADAPTER pAd)
8535 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8538 // 2860C did not support Fase CCA, therefore can't tune
8539 if (pAd->MACVersion == 0x28600100)
8545 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8548 if ((pAd->OpMode == OPMODE_STA)
8549 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8551 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8553 && (pAd->bPCIclkOff == FALSE)
8557 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8560 if (pAd->Antenna.field.RxPath > 1)
8561 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8563 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8565 if (pAd->LatchRfRegs.Channel <= 14)
8568 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8570 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8571 if (OrigR66Value != R66)
8573 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8578 R66 = 0x2E + GET_LNA_GAIN(pAd);
8579 if (OrigR66Value != R66)
8581 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8588 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8590 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8592 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8593 if (OrigR66Value != R66)
8595 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8600 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8601 if (OrigR66Value != R66)
8603 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8609 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8611 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8612 if (OrigR66Value != R66)
8614 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8619 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8620 if (OrigR66Value != R66)
8622 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8632 VOID AsicResetFromDMABusy(
8633 IN PRTMP_ADAPTER pAd)
8636 BOOLEAN bCtrl = FALSE;
8638 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8640 // Be sure restore link control value so we can write register.
8641 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8642 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8644 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8645 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8646 RTMPusecDelay(6000);
8647 pAd->bPCIclkOff = FALSE;
8651 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8653 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8655 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8656 // Reset DMA/CPU ring index
8657 RTMPRingCleanUp(pAd, QID_AC_BK);
8658 RTMPRingCleanUp(pAd, QID_AC_BE);
8659 RTMPRingCleanUp(pAd, QID_AC_VI);
8660 RTMPRingCleanUp(pAd, QID_AC_VO);
8661 RTMPRingCleanUp(pAd, QID_HCCA);
8662 RTMPRingCleanUp(pAd, QID_MGMT);
8663 RTMPRingCleanUp(pAd, QID_RX);
8666 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8668 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8670 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8671 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8672 RTMPPCIeLinkCtrlSetting(pAd, 3);
8674 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8675 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8676 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8680 IN PRTMP_ADAPTER pAd)
8682 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8684 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8685 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8686 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8688 // After hard-reset BBP, initialize all BBP values.
8689 NICRestoreBBPValue(pAd);
8690 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8694 IN PRTMP_ADAPTER pAd)
8698 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8699 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8701 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8703 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8705 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8709 IN PRTMP_ADAPTER pAd)
8711 ULONG Value1, Value2;
8714 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8715 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8718 // sum should be equals to 0xff, which is the total buffer size.
8719 if ((Value1 + Value2) < 0xff)
8721 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8722 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8724 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8726 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8728 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8731 #endif // CONFIG_STA_SUPPORT //
8733 VOID RTMPSetAGCInitValue(
8734 IN PRTMP_ADAPTER pAd,
8739 if (pAd->LatchRfRegs.Channel <= 14)
8741 R66 = 0x2E + GET_LNA_GAIN(pAd);
8742 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8746 if (BandWidth == BW_20)
8748 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8749 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8751 #ifdef DOT11_N_SUPPORT
8754 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8755 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8757 #endif // DOT11_N_SUPPORT //
8762 VOID AsicTurnOffRFClk(
8763 IN PRTMP_ADAPTER pAd,
8768 UINT32 R1 = 0, R2 = 0, R3 = 0;
8770 RTMP_RF_REGS *RFRegTable;
8772 RFRegTable = RF2850RegTable;
8774 switch (pAd->RfIcType)
8781 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8783 if (Channel == RFRegTable[index].Channel)
8785 R1 = RFRegTable[index].R1 & 0xffffdfff;
8786 R2 = RFRegTable[index].R2 & 0xfffbffff;
8787 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8789 RTMP_RF_IO_WRITE32(pAd, R1);
8790 RTMP_RF_IO_WRITE32(pAd, R2);
8792 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8793 // Set RF R2 bit18=0, R3 bit[18:19]=0
8794 //if (pAd->StaCfg.bRadio == FALSE)
8797 RTMP_RF_IO_WRITE32(pAd, R3);
8799 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8800 Channel, pAd->RfIcType, R2, R3));
8803 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8804 Channel, pAd->RfIcType, R2));
8816 VOID AsicTurnOnRFClk(
8817 IN PRTMP_ADAPTER pAd,
8822 UINT32 R1 = 0, R2 = 0, R3 = 0;
8824 RTMP_RF_REGS *RFRegTable;
8826 RFRegTable = RF2850RegTable;
8828 switch (pAd->RfIcType)
8835 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8837 if (Channel == RFRegTable[index].Channel)
8839 R3 = pAd->LatchRfRegs.R3;
8842 RTMP_RF_IO_WRITE32(pAd, R3);
8844 R1 = RFRegTable[index].R1;
8845 RTMP_RF_IO_WRITE32(pAd, R1);
8847 R2 = RFRegTable[index].R2;
8848 if (pAd->Antenna.field.TxPath == 1)
8850 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8853 if (pAd->Antenna.field.RxPath == 2)
8855 R2 |= 0x40; // write 1 to off Rxpath.
8857 else if (pAd->Antenna.field.RxPath == 1)
8859 R2 |= 0x20040; // write 1 to off RxPath
8861 RTMP_RF_IO_WRITE32(pAd, R2);
8872 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",