2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-08-25 Modify from RT2500 code base
36 John Chang 2004-09-06 modified for RT2600
39 #include "../rt_config.h"
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
44 UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45 UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
46 UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
47 UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
48 UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
49 UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
50 UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
51 UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
52 UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
53 #ifdef CONFIG_STA_SUPPORT
54 #ifdef DOT11_N_SUPPORT
55 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
56 #endif // DOT11_N_SUPPORT //
57 #endif // CONFIG_STA_SUPPORT //
59 UCHAR RateSwitchTable[] = {
60 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
61 0x11, 0x00, 0, 0, 0, // Initial used item after association
62 0x00, 0x00, 0, 40, 101,
63 0x01, 0x00, 1, 40, 50,
64 0x02, 0x00, 2, 35, 45,
65 0x03, 0x00, 3, 20, 45,
66 0x04, 0x21, 0, 30, 50,
67 0x05, 0x21, 1, 20, 50,
68 0x06, 0x21, 2, 20, 50,
69 0x07, 0x21, 3, 15, 50,
70 0x08, 0x21, 4, 15, 30,
71 0x09, 0x21, 5, 10, 25,
74 0x0c, 0x20, 12, 15, 30,
75 0x0d, 0x20, 13, 8, 20,
76 0x0e, 0x20, 14, 8, 20,
77 0x0f, 0x20, 15, 8, 25,
78 0x10, 0x22, 15, 8, 25,
96 UCHAR RateSwitchTable11B[] = {
97 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
98 0x04, 0x03, 0, 0, 0, // Initial used item after association
99 0x00, 0x00, 0, 40, 101,
100 0x01, 0x00, 1, 40, 50,
101 0x02, 0x00, 2, 35, 45,
102 0x03, 0x00, 3, 20, 45,
105 UCHAR RateSwitchTable11BG[] = {
106 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
107 0x0a, 0x00, 0, 0, 0, // Initial used item after association
108 0x00, 0x00, 0, 40, 101,
109 0x01, 0x00, 1, 40, 50,
110 0x02, 0x00, 2, 35, 45,
111 0x03, 0x00, 3, 20, 45,
112 0x04, 0x10, 2, 20, 35,
113 0x05, 0x10, 3, 16, 35,
114 0x06, 0x10, 4, 10, 25,
115 0x07, 0x10, 5, 16, 25,
116 0x08, 0x10, 6, 10, 25,
117 0x09, 0x10, 7, 10, 13,
120 UCHAR RateSwitchTable11G[] = {
121 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
122 0x08, 0x00, 0, 0, 0, // Initial used item after association
123 0x00, 0x10, 0, 20, 101,
124 0x01, 0x10, 1, 20, 35,
125 0x02, 0x10, 2, 20, 35,
126 0x03, 0x10, 3, 16, 35,
127 0x04, 0x10, 4, 10, 25,
128 0x05, 0x10, 5, 16, 25,
129 0x06, 0x10, 6, 10, 25,
130 0x07, 0x10, 7, 10, 13,
133 #ifdef DOT11_N_SUPPORT
134 UCHAR RateSwitchTable11N1S[] = {
135 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
136 0x09, 0x00, 0, 0, 0, // Initial used item after association
137 0x00, 0x21, 0, 30, 101,
138 0x01, 0x21, 1, 20, 50,
139 0x02, 0x21, 2, 20, 50,
140 0x03, 0x21, 3, 15, 50,
141 0x04, 0x21, 4, 15, 30,
142 0x05, 0x21, 5, 10, 25,
143 0x06, 0x21, 6, 8, 14,
144 0x07, 0x21, 7, 8, 14,
145 0x08, 0x23, 7, 8, 14,
148 UCHAR RateSwitchTable11N2S[] = {
149 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
150 0x0a, 0x00, 0, 0, 0, // Initial used item after association
151 0x00, 0x21, 0, 30, 101,
152 0x01, 0x21, 1, 20, 50,
153 0x02, 0x21, 2, 20, 50,
154 0x03, 0x21, 3, 15, 50,
155 0x04, 0x21, 4, 15, 30,
156 0x05, 0x20, 12, 15, 30,
157 0x06, 0x20, 13, 8, 20,
158 0x07, 0x20, 14, 8, 20,
159 0x08, 0x20, 15, 8, 25,
160 0x09, 0x22, 15, 8, 25,
163 UCHAR RateSwitchTable11N3S[] = {
164 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
165 0x0a, 0x00, 0, 0, 0, // Initial used item after association
166 0x00, 0x21, 0, 30, 101,
167 0x01, 0x21, 1, 20, 50,
168 0x02, 0x21, 2, 20, 50,
169 0x03, 0x21, 3, 15, 50,
170 0x04, 0x21, 4, 15, 30,
171 0x05, 0x20, 12, 15, 30,
172 0x06, 0x20, 13, 8, 20,
173 0x07, 0x20, 14, 8, 20,
174 0x08, 0x20, 15, 8, 25,
175 0x09, 0x22, 15, 8, 25,
178 UCHAR RateSwitchTable11N2SForABand[] = {
179 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
180 0x0b, 0x09, 0, 0, 0, // Initial used item after association
181 0x00, 0x21, 0, 30, 101,
182 0x01, 0x21, 1, 20, 50,
183 0x02, 0x21, 2, 20, 50,
184 0x03, 0x21, 3, 15, 50,
185 0x04, 0x21, 4, 15, 30,
186 0x05, 0x21, 5, 15, 30,
187 0x06, 0x20, 12, 15, 30,
188 0x07, 0x20, 13, 8, 20,
189 0x08, 0x20, 14, 8, 20,
190 0x09, 0x20, 15, 8, 25,
191 0x0a, 0x22, 15, 8, 25,
194 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
195 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
196 0x0b, 0x09, 0, 0, 0, // Initial used item after association
197 0x00, 0x21, 0, 30, 101,
198 0x01, 0x21, 1, 20, 50,
199 0x02, 0x21, 2, 20, 50,
200 0x03, 0x21, 3, 15, 50,
201 0x04, 0x21, 4, 15, 30,
202 0x05, 0x21, 5, 15, 30,
203 0x06, 0x20, 12, 15, 30,
204 0x07, 0x20, 13, 8, 20,
205 0x08, 0x20, 14, 8, 20,
206 0x09, 0x20, 15, 8, 25,
207 0x0a, 0x22, 15, 8, 25,
210 UCHAR RateSwitchTable11BGN1S[] = {
211 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
212 0x0d, 0x00, 0, 0, 0, // Initial used item after association
213 0x00, 0x00, 0, 40, 101,
214 0x01, 0x00, 1, 40, 50,
215 0x02, 0x00, 2, 35, 45,
216 0x03, 0x00, 3, 20, 45,
217 0x04, 0x21, 0, 30,101, //50
218 0x05, 0x21, 1, 20, 50,
219 0x06, 0x21, 2, 20, 50,
220 0x07, 0x21, 3, 15, 50,
221 0x08, 0x21, 4, 15, 30,
222 0x09, 0x21, 5, 10, 25,
223 0x0a, 0x21, 6, 8, 14,
224 0x0b, 0x21, 7, 8, 14,
225 0x0c, 0x23, 7, 8, 14,
228 UCHAR RateSwitchTable11BGN2S[] = {
229 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
230 0x0a, 0x00, 0, 0, 0, // Initial used item after association
231 0x00, 0x21, 0, 30,101, //50
232 0x01, 0x21, 1, 20, 50,
233 0x02, 0x21, 2, 20, 50,
234 0x03, 0x21, 3, 15, 50,
235 0x04, 0x21, 4, 15, 30,
236 0x05, 0x20, 12, 15, 30,
237 0x06, 0x20, 13, 8, 20,
238 0x07, 0x20, 14, 8, 20,
239 0x08, 0x20, 15, 8, 25,
240 0x09, 0x22, 15, 8, 25,
243 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
244 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
245 0x0a, 0x00, 0, 0, 0, // Initial used item after association
246 0x00, 0x21, 0, 30,101, //50
247 0x01, 0x21, 1, 20, 50,
248 0x02, 0x21, 2, 20, 50,
249 0x03, 0x21, 3, 20, 50,
250 0x04, 0x21, 4, 15, 50,
252 0x05, 0x20, 20, 15, 30,
253 0x06, 0x20, 21, 8, 20,
254 0x07, 0x20, 22, 8, 20,
255 0x08, 0x20, 23, 8, 25,
256 0x09, 0x22, 23, 8, 25,
257 #else // for RT2860 2*3 test
258 0x05, 0x20, 12, 15, 30,
259 0x06, 0x20, 13, 8, 20,
260 0x07, 0x20, 14, 8, 20,
261 0x08, 0x20, 15, 8, 25,
262 0x09, 0x22, 15, 8, 25,
266 UCHAR RateSwitchTable11BGN2SForABand[] = {
267 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
268 0x0b, 0x09, 0, 0, 0, // Initial used item after association
269 0x00, 0x21, 0, 30,101, //50
270 0x01, 0x21, 1, 20, 50,
271 0x02, 0x21, 2, 20, 50,
272 0x03, 0x21, 3, 15, 50,
273 0x04, 0x21, 4, 15, 30,
274 0x05, 0x21, 5, 15, 30,
275 0x06, 0x20, 12, 15, 30,
276 0x07, 0x20, 13, 8, 20,
277 0x08, 0x20, 14, 8, 20,
278 0x09, 0x20, 15, 8, 25,
279 0x0a, 0x22, 15, 8, 25,
282 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
283 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
284 0x0c, 0x09, 0, 0, 0, // Initial used item after association
285 0x00, 0x21, 0, 30,101, //50
286 0x01, 0x21, 1, 20, 50,
287 0x02, 0x21, 2, 20, 50,
288 0x03, 0x21, 3, 15, 50,
289 0x04, 0x21, 4, 15, 30,
290 0x05, 0x21, 5, 15, 30,
291 0x06, 0x21, 12, 15, 30,
292 0x07, 0x20, 20, 15, 30,
293 0x08, 0x20, 21, 8, 20,
294 0x09, 0x20, 22, 8, 20,
295 0x0a, 0x20, 23, 8, 25,
296 0x0b, 0x22, 23, 8, 25,
298 #endif // DOT11_N_SUPPORT //
300 PUCHAR ReasonString[] = {
302 /* 1 */ "Unspecified Reason",
303 /* 2 */ "Previous Auth no longer valid",
304 /* 3 */ "STA is leaving / has left",
305 /* 4 */ "DIS-ASSOC due to inactivity",
306 /* 5 */ "AP unable to hanle all associations",
307 /* 6 */ "class 2 error",
308 /* 7 */ "class 3 error",
309 /* 8 */ "STA is leaving / has left",
310 /* 9 */ "require auth before assoc/re-assoc",
314 /* 13 */ "invalid IE",
315 /* 14 */ "MIC error",
316 /* 15 */ "4-way handshake timeout",
317 /* 16 */ "2-way (group key) handshake timeout",
318 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
322 extern UCHAR OfdmRateToRxwiMCS[];
323 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
324 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
325 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
326 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
327 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
329 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
330 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
331 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
333 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
334 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
335 // clean environment.
336 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
337 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
339 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
340 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
342 UCHAR SsidIe = IE_SSID;
343 UCHAR SupRateIe = IE_SUPP_RATES;
344 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
345 #ifdef DOT11_N_SUPPORT
346 UCHAR HtCapIe = IE_HT_CAP;
347 UCHAR AddHtInfoIe = IE_ADD_HT;
348 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
350 UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
351 #endif // DOT11N_DRAFT3 //
352 #endif // DOT11_N_SUPPORT //
353 UCHAR ErpIe = IE_ERP;
354 UCHAR DsIe = IE_DS_PARM;
355 UCHAR TimIe = IE_TIM;
356 UCHAR WpaIe = IE_WPA;
357 UCHAR Wpa2Ie = IE_WPA2;
358 UCHAR IbssIe = IE_IBSS_PARM;
359 UCHAR Ccx2Ie = IE_CCX_V2;
360 UCHAR WapiIe = IE_WAPI;
362 extern UCHAR WPA_OUI[];
364 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
366 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
367 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
369 // Reset the RFIC setting to new series
370 RTMP_RF_REGS RF2850RegTable[] = {
371 // ch R1 R2 R3(TX0~4=0) R4
372 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
373 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
374 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
375 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
376 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
377 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
378 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
379 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
380 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
381 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
382 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
383 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
384 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
385 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
387 // 802.11 UNI / HyperLan 2
388 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
389 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
390 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
391 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
392 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
393 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
394 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
395 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
396 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
397 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
398 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
399 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
402 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
404 // 2008.04.30 modified
405 // The system team has AN to improve the EVM value
406 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
407 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
408 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
409 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
411 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
412 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
413 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
414 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
415 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
416 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
417 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
418 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
419 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
420 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
421 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
422 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
425 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
426 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
427 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
428 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
429 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
430 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
431 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
434 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
435 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
436 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
437 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
438 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
439 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
440 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
442 // still lack of MMAC(Japan) ch 34,38,42,46
444 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
446 FREQUENCY_ITEM FreqItems3020[] =
448 /**************************************************/
449 // ISM : 2.4 to 2.483 GHz //
450 /**************************************************/
452 /**************************************************/
453 //-CH---N-------R---K-----------
469 //2008/07/10:KH Modified to share this variable
470 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
473 ==========================================================================
475 initialize the MLME task and its data structure (queue, spinlock,
476 timer, state machines).
481 always return NDIS_STATUS_SUCCESS
483 ==========================================================================
485 NDIS_STATUS MlmeInit(
486 IN PRTMP_ADAPTER pAd)
488 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
490 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
494 Status = MlmeQueueInit(&pAd->Mlme.Queue);
495 if(Status != NDIS_STATUS_SUCCESS)
498 pAd->Mlme.bRunning = FALSE;
499 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
501 #ifdef CONFIG_STA_SUPPORT
502 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
504 BssTableInit(&pAd->ScanTab);
506 // init STA state machines
507 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
508 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
509 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
510 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
511 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
512 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
514 #ifdef QOS_DLS_SUPPORT
515 DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc);
516 #endif // QOS_DLS_SUPPORT //
519 // Since we are using switch/case to implement it, the init is different from the above
520 // state machine init
521 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
523 #endif // CONFIG_STA_SUPPORT //
527 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
529 // Init mlme periodic timer
530 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
532 // Set mlme periodic timer
533 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
535 // software-based RX Antenna diversity
536 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
539 #ifdef CONFIG_STA_SUPPORT
540 #endif // CONFIG_STA_SUPPORT //
544 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
550 ==========================================================================
552 main loop of the MLME
554 Mlme has to be initialized, and there are something inside the queue
556 This function is invoked from MPSetInformation and MPReceive;
557 This task guarantee only one MlmeHandler will run.
559 IRQL = DISPATCH_LEVEL
561 ==========================================================================
564 IN PRTMP_ADAPTER pAd)
566 MLME_QUEUE_ELEM *Elem = NULL;
568 // Only accept MLME and Frame from peer side, no other (control/data) frame should
569 // get into this state machine
571 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
572 if(pAd->Mlme.bRunning)
574 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
579 pAd->Mlme.bRunning = TRUE;
581 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
583 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
585 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
586 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
587 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
589 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
596 DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n"));
599 #endif // RALINK_ATE //
601 //From message type, determine which state machine I should drive
602 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
605 if (Elem->MsgType == MT2_RESET_CONF)
607 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
608 MlmeRestartStateMachine(pAd);
609 Elem->Occupied = FALSE;
615 // if dequeue success
616 switch (Elem->Machine)
618 // STA state machines
619 #ifdef CONFIG_STA_SUPPORT
620 case ASSOC_STATE_MACHINE:
621 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
623 case AUTH_STATE_MACHINE:
624 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
626 case AUTH_RSP_STATE_MACHINE:
627 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
629 case SYNC_STATE_MACHINE:
630 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
632 case MLME_CNTL_STATE_MACHINE:
633 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
635 case WPA_PSK_STATE_MACHINE:
636 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
639 case LEAP_STATE_MACHINE:
640 LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
643 case AIRONET_STATE_MACHINE:
644 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
647 #ifdef QOS_DLS_SUPPORT
648 case DLS_STATE_MACHINE:
649 StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem);
651 #endif // QOS_DLS_SUPPORT //
652 #endif // CONFIG_STA_SUPPORT //
654 case ACTION_STATE_MACHINE:
655 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
662 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
667 Elem->Occupied = FALSE;
672 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
676 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
677 pAd->Mlme.bRunning = FALSE;
678 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
682 ==========================================================================
684 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
686 Adapter - NIC Adapter pointer
688 The MLME task will no longer work properly
692 ==========================================================================
695 IN PRTMP_ADAPTER pAd)
699 UINT32 TxPinCfg = 0x00050F0F;
702 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
704 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
706 // disable BEACON generation and other BEACON related hardware timers
707 AsicDisableSync(pAd);
710 #ifdef CONFIG_STA_SUPPORT
711 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
713 #ifdef QOS_DLS_SUPPORT
715 #endif // QOS_DLS_SUPPORT //
716 // Cancel pending timers
717 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
718 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
719 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
720 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
721 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
722 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
724 #ifdef QOS_DLS_SUPPORT
725 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
727 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
729 #endif // QOS_DLS_SUPPORT //
731 #endif // CONFIG_STA_SUPPORT //
733 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
734 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
738 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
741 RTMPSetLED(pAd, LED_HALT);
742 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
745 LED_CFG_STRUC LedCfg;
746 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
747 LedCfg.field.LedPolar = 0;
748 LedCfg.field.RLedMode = 0;
749 LedCfg.field.GLedMode = 0;
750 LedCfg.field.YLedMode = 0;
751 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
758 if (IS_RT3070(pAd) || IS_RT3071(pAd))
760 TxPinCfg &= 0xFFFFF0F0;
761 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
766 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
768 MlmeQueueDestroy(&pAd->Mlme.Queue);
769 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
771 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
774 VOID MlmeResetRalinkCounters(
775 IN PRTMP_ADAPTER pAd)
777 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
778 // clear all OneSecxxx counters.
779 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
780 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
781 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
782 pAd->RalinkCounters.OneSecRxOkCnt = 0;
783 pAd->RalinkCounters.OneSecTxFailCount = 0;
784 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
785 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
786 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
788 // TODO: for debug only. to be removed
789 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
790 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
791 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
792 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
793 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
794 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
795 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
796 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
797 pAd->RalinkCounters.OneSecTxDoneCount = 0;
798 pAd->RalinkCounters.OneSecRxCount = 0;
799 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
800 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
805 unsigned long rx_AMSDU;
806 unsigned long rx_Total;
809 ==========================================================================
811 This routine is executed periodically to -
812 1. Decide if it's a right time to turn on PwrMgmt bit of all
814 2. Calculate ChannelQuality based on statistics of the last
815 period, so that TX rate won't toggling very frequently between a
816 successful TX and a failed TX.
817 3. If the calculated ChannelQuality indicated current connection not
818 healthy, then a ROAMing attempt is tried here.
820 IRQL = DISPATCH_LEVEL
822 ==========================================================================
824 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
825 VOID MlmePeriodicExec(
826 IN PVOID SystemSpecific1,
827 IN PVOID FunctionContext,
828 IN PVOID SystemSpecific2,
829 IN PVOID SystemSpecific3)
832 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
834 #ifdef CONFIG_STA_SUPPORT
835 #endif // CONFIG_STA_SUPPORT //
837 // Do nothing if the driver is starting halt state.
838 // This might happen when timer already been fired before cancel timer with mlmehalt
839 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
840 fRTMP_ADAPTER_RADIO_OFF |
841 fRTMP_ADAPTER_RADIO_MEASUREMENT |
842 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
845 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
848 /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */
851 if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1))
853 pAd->Mlme.PeriodicRound ++;
857 #endif // RALINK_ATE //
859 #ifdef CONFIG_STA_SUPPORT
860 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
862 // Do nothing if monitor mode is on
866 if (pAd->Mlme.PeriodicRound & 0x1)
868 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
869 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
870 (STA_TGN_WIFI_ON(pAd)) &&
871 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
874 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
875 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
877 else if ((STA_TGN_WIFI_ON(pAd)) &&
878 ((pAd->MACVersion & 0xffff) == 0x0101))
880 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
881 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
885 #endif // CONFIG_STA_SUPPORT //
887 pAd->bUpdateBcnCntDone = FALSE;
889 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
890 pAd->Mlme.PeriodicRound ++;
893 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
894 NICUpdateFifoStaCounters(pAd);
896 // execute every 500ms
897 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
899 #ifdef CONFIG_STA_SUPPORT
900 // perform dynamic tx rate switching based on past TX history
901 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
903 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
905 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
906 MlmeDynamicTxRateSwitching(pAd);
908 #endif // CONFIG_STA_SUPPORT //
911 // Normal 1 second Mlme PeriodicExec.
912 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
914 pAd->Mlme.OneSecPeriodicRound ++;
919 /* request from Baron : move this routine from later to here */
920 /* for showing Rx error count in ATE RXFRAME */
921 NICUpdateRawCounters(pAd);
922 if (pAd->ate.bRxFer == 1)
924 pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec;
925 ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt);
926 pAd->ate.RxCntPerSec = 0;
928 if (pAd->ate.RxAntennaSel == 0)
929 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n",
930 pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2);
932 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0);
934 MlmeResetRalinkCounters(pAd);
937 #endif // RALINK_ATE //
948 //ORIBATimerTimeout(pAd);
950 // Media status changed, report to NDIS
951 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
953 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
954 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
956 pAd->IndicateMediaState = NdisMediaStateConnected;
957 RTMP_IndicateMediaState(pAd);
962 pAd->IndicateMediaState = NdisMediaStateDisconnected;
963 RTMP_IndicateMediaState(pAd);
967 NdisGetSystemUpTime(&pAd->Mlme.Now32);
969 // add the most up-to-date h/w raw counters into software variable, so that
970 // the dynamic tuning mechanism below are based on most up-to-date information
971 NICUpdateRawCounters(pAd);
974 RT2870_WatchDog(pAd);
977 #ifdef DOT11_N_SUPPORT
978 // Need statistics after read counter. So put after NICUpdateRawCounters
979 ORIBATimerTimeout(pAd);
980 #endif // DOT11_N_SUPPORT //
982 // The time period for checking antenna is according to traffic
984 if (pAd->Mlme.bEnableAutoAntennaCheck)
986 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
987 pAd->RalinkCounters.OneSecTxRetryOkCount +
988 pAd->RalinkCounters.OneSecTxFailCount;
990 // dynamic adjust antenna evaluation period according to the traffic
993 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
995 AsicEvaluateRxAnt(pAd);
1000 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
1002 AsicEvaluateRxAnt(pAd);
1008 #ifdef CONFIG_STA_SUPPORT
1009 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1010 STAMlmePeriodicExec(pAd);
1011 #endif // CONFIG_STA_SUPPORT //
1013 MlmeResetRalinkCounters(pAd);
1015 #ifdef CONFIG_STA_SUPPORT
1016 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1019 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1020 // and sending CTS-to-self over and over.
1021 // Software Patch Solution:
1022 // 1. Polling debug state register 0x10F4 every one second.
1023 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1024 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1028 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1029 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1031 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1033 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1035 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1039 #endif // CONFIG_STA_SUPPORT //
1041 RT28XX_MLME_HANDLER(pAd);
1045 pAd->bUpdateBcnCntDone = FALSE;
1048 #ifdef CONFIG_STA_SUPPORT
1049 VOID STAMlmePeriodicExec(
1056 // We return here in ATE mode, because the statistics
1057 // that ATE needs are not collected via this routine.
1060 // It is supposed that we will never reach here in ATE mode.
1061 ASSERT(!(ATE_ON(pAd)));
1064 #endif // RALINK_ATE //
1066 #ifdef WPA_SUPPLICANT_SUPPORT
1067 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1068 #endif // WPA_SUPPLICANT_SUPPORT //
1070 // WPA MIC error should block association attempt for 60 seconds
1071 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1072 pAd->StaCfg.bBlockAssoc = FALSE;
1075 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1077 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1079 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1081 pAd->PreMediaState = pAd->IndicateMediaState;
1087 AsicStaBbpTuning(pAd);
1089 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1090 pAd->RalinkCounters.OneSecTxRetryOkCount +
1091 pAd->RalinkCounters.OneSecTxFailCount;
1093 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1095 // update channel quality for Roaming and UI LinkQuality display
1096 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1099 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1100 // Radio is currently in noisy environment
1101 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1102 AsicAdjustTxPower(pAd);
1106 #ifdef QOS_DLS_SUPPORT
1107 // Check DLS time out, then tear down those session
1108 RTMPCheckDLSTimeOut(pAd);
1109 #endif // QOS_DLS_SUPPORT //
1111 // Is PSM bit consistent with user power management policy?
1112 // This is the only place that will set PSM bit ON.
1113 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1114 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1116 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1118 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1119 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1120 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1122 RTMPSetAGCInitValue(pAd, BW_20);
1123 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1126 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1127 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1129 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1131 // When APSD is enabled, the period changes as 20 sec
1132 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1133 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1137 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1138 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1140 if (pAd->CommonCfg.bWmmCapable)
1141 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1143 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1148 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1150 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1151 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1152 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1154 // Lost AP, send disconnect & link down event
1155 LinkDown(pAd, FALSE);
1157 #ifdef WPA_SUPPLICANT_SUPPORT
1158 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1159 if (pAd->StaCfg.WpaSupplicantUP)
1161 union iwreq_data wrqu;
1162 //send disassociate event to wpa_supplicant
1163 memset(&wrqu, 0, sizeof(wrqu));
1164 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1165 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1167 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1168 #endif // WPA_SUPPLICANT_SUPPORT //
1170 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1172 union iwreq_data wrqu;
1173 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1174 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1176 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1178 // RTMPPatchMacBbpBug(pAd);
1179 MlmeAutoReconnectLastSSID(pAd);
1181 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1183 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1184 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1185 MlmeAutoReconnectLastSSID(pAd);
1188 // Add auto seamless roaming
1189 if (pAd->StaCfg.bFastRoaming)
1191 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1193 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));
1195 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1197 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1201 else if (ADHOC_ON(pAd))
1204 if ((pAd->CommonCfg.Channel > 14)
1205 && (pAd->CommonCfg.bIEEE80211H == 1)
1206 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1208 RadarDetectPeriodic(pAd);
1211 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1212 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1214 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1215 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1217 MLME_START_REQ_STRUCT StartReq;
1219 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1220 LinkDown(pAd, FALSE);
1222 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1223 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1224 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1227 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1229 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1231 if (pEntry->ValidAsCLI == FALSE)
1234 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1235 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1238 else // no INFRA nor ADHOC connection
1241 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1242 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1243 goto SKIP_AUTO_SCAN_CONN;
1245 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1247 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1248 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1249 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1251 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1253 MLME_SCAN_REQ_STRUCT ScanReq;
1255 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1257 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1258 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1259 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1260 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1261 // Reset Missed scan number
1262 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1264 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1265 MlmeAutoReconnectLastSSID(pAd);
1267 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1269 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1272 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1276 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1277 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1279 if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1)
1280 MlmeAutoReconnectLastSSID(pAd);
1283 #endif // CARRIER_DETECTION_SUPPORT //
1284 MlmeAutoReconnectLastSSID(pAd);
1290 SKIP_AUTO_SCAN_CONN:
1292 #ifdef DOT11_N_SUPPORT
1293 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1295 pAd->MacTab.fAnyBASession = TRUE;
1296 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1298 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1300 pAd->MacTab.fAnyBASession = FALSE;
1301 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1303 #endif // DOT11_N_SUPPORT //
1306 #ifdef DOT11_N_SUPPORT
1307 #ifdef DOT11N_DRAFT3
1308 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1309 TriEventCounterMaintenance(pAd);
1310 #endif // DOT11N_DRAFT3 //
1311 #endif // DOT11_N_SUPPORT //
1318 IN PVOID SystemSpecific1,
1319 IN PVOID FunctionContext,
1320 IN PVOID SystemSpecific2,
1321 IN PVOID SystemSpecific3)
1324 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1326 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1327 RTMP_IndicateMediaState(pAd);
1328 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1331 // IRQL = DISPATCH_LEVEL
1333 IN PRTMP_ADAPTER pAd)
1335 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1336 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1338 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1340 MLME_CNTL_STATE_MACHINE,
1341 OID_802_11_BSSID_LIST_SCAN,
1344 RT28XX_MLME_HANDLER(pAd);
1348 // IRQL = DISPATCH_LEVEL
1349 VOID MlmeAutoReconnectLastSSID(
1350 IN PRTMP_ADAPTER pAd)
1354 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1355 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1356 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1358 NDIS_802_11_SSID OidSsid;
1359 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1360 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1362 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1364 MLME_CNTL_STATE_MACHINE,
1366 sizeof(NDIS_802_11_SSID),
1368 RT28XX_MLME_HANDLER(pAd);
1371 #endif // CONFIG_STA_SUPPORT //
1374 ==========================================================================
1375 Validate SSID for connection try and rescan purpose
1376 Valid SSID will have visible chars only.
1377 The valid length is from 0 to 32.
1378 IRQL = DISPATCH_LEVEL
1379 ==========================================================================
1381 BOOLEAN MlmeValidateSSID(
1387 if (SsidLen > MAX_LEN_OF_SSID)
1390 // Check each character value
1391 for (index = 0; index < SsidLen; index++)
1393 if (pSsid[index] < 0x20)
1401 VOID MlmeSelectTxRateTable(
1402 IN PRTMP_ADAPTER pAd,
1403 IN PMAC_TABLE_ENTRY pEntry,
1405 IN PUCHAR pTableSize,
1406 IN PUCHAR pInitTxRateIdx)
1410 // decide the rate table for tuning
1411 if (pAd->CommonCfg.TxRateTableSize > 0)
1413 *ppTable = RateSwitchTable;
1414 *pTableSize = RateSwitchTable[0];
1415 *pInitTxRateIdx = RateSwitchTable[1];
1420 #ifdef CONFIG_STA_SUPPORT
1421 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1423 #ifdef DOT11_N_SUPPORT
1424 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1425 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1426 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1428 *ppTable = RateSwitchTable11N1S;
1429 *pTableSize = RateSwitchTable11N1S[0];
1430 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1433 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1434 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1435 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1436 (pAd->Antenna.field.TxPath == 2))
1438 if (pAd->LatchRfRegs.Channel <= 14)
1440 *ppTable = RateSwitchTable11N2S;
1441 *pTableSize = RateSwitchTable11N2S[0];
1442 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1446 *ppTable = RateSwitchTable11N2SForABand;
1447 *pTableSize = RateSwitchTable11N2SForABand[0];
1448 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1453 #endif // DOT11_N_SUPPORT //
1454 if ((pEntry->RateLen == 4)
1455 #ifdef DOT11_N_SUPPORT
1456 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1457 #endif // DOT11_N_SUPPORT //
1460 *ppTable = RateSwitchTable11B;
1461 *pTableSize = RateSwitchTable11B[0];
1462 *pInitTxRateIdx = RateSwitchTable11B[1];
1465 else if (pAd->LatchRfRegs.Channel <= 14)
1467 *ppTable = RateSwitchTable11BG;
1468 *pTableSize = RateSwitchTable11BG[0];
1469 *pInitTxRateIdx = RateSwitchTable11BG[1];
1474 *ppTable = RateSwitchTable11G;
1475 *pTableSize = RateSwitchTable11G[0];
1476 *pInitTxRateIdx = RateSwitchTable11G[1];
1481 #endif // CONFIG_STA_SUPPORT //
1483 #ifdef DOT11_N_SUPPORT
1484 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1485 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1486 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1487 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1489 *ppTable = RateSwitchTable11BGN1S;
1490 *pTableSize = RateSwitchTable11BGN1S[0];
1491 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1496 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1497 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1498 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1499 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1501 if (pAd->LatchRfRegs.Channel <= 14)
1503 *ppTable = RateSwitchTable11BGN2S;
1504 *pTableSize = RateSwitchTable11BGN2S[0];
1505 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1510 *ppTable = RateSwitchTable11BGN2SForABand;
1511 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1512 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1518 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1519 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1521 *ppTable = RateSwitchTable11N1S;
1522 *pTableSize = RateSwitchTable11N1S[0];
1523 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1528 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1529 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1531 if (pAd->LatchRfRegs.Channel <= 14)
1533 *ppTable = RateSwitchTable11N2S;
1534 *pTableSize = RateSwitchTable11N2S[0];
1535 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1539 *ppTable = RateSwitchTable11N2SForABand;
1540 *pTableSize = RateSwitchTable11N2SForABand[0];
1541 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1546 #endif // DOT11_N_SUPPORT //
1547 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1548 if ((pEntry->RateLen == 4)
1549 #ifdef DOT11_N_SUPPORT
1550 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1551 // && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1552 #endif // DOT11_N_SUPPORT //
1555 *ppTable = RateSwitchTable11B;
1556 *pTableSize = RateSwitchTable11B[0];
1557 *pInitTxRateIdx = RateSwitchTable11B[1];
1562 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1563 if ((pEntry->RateLen > 8)
1564 #ifdef DOT11_N_SUPPORT
1565 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1566 #endif // DOT11_N_SUPPORT //
1569 *ppTable = RateSwitchTable11BG;
1570 *pTableSize = RateSwitchTable11BG[0];
1571 *pInitTxRateIdx = RateSwitchTable11BG[1];
1576 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1577 if ((pEntry->RateLen == 8)
1578 #ifdef DOT11_N_SUPPORT
1579 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1580 #endif // DOT11_N_SUPPORT //
1583 *ppTable = RateSwitchTable11G;
1584 *pTableSize = RateSwitchTable11G[0];
1585 *pInitTxRateIdx = RateSwitchTable11G[1];
1589 #ifdef DOT11_N_SUPPORT
1590 #endif // DOT11_N_SUPPORT //
1592 #ifdef CONFIG_STA_SUPPORT
1593 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1595 #ifdef DOT11_N_SUPPORT
1596 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1597 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1598 #endif // DOT11_N_SUPPORT //
1600 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1602 *ppTable = RateSwitchTable11B;
1603 *pTableSize = RateSwitchTable11B[0];
1604 *pInitTxRateIdx = RateSwitchTable11B[1];
1606 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1608 *ppTable = RateSwitchTable11G;
1609 *pTableSize = RateSwitchTable11G[0];
1610 *pInitTxRateIdx = RateSwitchTable11G[1];
1615 *ppTable = RateSwitchTable11BG;
1616 *pTableSize = RateSwitchTable11BG[0];
1617 *pInitTxRateIdx = RateSwitchTable11BG[1];
1621 #ifdef DOT11_N_SUPPORT
1622 if (pAd->LatchRfRegs.Channel <= 14)
1624 if (pAd->CommonCfg.TxStream == 1)
1626 *ppTable = RateSwitchTable11N1S;
1627 *pTableSize = RateSwitchTable11N1S[0];
1628 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1629 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1633 *ppTable = RateSwitchTable11N2S;
1634 *pTableSize = RateSwitchTable11N2S[0];
1635 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1636 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1641 if (pAd->CommonCfg.TxStream == 1)
1643 *ppTable = RateSwitchTable11N1S;
1644 *pTableSize = RateSwitchTable11N1S[0];
1645 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1646 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1650 *ppTable = RateSwitchTable11N2SForABand;
1651 *pTableSize = RateSwitchTable11N2SForABand[0];
1652 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1653 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1656 #endif // DOT11_N_SUPPORT //
1657 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1658 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1660 #endif // CONFIG_STA_SUPPORT //
1664 #ifdef CONFIG_STA_SUPPORT
1666 ==========================================================================
1668 This routine checks if there're other APs out there capable for
1669 roaming. Caller should call this routine only when Link up in INFRA mode
1670 and channel quality is below CQI_GOOD_THRESHOLD.
1672 IRQL = DISPATCH_LEVEL
1675 ==========================================================================
1677 VOID MlmeCheckForRoaming(
1678 IN PRTMP_ADAPTER pAd,
1682 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1685 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1686 // put all roaming candidates into RoamTab, and sort in RSSI order
1687 BssTableInit(pRoamTab);
1688 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1690 pBss = &pAd->ScanTab.BssEntry[i];
1692 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1693 continue; // AP disappear
1694 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1695 continue; // RSSI too weak. forget it.
1696 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1697 continue; // skip current AP
1698 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1699 continue; // only AP with stronger RSSI is eligible for roaming
1701 // AP passing all above rules is put into roaming candidate table
1702 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1703 pRoamTab->BssNr += 1;
1706 if (pRoamTab->BssNr > 0)
1708 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1709 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1711 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1712 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1713 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1714 RT28XX_MLME_HANDLER(pAd);
1717 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1721 ==========================================================================
1723 This routine checks if there're other APs out there capable for
1724 roaming. Caller should call this routine only when link up in INFRA mode
1725 and channel quality is below CQI_GOOD_THRESHOLD.
1727 IRQL = DISPATCH_LEVEL
1730 ==========================================================================
1732 VOID MlmeCheckForFastRoaming(
1733 IN PRTMP_ADAPTER pAd,
1737 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1740 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1741 // put all roaming candidates into RoamTab, and sort in RSSI order
1742 BssTableInit(pRoamTab);
1743 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1745 pBss = &pAd->ScanTab.BssEntry[i];
1747 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1748 continue; // RSSI too weak. forget it.
1749 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1750 continue; // skip current AP
1751 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1752 continue; // skip different SSID
1753 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1754 continue; // skip AP without better RSSI
1756 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));
1757 // AP passing all above rules is put into roaming candidate table
1758 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1759 pRoamTab->BssNr += 1;
1762 if (pRoamTab->BssNr > 0)
1764 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1765 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1767 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1768 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1769 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1770 RT28XX_MLME_HANDLER(pAd);
1773 // Maybe site survey required
1776 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1778 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1779 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1780 pAd->StaCfg.ScanCnt = 2;
1781 pAd->StaCfg.LastScanTime = Now;
1786 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1790 ==========================================================================
1792 This routine calculates TxPER, RxPER of the past N-sec period. And
1793 according to the calculation result, ChannelQuality is calculated here
1794 to decide if current AP is still doing the job.
1796 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1798 StaCfg.ChannelQuality - 0..100
1800 IRQL = DISPATCH_LEVEL
1802 NOTE: This routine decide channle quality based on RX CRC error ratio.
1803 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1804 is performed right before this routine, so that this routine can decide
1805 channel quality based on the most up-to-date information
1806 ==========================================================================
1808 VOID MlmeCalculateChannelQuality(
1809 IN PRTMP_ADAPTER pAd,
1812 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1816 ULONG BeaconLostTime = BEACON_LOST_TIME;
1818 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1819 // longer beacon lost time when carrier detection enabled
1820 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1822 BeaconLostTime = BEACON_LOST_TIME + BEACON_LOST_TIME/2;
1824 #endif // CARRIER_DETECTION_SUPPORT //
1826 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1829 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1831 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1832 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1840 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1841 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1845 // calculate RX PER - don't take RxPER into consideration if too few sample
1847 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1851 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1854 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1856 if (INFRA_ON(pAd) &&
1857 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1858 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1860 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1861 pAd->Mlme.ChannelQuality = 0;
1868 else if (MaxRssi < -90)
1871 NorRssi = (MaxRssi + 90) * 2;
1873 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1874 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1875 TX_WEIGHTING * (100 - TxPRR) +
1876 RX_WEIGHTING* (100 - RxPER)) / 100;
1877 if (pAd->Mlme.ChannelQuality >= 100)
1878 pAd->Mlme.ChannelQuality = 100;
1884 IN PRTMP_ADAPTER pAd,
1885 IN PMAC_TABLE_ENTRY pEntry,
1886 IN PRTMP_TX_RATE_SWITCH pTxRate)
1888 UCHAR MaxMode = MODE_OFDM;
1890 #ifdef DOT11_N_SUPPORT
1891 MaxMode = MODE_HTGREENFIELD;
1893 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1894 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1896 #endif // DOT11_N_SUPPORT //
1897 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1899 if (pTxRate->CurrMCS < MCS_AUTO)
1900 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1902 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1903 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1907 // If peer adhoc is b-only mode, we can't send 11g rate.
1908 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1909 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1912 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1914 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1915 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1916 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1918 // Patch speed error in status page
1919 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1923 if (pTxRate->Mode <= MaxMode)
1924 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1926 #ifdef DOT11_N_SUPPORT
1927 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1928 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1930 #endif // DOT11_N_SUPPORT //
1931 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1933 #ifdef DOT11_N_SUPPORT
1934 // Reexam each bandwidth's SGI support.
1935 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1937 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1938 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1939 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1940 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1943 // Turn RTS/CTS rate to 6Mbps.
1944 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1946 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1947 if (pAd->MacTab.fAnyBASession)
1949 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1953 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1956 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1958 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1959 if (pAd->MacTab.fAnyBASession)
1961 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1965 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1968 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1970 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1973 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1975 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1977 #endif // DOT11_N_SUPPORT //
1979 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1980 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1981 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1982 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1983 #ifdef DOT11_N_SUPPORT
1984 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1985 pAd->WIFItestbed.bGreenField)
1986 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1987 #endif // DOT11_N_SUPPORT //
1990 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1994 ==========================================================================
1996 This routine calculates the acumulated TxPER of eaxh TxRate. And
1997 according to the calculation result, change CommonCfg.TxRate which
1998 is the stable TX Rate we expect the Radio situation could sustained.
2000 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
2004 IRQL = DISPATCH_LEVEL
2007 call this routine every second
2008 ==========================================================================
2010 VOID MlmeDynamicTxRateSwitching(
2011 IN PRTMP_ADAPTER pAd)
2013 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2014 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2015 ULONG TxErrorRatio = 0;
2016 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2017 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2019 UCHAR TableSize = 0;
2020 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2021 CHAR Rssi, RssiOffset = 0;
2022 TX_STA_CNT1_STRUC StaTx1;
2023 TX_STA_CNT0_STRUC TxStaCnt0;
2024 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2025 MAC_TABLE_ENTRY *pEntry;
2032 #endif // RALINK_ATE //
2035 // walk through MAC table, see if need to change AP's TX rate toward each entry
2037 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2039 pEntry = &pAd->MacTab.Content[i];
2041 // check if this entry need to switch rate automatically
2042 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2045 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2047 Rssi = RTMPMaxRssi(pAd,
2048 pAd->StaCfg.RssiSample.AvgRssi0,
2049 pAd->StaCfg.RssiSample.AvgRssi1,
2050 pAd->StaCfg.RssiSample.AvgRssi2);
2052 // Update statistic counter
2053 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2054 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2055 pAd->bUpdateBcnCntDone = TRUE;
2056 TxRetransmit = StaTx1.field.TxRetransmit;
2057 TxSuccess = StaTx1.field.TxSuccess;
2058 TxFailCount = TxStaCnt0.field.TxFailCount;
2059 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2061 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2062 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2063 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2064 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2065 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2066 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2068 // if no traffic in the past 1-sec period, don't change TX rate,
2069 // but clear all bad history. because the bad history may affect the next
2070 // Chariot throughput test
2071 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2072 pAd->RalinkCounters.OneSecTxRetryOkCount +
2073 pAd->RalinkCounters.OneSecTxFailCount;
2076 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2080 if (INFRA_ON(pAd) && (i == 1))
2081 Rssi = RTMPMaxRssi(pAd,
2082 pAd->StaCfg.RssiSample.AvgRssi0,
2083 pAd->StaCfg.RssiSample.AvgRssi1,
2084 pAd->StaCfg.RssiSample.AvgRssi2);
2086 Rssi = RTMPMaxRssi(pAd,
2087 pEntry->RssiSample.AvgRssi0,
2088 pEntry->RssiSample.AvgRssi1,
2089 pEntry->RssiSample.AvgRssi2);
2091 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2092 pEntry->OneSecTxRetryOkCount +
2093 pEntry->OneSecTxFailCount;
2096 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2099 CurrRateIdx = pEntry->CurrTxRateIndex;
2101 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2103 if (CurrRateIdx >= TableSize)
2105 CurrRateIdx = TableSize - 1;
2108 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2109 // So need to sync here.
2110 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2111 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2112 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2116 // Need to sync Real Tx rate and our record.
2117 // Then return for next DRS.
2118 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2119 pEntry->CurrTxRateIndex = InitTxRateIdx;
2120 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2122 // reset all OneSecTx counters
2123 RESET_ONE_SEC_TX_CNT(pEntry);
2127 // decide the next upgrade rate and downgrade rate, if any
2128 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2130 UpRateIdx = CurrRateIdx + 1;
2131 DownRateIdx = CurrRateIdx -1;
2133 else if (CurrRateIdx == 0)
2135 UpRateIdx = CurrRateIdx + 1;
2136 DownRateIdx = CurrRateIdx;
2138 else if (CurrRateIdx == (TableSize - 1))
2140 UpRateIdx = CurrRateIdx;
2141 DownRateIdx = CurrRateIdx - 1;
2144 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2146 #ifdef DOT11_N_SUPPORT
2147 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2149 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2150 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2153 #endif // DOT11_N_SUPPORT //
2155 TrainUp = pCurrTxRate->TrainUp;
2156 TrainDown = pCurrTxRate->TrainDown;
2159 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2162 // Keep the last time TxRateChangeAction status.
2164 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2169 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2170 // (criteria copied from RT2500 for Netopia case)
2172 if (TxTotalCnt <= 15)
2176 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2177 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2178 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2179 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2181 // check the existence and index of each needed MCS
2182 while (idx < pTable[0])
2184 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2186 if (pCurrTxRate->CurrMCS == MCS_0)
2190 else if (pCurrTxRate->CurrMCS == MCS_1)
2194 else if (pCurrTxRate->CurrMCS == MCS_2)
2198 else if (pCurrTxRate->CurrMCS == MCS_3)
2202 else if (pCurrTxRate->CurrMCS == MCS_4)
2206 else if (pCurrTxRate->CurrMCS == MCS_5)
2210 else if (pCurrTxRate->CurrMCS == MCS_6)
2214 //else if (pCurrTxRate->CurrMCS == MCS_7)
2215 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2219 else if (pCurrTxRate->CurrMCS == MCS_12)
2223 else if (pCurrTxRate->CurrMCS == MCS_13)
2227 else if (pCurrTxRate->CurrMCS == MCS_14)
2231 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800))
2235 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2239 else if (pCurrTxRate->CurrMCS == MCS_21)
2243 else if (pCurrTxRate->CurrMCS == MCS_22)
2247 else if (pCurrTxRate->CurrMCS == MCS_23)
2254 if (pAd->LatchRfRegs.Channel <= 14)
2256 if (pAd->NicConfig2.field.ExternalLNAForG)
2267 if (pAd->NicConfig2.field.ExternalLNAForA)
2276 #ifdef DOT11_N_SUPPORT
2278 if ((pTable == RateSwitchTable11BGN3S) ||
2279 (pTable == RateSwitchTable11N3S) ||
2280 (pTable == RateSwitchTable))
2281 {// N mode with 3 stream // 3*3
2282 if (MCS23 && (Rssi >= -70))
2284 else if (MCS22 && (Rssi >= -72))
2286 else if (MCS21 && (Rssi >= -76))
2288 else if (MCS20 && (Rssi >= -78))
2290 else if (MCS4 && (Rssi >= -82))
2292 else if (MCS3 && (Rssi >= -84))
2294 else if (MCS2 && (Rssi >= -86))
2296 else if (MCS1 && (Rssi >= -88))
2301 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2302 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2303 {// N mode with 2 stream
2304 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2306 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2308 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2310 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2312 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2314 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2316 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2318 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2323 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2324 {// N mode with 1 stream
2325 if (MCS7 && (Rssi > (-72+RssiOffset)))
2327 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2329 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2331 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2333 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2335 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2337 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2343 #endif // DOT11_N_SUPPORT //
2345 if (MCS7 && (Rssi > -70))
2347 else if (MCS6 && (Rssi > -74))
2349 else if (MCS5 && (Rssi > -78))
2351 else if (MCS4 && (Rssi > -82))
2353 else if (MCS4 == 0) // for B-only mode
2355 else if (MCS3 && (Rssi > -85))
2357 else if (MCS2 && (Rssi > -87))
2359 else if (MCS1 && (Rssi > -90))
2365 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2367 pEntry->CurrTxRateIndex = TxRateIdx;
2368 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2369 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2372 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2373 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2374 pEntry->fLastSecAccordingRSSI = TRUE;
2375 // reset all OneSecTx counters
2376 RESET_ONE_SEC_TX_CNT(pEntry);
2381 if (pEntry->fLastSecAccordingRSSI == TRUE)
2383 pEntry->fLastSecAccordingRSSI = FALSE;
2384 pEntry->LastSecTxRateChangeAction = 0;
2385 // reset all OneSecTx counters
2386 RESET_ONE_SEC_TX_CNT(pEntry);
2393 BOOLEAN bTrainUpDown = FALSE;
2395 pEntry->CurrTxRateStableTime ++;
2397 // downgrade TX quality if PER >= Rate-Down threshold
2398 if (TxErrorRatio >= TrainDown)
2400 bTrainUpDown = TRUE;
2401 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2403 // upgrade TX quality if PER <= Rate-Up threshold
2404 else if (TxErrorRatio <= TrainUp)
2406 bTrainUpDown = TRUE;
2407 bUpgradeQuality = TRUE;
2408 if (pEntry->TxQuality[CurrRateIdx])
2409 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2411 if (pEntry->TxRateUpPenalty)
2412 pEntry->TxRateUpPenalty --;
2413 else if (pEntry->TxQuality[UpRateIdx])
2414 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2417 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2421 // perform DRS - consider TxRate Down first, then rate up.
2422 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2424 pEntry->CurrTxRateIndex = DownRateIdx;
2426 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2428 pEntry->CurrTxRateIndex = UpRateIdx;
2433 // if rate-up happen, clear all bad history of all TX rates
2434 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2436 pEntry->CurrTxRateStableTime = 0;
2437 pEntry->TxRateUpPenalty = 0;
2438 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2439 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2440 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2443 // For TxRate fast train up
2445 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2447 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2449 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2451 bTxRateChanged = TRUE;
2453 // if rate-down happen, only clear DownRate's bad history
2454 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2456 pEntry->CurrTxRateStableTime = 0;
2457 pEntry->TxRateUpPenalty = 0; // no penalty
2458 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2459 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2460 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2463 // For TxRate fast train down
2465 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2467 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2469 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2471 bTxRateChanged = TRUE;
2475 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2476 bTxRateChanged = FALSE;
2479 pEntry->LastTxOkCount = TxSuccess;
2481 // reset all OneSecTx counters
2482 RESET_ONE_SEC_TX_CNT(pEntry);
2484 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2485 if (bTxRateChanged && pNextTxRate)
2487 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2493 ========================================================================
2494 Routine Description:
2495 Station side, Auto TxRate faster train up timer call back function.
2498 SystemSpecific1 - Not used.
2499 FunctionContext - Pointer to our Adapter context.
2500 SystemSpecific2 - Not used.
2501 SystemSpecific3 - Not used.
2506 ========================================================================
2508 VOID StaQuickResponeForRateUpExec(
2509 IN PVOID SystemSpecific1,
2510 IN PVOID FunctionContext,
2511 IN PVOID SystemSpecific2,
2512 IN PVOID SystemSpecific3)
2514 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2515 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2517 ULONG TxErrorRatio = 0;
2518 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2519 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2521 UCHAR TableSize = 0;
2522 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2523 TX_STA_CNT1_STRUC StaTx1;
2524 TX_STA_CNT0_STRUC TxStaCnt0;
2526 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2527 MAC_TABLE_ENTRY *pEntry;
2530 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2533 // walk through MAC table, see if need to change AP's TX rate toward each entry
2535 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2537 pEntry = &pAd->MacTab.Content[i];
2539 // check if this entry need to switch rate automatically
2540 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2543 if (INFRA_ON(pAd) && (i == 1))
2544 Rssi = RTMPMaxRssi(pAd,
2545 pAd->StaCfg.RssiSample.AvgRssi0,
2546 pAd->StaCfg.RssiSample.AvgRssi1,
2547 pAd->StaCfg.RssiSample.AvgRssi2);
2549 Rssi = RTMPMaxRssi(pAd,
2550 pEntry->RssiSample.AvgRssi0,
2551 pEntry->RssiSample.AvgRssi1,
2552 pEntry->RssiSample.AvgRssi2);
2554 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2556 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2558 // decide the next upgrade rate and downgrade rate, if any
2559 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2561 UpRateIdx = CurrRateIdx + 1;
2562 DownRateIdx = CurrRateIdx -1;
2564 else if (CurrRateIdx == 0)
2566 UpRateIdx = CurrRateIdx + 1;
2567 DownRateIdx = CurrRateIdx;
2569 else if (CurrRateIdx == (TableSize - 1))
2571 UpRateIdx = CurrRateIdx;
2572 DownRateIdx = CurrRateIdx - 1;
2575 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2577 #ifdef DOT11_N_SUPPORT
2578 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2580 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2581 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2584 #endif // DOT11_N_SUPPORT //
2586 TrainUp = pCurrTxRate->TrainUp;
2587 TrainDown = pCurrTxRate->TrainDown;
2590 if (pAd->MacTab.Size == 1)
2592 // Update statistic counter
2593 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2594 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2596 TxRetransmit = StaTx1.field.TxRetransmit;
2597 TxSuccess = StaTx1.field.TxSuccess;
2598 TxFailCount = TxStaCnt0.field.TxFailCount;
2599 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2601 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2602 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2603 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2604 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2605 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2606 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2609 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2613 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2614 pEntry->OneSecTxRetryOkCount +
2615 pEntry->OneSecTxFailCount;
2618 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2623 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2624 // (criteria copied from RT2500 for Netopia case)
2626 if (TxTotalCnt <= 12)
2628 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2629 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2631 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2633 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2634 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2636 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2638 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2641 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2647 ULONG OneSecTxNoRetryOKRationCount;
2649 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2654 // downgrade TX quality if PER >= Rate-Down threshold
2655 if (TxErrorRatio >= TrainDown)
2657 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2660 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2662 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2664 // perform DRS - consider TxRate Down first, then rate up.
2665 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2667 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2669 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2670 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2675 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2677 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2681 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2683 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2688 // if rate-up happen, clear all bad history of all TX rates
2689 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2691 pAd->DrsCounters.TxRateUpPenalty = 0;
2692 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2693 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2694 bTxRateChanged = TRUE;
2696 // if rate-down happen, only clear DownRate's bad history
2697 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2699 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2701 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2702 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2703 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2704 bTxRateChanged = TRUE;
2708 bTxRateChanged = FALSE;
2711 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2712 if (bTxRateChanged && pNextTxRate)
2714 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2720 ==========================================================================
2722 This routine is executed periodically inside MlmePeriodicExec() after
2723 association with an AP.
2724 It checks if StaCfg.Psm is consistent with user policy (recorded in
2725 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2726 there're some conditions to consider:
2727 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2728 the time when Mibss==TRUE
2729 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2730 if outgoing traffic available in TxRing or MgmtRing.
2732 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2734 IRQL = DISPATCH_LEVEL
2736 ==========================================================================
2738 VOID MlmeCheckPsmChange(
2739 IN PRTMP_ADAPTER pAd,
2745 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2746 // 2. user wants either MAX_PSP or FAST_PSP
2747 // 3. but current psm is not in PWR_SAVE
2748 // 4. CNTL state machine is not doing SCANning
2749 // 5. no TX SUCCESS event for the past 1-sec period
2750 #ifdef NDIS51_MINIPORT
2751 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2752 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2755 PowerMode = pAd->StaCfg.WindowsPowerMode;
2757 if (INFRA_ON(pAd) &&
2758 (PowerMode != Ndis802_11PowerModeCAM) &&
2759 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2760 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2761 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2762 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2763 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2765 // add by johnli, use Rx OK data count per second to calculate throughput
2766 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2767 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2768 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2770 (pAd->StaCfg.HTPhyMode.field.MODE <= MODE_OFDM) &&
2772 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2773 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2775 (pAd->StaCfg.HTPhyMode.field.MODE > MODE_OFDM) &&
2777 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2780 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2781 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2782 MlmeSetPsmBit(pAd, PWR_SAVE);
2783 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2785 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2789 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2795 // IRQL = PASSIVE_LEVEL
2796 // IRQL = DISPATCH_LEVEL
2798 IN PRTMP_ADAPTER pAd,
2801 AUTO_RSP_CFG_STRUC csr4;
2803 pAd->StaCfg.Psm = psm;
2804 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2805 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2806 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2808 #endif // CONFIG_STA_SUPPORT //
2811 // IRQL = DISPATCH_LEVEL
2812 VOID MlmeSetTxPreamble(
2813 IN PRTMP_ADAPTER pAd,
2814 IN USHORT TxPreamble)
2816 AUTO_RSP_CFG_STRUC csr4;
2819 // Always use Long preamble before verifiation short preamble functionality works well.
2820 // Todo: remove the following line if short preamble functionality works
2822 //TxPreamble = Rt802_11PreambleLong;
2824 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2825 if (TxPreamble == Rt802_11PreambleLong)
2827 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2828 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2829 csr4.field.AutoResponderPreamble = 0;
2833 // NOTE: 1Mbps should always use long preamble
2834 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2835 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2836 csr4.field.AutoResponderPreamble = 1;
2839 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2843 ==========================================================================
2845 Update basic rate bitmap
2846 ==========================================================================
2849 VOID UpdateBasicRateBitmap(
2850 IN PRTMP_ADAPTER pAdapter)
2853 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2854 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2855 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2856 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2857 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2860 /* if A mode, always use fix BasicRateBitMap */
2861 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2862 if (pAdapter->CommonCfg.Channel > 14)
2863 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2866 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2868 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2872 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2878 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2880 if (bitmap & (1 << i))
2882 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2884 if (sup_p[j] == rate[i])
2889 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2891 if (ext_p[j] == rate[i])
2897 } /* End of UpdateBasicRateBitmap */
2899 // IRQL = PASSIVE_LEVEL
2900 // IRQL = DISPATCH_LEVEL
2901 // bLinkUp is to identify the inital link speed.
2902 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2903 VOID MlmeUpdateTxRates(
2904 IN PRTMP_ADAPTER pAd,
2909 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2910 UCHAR MinSupport = RATE_54;
2911 ULONG BasicRateBitmap = 0;
2912 UCHAR CurrBasicRate = RATE_1;
2913 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2914 PHTTRANSMIT_SETTING pHtPhy = NULL;
2915 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2916 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2917 BOOLEAN *auto_rate_cur_p;
2918 UCHAR HtMcs = MCS_AUTO;
2920 // find max desired rate
2921 UpdateBasicRateBitmap(pAd);
2924 auto_rate_cur_p = NULL;
2925 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2927 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2929 case 2: Rate = RATE_1; num++; break;
2930 case 4: Rate = RATE_2; num++; break;
2931 case 11: Rate = RATE_5_5; num++; break;
2932 case 22: Rate = RATE_11; num++; break;
2933 case 12: Rate = RATE_6; num++; break;
2934 case 18: Rate = RATE_9; num++; break;
2935 case 24: Rate = RATE_12; num++; break;
2936 case 36: Rate = RATE_18; num++; break;
2937 case 48: Rate = RATE_24; num++; break;
2938 case 72: Rate = RATE_36; num++; break;
2939 case 96: Rate = RATE_48; num++; break;
2940 case 108: Rate = RATE_54; num++; break;
2941 //default: Rate = RATE_1; break;
2943 if (MaxDesire < Rate) MaxDesire = Rate;
2946 //===========================================================================
2947 //===========================================================================
2949 #ifdef CONFIG_STA_SUPPORT
2950 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2952 pHtPhy = &pAd->StaCfg.HTPhyMode;
2953 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2954 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2956 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2957 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2959 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2960 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2961 (MaxDesire > RATE_11))
2963 MaxDesire = RATE_11;
2966 #endif // CONFIG_STA_SUPPORT //
2968 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2969 pMinHtPhy->word = 0;
2970 pMaxHtPhy->word = 0;
2973 // Auto rate switching is enabled only if more than one DESIRED RATES are
2974 // specified; otherwise disabled
2977 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2978 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2979 *auto_rate_cur_p = FALSE;
2983 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2984 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2985 *auto_rate_cur_p = TRUE;
2989 if (HtMcs != MCS_AUTO)
2991 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2992 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2993 *auto_rate_cur_p = FALSE;
2997 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2998 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2999 *auto_rate_cur_p = TRUE;
3003 #ifdef CONFIG_STA_SUPPORT
3004 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3006 pSupRate = &pAd->StaActive.SupRate[0];
3007 pExtRate = &pAd->StaActive.ExtRate[0];
3008 SupRateLen = pAd->StaActive.SupRateLen;
3009 ExtRateLen = pAd->StaActive.ExtRateLen;
3012 #endif // CONFIG_STA_SUPPORT //
3014 pSupRate = &pAd->CommonCfg.SupRate[0];
3015 pExtRate = &pAd->CommonCfg.ExtRate[0];
3016 SupRateLen = pAd->CommonCfg.SupRateLen;
3017 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3020 // find max supported rate
3021 for (i=0; i<SupRateLen; i++)
3023 switch (pSupRate[i] & 0x7f)
3025 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3026 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3027 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3028 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3029 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3030 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3031 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3032 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3033 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3034 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3035 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3036 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3037 default: Rate = RATE_1; break;
3039 if (MaxSupport < Rate) MaxSupport = Rate;
3041 if (MinSupport > Rate) MinSupport = Rate;
3044 for (i=0; i<ExtRateLen; i++)
3046 switch (pExtRate[i] & 0x7f)
3048 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3049 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3050 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3051 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3052 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3053 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3054 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3055 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3056 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3057 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3058 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3059 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3060 default: Rate = RATE_1; break;
3062 if (MaxSupport < Rate) MaxSupport = Rate;
3064 if (MinSupport > Rate) MinSupport = Rate;
3067 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3069 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3070 // the DURATION field of outgoing uniicast DATA/MGMT frame
3071 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3073 if (BasicRateBitmap & (0x01 << i))
3074 CurrBasicRate = (UCHAR)i;
3075 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3078 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3079 // max tx rate = min {max desire rate, max supported rate}
3080 if (MaxSupport < MaxDesire)
3081 pAd->CommonCfg.MaxTxRate = MaxSupport;
3083 pAd->CommonCfg.MaxTxRate = MaxDesire;
3085 pAd->CommonCfg.MinTxRate = MinSupport;
3086 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
3087 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
3089 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
3090 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
3091 // 3. -75 > RSSI, start at 11 Mbps (long distance)
3092 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
3093 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
3094 if (*auto_rate_cur_p)
3097 #ifdef CONFIG_STA_SUPPORT
3098 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3099 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3100 #endif // CONFIG_STA_SUPPORT //
3101 if (bLinkUp == TRUE)
3102 pAd->CommonCfg.TxRate = RATE_24;
3104 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3107 pAd->CommonCfg.TxRate = RATE_11;
3109 pAd->CommonCfg.TxRate = RATE_24;
3111 // should never exceed MaxTxRate (consider 11B-only mode)
3112 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3113 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3115 pAd->CommonCfg.TxRateIndex = 0;
3119 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3120 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3121 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3123 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3124 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3125 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3126 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3129 if (pAd->CommonCfg.TxRate <= RATE_11)
3131 pMaxHtPhy->field.MODE = MODE_CCK;
3132 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3133 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3137 pMaxHtPhy->field.MODE = MODE_OFDM;
3138 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3139 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3140 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3142 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3145 pHtPhy->word = (pMaxHtPhy->word);
3146 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3148 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3149 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3150 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3154 switch (pAd->CommonCfg.PhyMode)
3156 case PHY_11BG_MIXED:
3158 #ifdef DOT11_N_SUPPORT
3159 case PHY_11BGN_MIXED:
3160 #endif // DOT11_N_SUPPORT //
3161 pAd->CommonCfg.MlmeRate = RATE_1;
3162 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3163 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3166 pAd->CommonCfg.RtsRate = RATE_11;
3168 // pAd->CommonCfg.RtsRate = RATE_1;
3173 #ifdef DOT11_N_SUPPORT
3174 case PHY_11AGN_MIXED:
3175 case PHY_11GN_MIXED:
3177 case PHY_11AN_MIXED:
3179 #endif // DOT11_N_SUPPORT //
3180 pAd->CommonCfg.MlmeRate = RATE_6;
3181 pAd->CommonCfg.RtsRate = RATE_6;
3182 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3183 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3185 case PHY_11ABG_MIXED:
3186 #ifdef DOT11_N_SUPPORT
3187 case PHY_11ABGN_MIXED:
3188 #endif // DOT11_N_SUPPORT //
3189 if (pAd->CommonCfg.Channel <= 14)
3191 pAd->CommonCfg.MlmeRate = RATE_1;
3192 pAd->CommonCfg.RtsRate = RATE_1;
3193 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3194 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3198 pAd->CommonCfg.MlmeRate = RATE_6;
3199 pAd->CommonCfg.RtsRate = RATE_6;
3200 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3201 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3205 pAd->CommonCfg.MlmeRate = RATE_6;
3206 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3207 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3208 pAd->CommonCfg.RtsRate = RATE_1;
3212 // Keep Basic Mlme Rate.
3214 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3215 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3216 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3218 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3219 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3222 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3223 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3224 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3225 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3226 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3227 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3228 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 ));
3231 #ifdef DOT11_N_SUPPORT
3233 ==========================================================================
3235 This function update HT Rate setting.
3236 Input Wcid value is valid for 2 case :
3237 1. it's used for Station in infra mode that copy AP rate to Mactable.
3238 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3240 IRQL = DISPATCH_LEVEL
3242 ==========================================================================
3244 VOID MlmeUpdateHtTxRates(
3245 IN PRTMP_ADAPTER pAd,
3248 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3250 RT_HT_CAPABILITY *pRtHtCap = NULL;
3251 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3254 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3255 PHTTRANSMIT_SETTING pHtPhy = NULL;
3256 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3257 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3258 BOOLEAN *auto_rate_cur_p;
3260 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3262 auto_rate_cur_p = NULL;
3264 #ifdef CONFIG_STA_SUPPORT
3265 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3267 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3268 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3269 pHtPhy = &pAd->StaCfg.HTPhyMode;
3270 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3271 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3273 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3275 #endif // CONFIG_STA_SUPPORT //
3277 #ifdef CONFIG_STA_SUPPORT
3278 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3280 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3283 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3284 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3285 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3286 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3287 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3288 pMaxHtPhy->field.STBC = STBC_USE;
3290 pMaxHtPhy->field.STBC = STBC_NONE;
3293 #endif // CONFIG_STA_SUPPORT //
3295 if (pDesireHtPhy->bHtEnable == FALSE)
3298 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3299 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3300 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3301 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3302 pMaxHtPhy->field.STBC = STBC_USE;
3304 pMaxHtPhy->field.STBC = STBC_NONE;
3307 // Decide MAX ht rate.
3308 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3309 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3311 pMaxHtPhy->field.MODE = MODE_HTMIX;
3313 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3314 pMaxHtPhy->field.BW = BW_40;
3316 pMaxHtPhy->field.BW = BW_20;
3318 if (pMaxHtPhy->field.BW == BW_20)
3319 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3321 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3323 for (i=23; i>=0; i--) // 3*3
3326 bitmask = (1<<(i-(j*8)));
3328 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3330 pMaxHtPhy->field.MCS = i;
3338 // Copy MIN ht rate. rt2860???
3339 pMinHtPhy->field.BW = BW_20;
3340 pMinHtPhy->field.MCS = 0;
3341 pMinHtPhy->field.STBC = 0;
3342 pMinHtPhy->field.ShortGI = 0;
3343 //If STA assigns fixed rate. update to fixed here.
3344 #ifdef CONFIG_STA_SUPPORT
3345 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3347 if (pDesireHtPhy->MCSSet[4] != 0)
3349 pMaxHtPhy->field.MCS = 32;
3350 pMinHtPhy->field.MCS = 32;
3351 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3354 for (i=23; (CHAR)i >= 0; i--) // 3*3
3357 bitmask = (1<<(i-(j*8)));
3358 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3360 pMaxHtPhy->field.MCS = i;
3361 pMinHtPhy->field.MCS = i;
3368 #endif // CONFIG_STA_SUPPORT //
3372 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3373 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3374 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3375 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3376 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3378 // use default now. rt2860
3379 if (pDesireHtPhy->MCSSet[0] != 0xff)
3380 *auto_rate_cur_p = FALSE;
3382 *auto_rate_cur_p = TRUE;
3384 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3385 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3386 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3387 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3389 #endif // DOT11_N_SUPPORT //
3391 // IRQL = DISPATCH_LEVEL
3393 IN PRTMP_ADAPTER pAd)
3395 RT28XX_MLME_RADIO_OFF(pAd);
3398 // IRQL = DISPATCH_LEVEL
3400 IN PRTMP_ADAPTER pAd)
3402 RT28XX_MLME_RADIO_ON(pAd);
3405 // ===========================================================================================
3407 // ===========================================================================================
3410 /*! \brief initialize BSS table
3411 * \param p_tab pointer to the table
3416 IRQL = PASSIVE_LEVEL
3417 IRQL = DISPATCH_LEVEL
3426 Tab->BssOverlapNr = 0;
3427 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3429 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3430 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3434 #ifdef DOT11_N_SUPPORT
3436 IN PRTMP_ADAPTER pAd,
3441 Tab->numAsOriginator = 0;
3442 Tab->numAsRecipient = 0;
3443 NdisAllocateSpinLock(&pAd->BATabLock);
3444 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3446 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3447 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3449 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3451 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3454 #endif // DOT11_N_SUPPORT //
3456 /*! \brief search the BSS table by SSID
3457 * \param p_tab pointer to the bss table
3458 * \param ssid SSID string
3459 * \return index of the table, BSS_NOT_FOUND if not in the table
3462 * \note search by sequential search
3464 IRQL = DISPATCH_LEVEL
3467 ULONG BssTableSearch(
3474 for (i = 0; i < Tab->BssNr; i++)
3477 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3478 // We should distinguish this case.
3480 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3481 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3482 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3487 return (ULONG)BSS_NOT_FOUND;
3490 ULONG BssSsidTableSearch(
3499 for (i = 0; i < Tab->BssNr; i++)
3502 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3503 // We should distinguish this case.
3505 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3506 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3507 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3508 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3513 return (ULONG)BSS_NOT_FOUND;
3516 ULONG BssTableSearchWithSSID(
3525 for (i = 0; i < Tab->BssNr; i++)
3527 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3528 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3529 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3530 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3531 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3532 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3537 return (ULONG)BSS_NOT_FOUND;
3540 // IRQL = DISPATCH_LEVEL
3541 VOID BssTableDeleteEntry(
3542 IN OUT BSS_TABLE *Tab,
3548 for (i = 0; i < Tab->BssNr; i++)
3550 if ((Tab->BssEntry[i].Channel == Channel) &&
3551 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3553 for (j = i; j < Tab->BssNr - 1; j++)
3555 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3557 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3564 #ifdef DOT11_N_SUPPORT
3566 ========================================================================
3567 Routine Description:
3568 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3571 // IRQL = DISPATCH_LEVEL
3572 ========================================================================
3574 VOID BATableDeleteORIEntry(
3575 IN OUT PRTMP_ADAPTER pAd,
3576 IN BA_ORI_ENTRY *pBAORIEntry)
3579 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3581 NdisAcquireSpinLock(&pAd->BATabLock);
3582 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3584 pAd->BATable.numAsOriginator -= 1;
3585 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3586 // Erase Bitmap flag.
3588 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3589 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3590 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3591 pBAORIEntry->Token = 1;
3592 // Not clear Sequence here.
3593 NdisReleaseSpinLock(&pAd->BATabLock);
3596 #endif // DOT11_N_SUPPORT //
3604 IRQL = DISPATCH_LEVEL
3608 IN PRTMP_ADAPTER pAd,
3609 OUT BSS_ENTRY *pBss,
3614 IN USHORT BeaconPeriod,
3615 IN PCF_PARM pCfParm,
3617 IN USHORT CapabilityInfo,
3619 IN UCHAR SupRateLen,
3621 IN UCHAR ExtRateLen,
3622 IN HT_CAPABILITY_IE *pHtCapability,
3623 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3624 IN UCHAR HtCapabilityLen,
3625 IN UCHAR AddHtInfoLen,
3626 IN UCHAR NewExtChanOffset,
3629 IN LARGE_INTEGER TimeStamp,
3631 IN PEDCA_PARM pEdcaParm,
3632 IN PQOS_CAPABILITY_PARM pQosCapability,
3633 IN PQBSS_LOAD_PARM pQbssLoad,
3634 IN USHORT LengthVIE,
3635 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3637 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3638 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3642 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3643 // Or send beacon /probe response with SSID len matching real SSID length,
3644 // but SSID is all zero. such as "00-00-00-00" with length 4.
3645 // We have to prevent this case overwrite correct table
3646 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3648 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3649 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3650 pBss->SsidLen = SsidLen;
3656 pBss->BssType = BssType;
3657 pBss->BeaconPeriod = BeaconPeriod;
3658 if (BssType == BSS_INFRA)
3660 if (pCfParm->bValid)
3662 pBss->CfpCount = pCfParm->CfpCount;
3663 pBss->CfpPeriod = pCfParm->CfpPeriod;
3664 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3665 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3670 pBss->AtimWin = AtimWin;
3673 pBss->CapabilityInfo = CapabilityInfo;
3674 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3675 // Combine with AuthMode, they will decide the connection methods.
3676 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3677 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3678 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3679 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3681 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3682 pBss->SupRateLen = SupRateLen;
3683 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3684 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3685 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3686 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3687 pBss->NewExtChanOffset = NewExtChanOffset;
3688 pBss->ExtRateLen = ExtRateLen;
3689 pBss->Channel = Channel;
3690 pBss->CentralChannel = Channel;
3692 // Update CkipFlag. if not exists, the value is 0x0
3693 pBss->CkipFlag = CkipFlag;
3695 // New for microsoft Fixed IEs
3696 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3697 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3698 pBss->FixIEs.Capabilities = CapabilityInfo;
3700 // New for microsoft Variable IEs
3703 pBss->VarIELen = LengthVIE;
3704 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3711 pBss->AddHtInfoLen = 0;
3712 pBss->HtCapabilityLen = 0;
3713 #ifdef DOT11_N_SUPPORT
3714 if (HtCapabilityLen> 0)
3716 pBss->HtCapabilityLen = HtCapabilityLen;
3717 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3718 if (AddHtInfoLen > 0)
3720 pBss->AddHtInfoLen = AddHtInfoLen;
3721 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3723 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3725 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3727 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3729 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3733 #endif // DOT11_N_SUPPORT //
3735 BssCipherParse(pBss);
3739 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3741 pBss->EdcaParm.bValid = FALSE;
3743 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3745 pBss->QosCapability.bValid = FALSE;
3747 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3749 pBss->QbssLoad.bValid = FALSE;
3751 #ifdef CONFIG_STA_SUPPORT
3752 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3758 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3759 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3760 #ifdef EXT_BUILD_CHANNEL_LIST
3761 NdisZeroMemory(&pBss->CountryString[0], 3);
3762 pBss->bHasCountryIE = FALSE;
3763 #endif // EXT_BUILD_CHANNEL_LIST //
3764 pEid = (PEID_STRUCT) pVIE;
3765 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3770 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3772 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3774 pBss->WpaIE.IELen = 0;
3777 pBss->WpaIE.IELen = pEid->Len + 2;
3778 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3782 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3784 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3786 pBss->RsnIE.IELen = 0;
3789 pBss->RsnIE.IELen = pEid->Len + 2;
3790 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3793 #ifdef EXT_BUILD_CHANNEL_LIST
3795 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3796 pBss->bHasCountryIE = TRUE;
3798 #endif // EXT_BUILD_CHANNEL_LIST //
3800 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3801 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3804 #endif // CONFIG_STA_SUPPORT //
3808 * \brief insert an entry into the bss table
3809 * \param p_tab The BSS table
3810 * \param Bssid BSSID
3812 * \param ssid_len Length of SSID
3814 * \param beacon_period
3821 * \param channel_idx
3825 * \note If SSID is identical, the old entry will be replaced by the new one
3827 IRQL = DISPATCH_LEVEL
3830 ULONG BssTableSetEntry(
3831 IN PRTMP_ADAPTER pAd,
3837 IN USHORT BeaconPeriod,
3840 IN USHORT CapabilityInfo,
3842 IN UCHAR SupRateLen,
3844 IN UCHAR ExtRateLen,
3845 IN HT_CAPABILITY_IE *pHtCapability,
3846 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3847 IN UCHAR HtCapabilityLen,
3848 IN UCHAR AddHtInfoLen,
3849 IN UCHAR NewExtChanOffset,
3852 IN LARGE_INTEGER TimeStamp,
3854 IN PEDCA_PARM pEdcaParm,
3855 IN PQOS_CAPABILITY_PARM pQosCapability,
3856 IN PQBSS_LOAD_PARM pQbssLoad,
3857 IN USHORT LengthVIE,
3858 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3862 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3863 if (Idx == BSS_NOT_FOUND)
3865 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3868 // It may happen when BSS Table was full.
3869 // The desired AP will not be added into BSS Table
3870 // In this case, if we found the desired AP then overwrite BSS Table.
3872 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3874 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3875 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3877 Idx = Tab->BssOverlapNr;
3878 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3879 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3880 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3881 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3887 return BSS_NOT_FOUND;
3891 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3892 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3893 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3898 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3899 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3900 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3902 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3903 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3904 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3911 #ifdef CONFIG_STA_SUPPORT
3912 #ifdef DOT11_N_SUPPORT
3913 #ifdef DOT11N_DRAFT3
3915 IN PRTMP_ADAPTER pAd)
3919 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3920 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3922 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3923 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3926 ULONG TriEventTableSetEntry(
3927 IN PRTMP_ADAPTER pAd,
3928 OUT TRIGGER_EVENT_TAB *Tab,
3930 IN HT_CAPABILITY_IE *pHtCapability,
3931 IN UCHAR HtCapabilityLen,
3936 if (HtCapabilityLen == 0)
3938 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3940 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3941 Tab->EventA[Tab->EventANo].bValid = TRUE;
3942 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3943 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3946 // Beacon has Regulatory class IE. So use beacon's
3947 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3951 // Use Station's Regulatory class instead.
3952 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3954 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3956 Tab->EventA[Tab->EventANo].RegClass = 32;
3958 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3959 Tab->EventA[Tab->EventANo].RegClass = 33;
3962 Tab->EventA[Tab->EventANo].RegClass = ??;
3969 else if (pHtCapability->HtCapInfo.Intolerant40)
3971 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3977 ========================================================================
3978 Routine Description:
3979 Trigger Event table Maintainence called once every second.
3982 // IRQL = DISPATCH_LEVEL
3983 ========================================================================
3985 VOID TriEventCounterMaintenance(
3986 IN PRTMP_ADAPTER pAd)
3989 BOOLEAN bNotify = FALSE;
3990 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3992 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3994 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3995 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3997 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3998 pAd->CommonCfg.TriggerEventTab.EventANo --;
3999 // Need to send 20/40 Coexistence Notify frame if has status change.
4004 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
4006 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
4007 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
4011 if (bNotify == TRUE)
4012 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
4014 #endif // DOT11N_DRAFT3 //
4015 #endif // DOT11_N_SUPPORT //
4017 // IRQL = DISPATCH_LEVEL
4018 VOID BssTableSsidSort(
4019 IN PRTMP_ADAPTER pAd,
4020 OUT BSS_TABLE *OutTab,
4025 BssTableInit(OutTab);
4027 for (i = 0; i < pAd->ScanTab.BssNr; i++)
4029 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
4030 BOOLEAN bIsHiddenApIncluded = FALSE;
4032 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
4033 (pAd->MlmeAux.Channel > 14) &&
4034 RadarChannelCheck(pAd, pInBss->Channel))
4035 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
4036 || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
4037 #endif // CARRIER_DETECTION_SUPPORT //
4041 bIsHiddenApIncluded = TRUE;
4044 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
4045 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
4047 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4050 #ifdef EXT_BUILD_CHANNEL_LIST
4051 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
4052 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
4053 (pInBss->bHasCountryIE == FALSE))
4055 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
4058 #endif // EXT_BUILD_CHANNEL_LIST //
4060 #ifdef DOT11_N_SUPPORT
4061 // 2.4G/5G N only mode
4062 if ((pInBss->HtCapabilityLen == 0) &&
4063 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4065 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4068 #endif // DOT11_N_SUPPORT //
4071 // Check the Authmode first
4072 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4074 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4075 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4079 // Check cipher suite, AP must have more secured cipher than station setting
4080 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4082 // If it's not mixed mode, we should only let BSS pass with the same encryption
4083 if (pInBss->WPA.bMixMode == FALSE)
4084 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4087 // check group cipher
4088 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4091 // check pairwise cipher, skip if none matched
4092 // If profile set to AES, let it pass without question.
4093 // If profile set to TKIP, we must find one mateched
4094 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4095 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4096 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4099 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4101 // If it's not mixed mode, we should only let BSS pass with the same encryption
4102 if (pInBss->WPA2.bMixMode == FALSE)
4103 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4106 // check group cipher
4107 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4110 // check pairwise cipher, skip if none matched
4111 // If profile set to AES, let it pass without question.
4112 // If profile set to TKIP, we must find one mateched
4113 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4114 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4115 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4119 // Bss Type matched, SSID matched.
4120 // We will check wepstatus for qualification Bss
4121 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4123 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4125 // For the SESv2 case, we will not qualify WepStatus.
4131 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4132 // It definitely will fail. So, skip it.
4133 // CCX also require not even try to connect it!!
4137 #ifdef DOT11_N_SUPPORT
4138 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4139 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4140 if ((pInBss->CentralChannel != pInBss->Channel) &&
4141 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4143 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4145 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4147 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4151 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4157 #endif // DOT11_N_SUPPORT //
4159 // copy matching BSS from InTab to OutTab
4160 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4164 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4166 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4169 #ifdef DOT11_N_SUPPORT
4170 // 2.4G/5G N only mode
4171 if ((pInBss->HtCapabilityLen == 0) &&
4172 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4174 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4177 #endif // DOT11_N_SUPPORT //
4180 // Check the Authmode first
4181 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4183 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4184 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4188 // Check cipher suite, AP must have more secured cipher than station setting
4189 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4191 // If it's not mixed mode, we should only let BSS pass with the same encryption
4192 if (pInBss->WPA.bMixMode == FALSE)
4193 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4196 // check group cipher
4197 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4200 // check pairwise cipher, skip if none matched
4201 // If profile set to AES, let it pass without question.
4202 // If profile set to TKIP, we must find one mateched
4203 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4204 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4205 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4208 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4210 // If it's not mixed mode, we should only let BSS pass with the same encryption
4211 if (pInBss->WPA2.bMixMode == FALSE)
4212 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4215 // check group cipher
4216 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4219 // check pairwise cipher, skip if none matched
4220 // If profile set to AES, let it pass without question.
4221 // If profile set to TKIP, we must find one mateched
4222 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4223 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4224 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4228 // Bss Type matched, SSID matched.
4229 // We will check wepstatus for qualification Bss
4230 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4233 #ifdef DOT11_N_SUPPORT
4234 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4235 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4236 if ((pInBss->CentralChannel != pInBss->Channel) &&
4237 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4239 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4241 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4243 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4246 #endif // DOT11_N_SUPPORT //
4248 // copy matching BSS from InTab to OutTab
4249 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4254 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4258 BssTableSortByRssi(OutTab);
4262 // IRQL = DISPATCH_LEVEL
4263 VOID BssTableSortByRssi(
4264 IN OUT BSS_TABLE *OutTab)
4269 for (i = 0; i < OutTab->BssNr - 1; i++)
4271 for (j = i+1; j < OutTab->BssNr; j++)
4273 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4275 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4276 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4277 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4282 #endif // CONFIG_STA_SUPPORT //
4285 VOID BssCipherParse(
4286 IN OUT PBSS_ENTRY pBss)
4290 PRSN_IE_HEADER_STRUCT pRsnHeader;
4291 PCIPHER_SUITE_STRUCT pCipher;
4292 PAKM_SUITE_STRUCT pAKM;
4295 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4298 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4302 pBss->WepStatus = Ndis802_11WEPEnabled;
4306 pBss->WepStatus = Ndis802_11WEPDisabled;
4308 // Set default to disable & open authentication before parsing variable IE
4309 pBss->AuthMode = Ndis802_11AuthModeOpen;
4310 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4313 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4314 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4315 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4316 pBss->WPA.RsnCapability = 0;
4317 pBss->WPA.bMixMode = FALSE;
4319 // Init WPA2 setting
4320 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4321 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4322 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4323 pBss->WPA2.RsnCapability = 0;
4324 pBss->WPA2.bMixMode = FALSE;
4327 Length = (INT) pBss->VarIELen;
4331 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4332 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4333 pEid = (PEID_STRUCT) pTmp;
4337 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4338 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4344 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4345 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4346 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4347 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4350 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4351 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4352 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4355 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4356 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4357 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4363 // if Cisco IE_WPA, break
4366 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4371 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4373 // if unsupported vendor specific IE
4376 // Skip OUI, version, and multicast suite
4377 // This part should be improved in the future when AP supported multiple cipher suite.
4378 // For now, it's OK since almost all APs have fixed cipher suite supported.
4379 // pTmp = (PUCHAR) pEid->Octet;
4382 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4390 // Parse group cipher
4394 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4395 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4398 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4401 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4406 // number of unicast suite
4409 // skip all unicast cipher suites
4410 //Count = *(PUSHORT) pTmp;
4411 Count = (pTmp[1]<<8) + pTmp[0];
4412 pTmp += sizeof(USHORT);
4414 // Parsing all unicast cipher suite
4419 TmpCipher = Ndis802_11WEPDisabled;
4423 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4424 TmpCipher = Ndis802_11Encryption1Enabled;
4427 TmpCipher = Ndis802_11Encryption2Enabled;
4430 TmpCipher = Ndis802_11Encryption3Enabled;
4435 if (TmpCipher > pBss->WPA.PairCipher)
4437 // Move the lower cipher suite to PairCipherAux
4438 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4439 pBss->WPA.PairCipher = TmpCipher;
4443 pBss->WPA.PairCipherAux = TmpCipher;
4449 // 4. get AKM suite counts
4450 //Count = *(PUSHORT) pTmp;
4451 Count = (pTmp[1]<<8) + pTmp[0];
4452 pTmp += sizeof(USHORT);
4458 // Set AP support WPA mode
4459 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4460 pBss->AuthMode = Ndis802_11AuthModeWPA;
4462 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4465 // Set AP support WPA mode
4466 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4467 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4469 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4476 // Fixed for WPA-None
4477 if (pBss->BssType == BSS_ADHOC)
4479 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4480 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4481 pBss->WepStatus = pBss->WPA.GroupCipher;
4482 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4483 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4486 pBss->WepStatus = pBss->WPA.PairCipher;
4488 // Check the Pair & Group, if different, turn on mixed mode flag
4489 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4490 pBss->WPA.bMixMode = TRUE;
4495 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4497 // 0. Version must be 1
4498 if (le2cpu16(pRsnHeader->Version) != 1)
4500 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4502 // 1. Check group cipher
4503 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4504 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4507 // Parse group cipher
4508 switch (pCipher->Type)
4511 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4512 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4515 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4518 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4523 // set to correct offset for next parsing
4524 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4526 // 2. Get pairwise cipher counts
4527 //Count = *(PUSHORT) pTmp;
4528 Count = (pTmp[1]<<8) + pTmp[0];
4529 pTmp += sizeof(USHORT);
4531 // 3. Get pairwise cipher
4532 // Parsing all unicast cipher suite
4536 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4537 TmpCipher = Ndis802_11WEPDisabled;
4538 switch (pCipher->Type)
4541 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4542 TmpCipher = Ndis802_11Encryption1Enabled;
4545 TmpCipher = Ndis802_11Encryption2Enabled;
4548 TmpCipher = Ndis802_11Encryption3Enabled;
4553 if (TmpCipher > pBss->WPA2.PairCipher)
4555 // Move the lower cipher suite to PairCipherAux
4556 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4557 pBss->WPA2.PairCipher = TmpCipher;
4561 pBss->WPA2.PairCipherAux = TmpCipher;
4563 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4567 // 4. get AKM suite counts
4568 //Count = *(PUSHORT) pTmp;
4569 Count = (pTmp[1]<<8) + pTmp[0];
4570 pTmp += sizeof(USHORT);
4572 // 5. Get AKM ciphers
4573 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4574 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4580 // Set AP support WPA mode
4581 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4582 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4584 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4587 // Set AP support WPA mode
4588 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4589 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4591 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4596 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4598 // Fixed for WPA-None
4599 if (pBss->BssType == BSS_ADHOC)
4601 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4602 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4603 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4604 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4605 pBss->WepStatus = pBss->WPA.GroupCipher;
4606 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4607 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4609 pBss->WepStatus = pBss->WPA2.PairCipher;
4611 // 6. Get RSN capability
4612 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4613 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4614 pTmp += sizeof(USHORT);
4616 // Check the Pair & Group, if different, turn on mixed mode flag
4617 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4618 pBss->WPA2.bMixMode = TRUE;
4624 Length -= (pEid->Len + 2);
4628 // ===========================================================================================
4630 // ===========================================================================================
4632 /*! \brief generates a random mac address value for IBSS BSSID
4633 * \param Addr the bssid location
4638 VOID MacAddrRandomBssid(
4639 IN PRTMP_ADAPTER pAd,
4644 for (i = 0; i < MAC_ADDR_LEN; i++)
4646 pAddr[i] = RandomByte(pAd);
4649 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4652 /*! \brief init the management mac frame header
4653 * \param p_hdr mac header
4654 * \param subtype subtype of the frame
4655 * \param p_ds destination address, don't care if it is a broadcast address
4657 * \pre the station has the following information in the pAd->StaCfg
4661 * \note this function initializes the following field
4663 IRQL = PASSIVE_LEVEL
4664 IRQL = DISPATCH_LEVEL
4667 VOID MgtMacHeaderInit(
4668 IN PRTMP_ADAPTER pAd,
4669 IN OUT PHEADER_802_11 pHdr80211,
4675 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4677 pHdr80211->FC.Type = BTYPE_MGMT;
4678 pHdr80211->FC.SubType = SubType;
4679 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4680 // pHdr80211->FC.Type = BTYPE_CNTL;
4681 pHdr80211->FC.ToDs = ToDs;
4682 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4683 #ifdef CONFIG_STA_SUPPORT
4684 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4685 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4686 #endif // CONFIG_STA_SUPPORT //
4687 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4690 // ===========================================================================================
4692 // ===========================================================================================
4694 /*!***************************************************************************
4695 * This routine build an outgoing frame, and fill all information specified
4696 * in argument list to the frame body. The actual frame size is the summation
4699 * Buffer - pointer to a pre-allocated memory segment
4700 * args - a list of <int arg_size, arg> pairs.
4701 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4702 * function will FAIL!!!
4704 * Size of the buffer
4706 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4708 IRQL = PASSIVE_LEVEL
4709 IRQL = DISPATCH_LEVEL
4711 ****************************************************************************/
4712 ULONG MakeOutgoingFrame(
4714 OUT ULONG *FrameLen, ...)
4721 // calculates the total length
4723 va_start(Args, FrameLen);
4726 leng = va_arg(Args, int);
4727 if (leng == END_OF_ARGS)
4731 p = va_arg(Args, PVOID);
4732 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4733 TotLeng = TotLeng + leng;
4736 va_end(Args); /* clean up */
4737 *FrameLen = TotLeng;
4741 // ===========================================================================================
4743 // ===========================================================================================
4745 /*! \brief Initialize The MLME Queue, used by MLME Functions
4746 * \param *Queue The MLME Queue
4747 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4750 * \note Because this is done only once (at the init stage), no need to be locked
4752 IRQL = PASSIVE_LEVEL
4755 NDIS_STATUS MlmeQueueInit(
4756 IN MLME_QUEUE *Queue)
4760 NdisAllocateSpinLock(&Queue->Lock);
4766 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4768 Queue->Entry[i].Occupied = FALSE;
4769 Queue->Entry[i].MsgLen = 0;
4770 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4773 return NDIS_STATUS_SUCCESS;
4776 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4777 * \param *Queue The MLME Queue
4778 * \param Machine The State Machine Id
4779 * \param MsgType The Message Type
4780 * \param MsgLen The Message length
4781 * \param *Msg The message pointer
4782 * \return TRUE if enqueue is successful, FALSE if the queue is full
4785 * \note The message has to be initialized
4787 IRQL = PASSIVE_LEVEL
4788 IRQL = DISPATCH_LEVEL
4791 BOOLEAN MlmeEnqueue(
4792 IN PRTMP_ADAPTER pAd,
4799 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4801 // Do nothing if the driver is starting halt state.
4802 // This might happen when timer already been fired before cancel timer with mlmehalt
4803 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4806 // First check the size, it MUST not exceed the mlme queue size
4807 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4809 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4813 if (MlmeQueueFull(Queue))
4818 NdisAcquireSpinLock(&(Queue->Lock));
4822 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4827 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4828 Queue->Entry[Tail].Occupied = TRUE;
4829 Queue->Entry[Tail].Machine = Machine;
4830 Queue->Entry[Tail].MsgType = MsgType;
4831 Queue->Entry[Tail].MsgLen = MsgLen;
4835 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4838 NdisReleaseSpinLock(&(Queue->Lock));
4842 /*! \brief This function is used when Recv gets a MLME message
4843 * \param *Queue The MLME Queue
4844 * \param TimeStampHigh The upper 32 bit of timestamp
4845 * \param TimeStampLow The lower 32 bit of timestamp
4846 * \param Rssi The receiving RSSI strength
4847 * \param MsgLen The length of the message
4848 * \param *Msg The message pointer
4849 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4853 IRQL = DISPATCH_LEVEL
4856 BOOLEAN MlmeEnqueueForRecv(
4857 IN PRTMP_ADAPTER pAd,
4859 IN ULONG TimeStampHigh,
4860 IN ULONG TimeStampLow,
4869 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4871 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4874 /* Nothing to do in ATE mode */
4877 #endif // RALINK_ATE //
4879 // Do nothing if the driver is starting halt state.
4880 // This might happen when timer already been fired before cancel timer with mlmehalt
4881 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4883 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4887 // First check the size, it MUST not exceed the mlme queue size
4888 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4890 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4894 if (MlmeQueueFull(Queue))
4899 #ifdef CONFIG_STA_SUPPORT
4900 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4902 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4904 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4908 #endif // CONFIG_STA_SUPPORT //
4910 // OK, we got all the informations, it is time to put things into queue
4911 NdisAcquireSpinLock(&(Queue->Lock));
4915 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4919 Queue->Entry[Tail].Occupied = TRUE;
4920 Queue->Entry[Tail].Machine = Machine;
4921 Queue->Entry[Tail].MsgType = MsgType;
4922 Queue->Entry[Tail].MsgLen = MsgLen;
4923 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4924 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4925 Queue->Entry[Tail].Rssi0 = Rssi0;
4926 Queue->Entry[Tail].Rssi1 = Rssi1;
4927 Queue->Entry[Tail].Rssi2 = Rssi2;
4928 Queue->Entry[Tail].Signal = Signal;
4929 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4931 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4935 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4938 NdisReleaseSpinLock(&(Queue->Lock));
4940 RT28XX_MLME_HANDLER(pAd);
4946 /*! \brief Dequeue a message from the MLME Queue
4947 * \param *Queue The MLME Queue
4948 * \param *Elem The message dequeued from MLME Queue
4949 * \return TRUE if the Elem contains something, FALSE otherwise
4953 IRQL = DISPATCH_LEVEL
4956 BOOLEAN MlmeDequeue(
4957 IN MLME_QUEUE *Queue,
4958 OUT MLME_QUEUE_ELEM **Elem)
4960 NdisAcquireSpinLock(&(Queue->Lock));
4961 *Elem = &(Queue->Entry[Queue->Head]);
4964 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4968 NdisReleaseSpinLock(&(Queue->Lock));
4972 // IRQL = DISPATCH_LEVEL
4973 VOID MlmeRestartStateMachine(
4974 IN PRTMP_ADAPTER pAd)
4976 #ifdef CONFIG_STA_SUPPORT
4978 #endif // CONFIG_STA_SUPPORT //
4980 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4983 #ifdef CONFIG_STA_SUPPORT
4984 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4986 #ifdef QOS_DLS_SUPPORT
4988 #endif // QOS_DLS_SUPPORT //
4989 // Cancel all timer events
4990 // Be careful to cancel new added timer
4991 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4992 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4993 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4994 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4995 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4996 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4998 #ifdef QOS_DLS_SUPPORT
4999 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
5001 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
5003 #endif // QOS_DLS_SUPPORT //
5005 #endif // CONFIG_STA_SUPPORT //
5007 // Change back to original channel in case of doing scan
5008 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
5009 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
5011 // Resume MSDU which is turned off durning scan
5012 RTMPResumeMsduTransmission(pAd);
5014 #ifdef CONFIG_STA_SUPPORT
5015 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5017 // Set all state machines back IDLE
5018 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
5019 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
5020 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
5021 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
5022 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
5023 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
5024 #ifdef QOS_DLS_SUPPORT
5025 pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
5026 #endif // QOS_DLS_SUPPORT //
5028 #endif // CONFIG_STA_SUPPORT //
5032 /*! \brief test if the MLME Queue is empty
5033 * \param *Queue The MLME Queue
5034 * \return TRUE if the Queue is empty, FALSE otherwise
5038 IRQL = DISPATCH_LEVEL
5041 BOOLEAN MlmeQueueEmpty(
5042 IN MLME_QUEUE *Queue)
5046 NdisAcquireSpinLock(&(Queue->Lock));
5047 Ans = (Queue->Num == 0);
5048 NdisReleaseSpinLock(&(Queue->Lock));
5053 /*! \brief test if the MLME Queue is full
5054 * \param *Queue The MLME Queue
5055 * \return TRUE if the Queue is empty, FALSE otherwise
5059 IRQL = PASSIVE_LEVEL
5060 IRQL = DISPATCH_LEVEL
5063 BOOLEAN MlmeQueueFull(
5064 IN MLME_QUEUE *Queue)
5068 NdisAcquireSpinLock(&(Queue->Lock));
5069 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5070 NdisReleaseSpinLock(&(Queue->Lock));
5075 /*! \brief The destructor of MLME Queue
5080 * \note Clear Mlme Queue, Set Queue->Num to Zero.
5082 IRQL = PASSIVE_LEVEL
5085 VOID MlmeQueueDestroy(
5086 IN MLME_QUEUE *pQueue)
5088 NdisAcquireSpinLock(&(pQueue->Lock));
5092 NdisReleaseSpinLock(&(pQueue->Lock));
5093 NdisFreeSpinLock(&(pQueue->Lock));
5096 /*! \brief To substitute the message type if the message is coming from external
5097 * \param pFrame The frame received
5098 * \param *Machine The state machine
5099 * \param *MsgType the message type for the state machine
5100 * \return TRUE if the substitution is successful, FALSE otherwise
5104 IRQL = DISPATCH_LEVEL
5107 #ifdef CONFIG_STA_SUPPORT
5108 BOOLEAN MsgTypeSubst(
5109 IN PRTMP_ADAPTER pAd,
5110 IN PFRAME_802_11 pFrame,
5118 // Pointer to start of data frames including SNAP header
5119 pData = (PUCHAR) pFrame + LENGTH_802_11;
5121 // The only data type will pass to this function is EAPOL frame
5122 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5124 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5126 // Cisco Aironet SNAP header
5127 *Machine = AIRONET_STATE_MACHINE;
5128 *MsgType = MT2_AIRONET_MSG;
5132 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5135 *Machine = LEAP_STATE_MACHINE;
5136 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5137 return (LeapMsgTypeSubst(EAPType, MsgType));
5140 #endif // LEAP_SUPPORT //
5142 *Machine = WPA_PSK_STATE_MACHINE;
5143 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5144 return(WpaMsgTypeSubst(EAPType, MsgType));
5148 switch (pFrame->Hdr.FC.SubType)
5150 case SUBTYPE_ASSOC_REQ:
5151 *Machine = ASSOC_STATE_MACHINE;
5152 *MsgType = MT2_PEER_ASSOC_REQ;
5154 case SUBTYPE_ASSOC_RSP:
5155 *Machine = ASSOC_STATE_MACHINE;
5156 *MsgType = MT2_PEER_ASSOC_RSP;
5158 case SUBTYPE_REASSOC_REQ:
5159 *Machine = ASSOC_STATE_MACHINE;
5160 *MsgType = MT2_PEER_REASSOC_REQ;
5162 case SUBTYPE_REASSOC_RSP:
5163 *Machine = ASSOC_STATE_MACHINE;
5164 *MsgType = MT2_PEER_REASSOC_RSP;
5166 case SUBTYPE_PROBE_REQ:
5167 *Machine = SYNC_STATE_MACHINE;
5168 *MsgType = MT2_PEER_PROBE_REQ;
5170 case SUBTYPE_PROBE_RSP:
5171 *Machine = SYNC_STATE_MACHINE;
5172 *MsgType = MT2_PEER_PROBE_RSP;
5174 case SUBTYPE_BEACON:
5175 *Machine = SYNC_STATE_MACHINE;
5176 *MsgType = MT2_PEER_BEACON;
5179 *Machine = SYNC_STATE_MACHINE;
5180 *MsgType = MT2_PEER_ATIM;
5182 case SUBTYPE_DISASSOC:
5183 *Machine = ASSOC_STATE_MACHINE;
5184 *MsgType = MT2_PEER_DISASSOC_REQ;
5187 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5188 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5189 if (Seq == 1 || Seq == 3)
5191 *Machine = AUTH_RSP_STATE_MACHINE;
5192 *MsgType = MT2_PEER_AUTH_ODD;
5194 else if (Seq == 2 || Seq == 4)
5196 *Machine = AUTH_STATE_MACHINE;
5197 *MsgType = MT2_PEER_AUTH_EVEN;
5204 case SUBTYPE_DEAUTH:
5205 *Machine = AUTH_RSP_STATE_MACHINE;
5206 *MsgType = MT2_PEER_DEAUTH;
5208 case SUBTYPE_ACTION:
5209 *Machine = ACTION_STATE_MACHINE;
5210 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5211 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5213 *MsgType = MT2_ACT_INVALID;
5217 *MsgType = (pFrame->Octet[0]&0x7F);
5227 #endif // CONFIG_STA_SUPPORT //
5229 // ===========================================================================================
5231 // ===========================================================================================
5233 /*! \brief Initialize the state machine.
5234 * \param *S pointer to the state machine
5235 * \param Trans State machine transition function
5236 * \param StNr number of states
5237 * \param MsgNr number of messages
5238 * \param DefFunc default function, when there is invalid state/message combination
5239 * \param InitState initial state of the state machine
5240 * \param Base StateMachine base, internal use only
5241 * \pre p_sm should be a legal pointer
5244 IRQL = PASSIVE_LEVEL
5247 VOID StateMachineInit(
5248 IN STATE_MACHINE *S,
5249 IN STATE_MACHINE_FUNC Trans[],
5252 IN STATE_MACHINE_FUNC DefFunc,
5258 // set number of states and messages
5263 S->TransFunc = Trans;
5265 // init all state transition to default function
5266 for (i = 0; i < StNr; i++)
5268 for (j = 0; j < MsgNr; j++)
5270 S->TransFunc[i * MsgNr + j] = DefFunc;
5274 // set the starting state
5275 S->CurrState = InitState;
5278 /*! \brief This function fills in the function pointer into the cell in the state machine
5279 * \param *S pointer to the state machine
5281 * \param Msg incoming message
5282 * \param f the function to be executed when (state, message) combination occurs at the state machine
5283 * \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
5286 IRQL = PASSIVE_LEVEL
5289 VOID StateMachineSetAction(
5290 IN STATE_MACHINE *S,
5293 IN STATE_MACHINE_FUNC Func)
5297 MsgIdx = Msg - S->Base;
5299 if (St < S->NrState && MsgIdx < S->NrMsg)
5301 // boundary checking before setting the action
5302 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5306 /*! \brief This function does the state transition
5307 * \param *Adapter the NIC adapter pointer
5308 * \param *S the state machine
5309 * \param *Elem the message to be executed
5312 IRQL = DISPATCH_LEVEL
5315 VOID StateMachinePerformAction(
5316 IN PRTMP_ADAPTER pAd,
5317 IN STATE_MACHINE *S,
5318 IN MLME_QUEUE_ELEM *Elem)
5320 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5324 ==========================================================================
5326 The drop function, when machine executes this, the message is simply
5327 ignored. This function does nothing, the message is freed in
5328 StateMachinePerformAction()
5329 ==========================================================================
5332 IN PRTMP_ADAPTER pAd,
5333 IN MLME_QUEUE_ELEM *Elem)
5337 // ===========================================================================================
5339 // ===========================================================================================
5342 ==========================================================================
5345 IRQL = PASSIVE_LEVEL
5347 ==========================================================================
5350 IN PRTMP_ADAPTER pAd,
5354 pAd->Mlme.ShiftReg = 1;
5356 pAd->Mlme.ShiftReg = Seed;
5360 ==========================================================================
5362 ==========================================================================
5365 IN PRTMP_ADAPTER pAd)
5372 if (pAd->Mlme.ShiftReg == 0)
5373 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5375 for (i = 0; i < 8; i++)
5377 if (pAd->Mlme.ShiftReg & 0x00000001)
5379 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5384 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5387 R = (R << 1) | Result;
5393 VOID AsicUpdateAutoFallBackTable(
5394 IN PRTMP_ADAPTER pAd,
5395 IN PUCHAR pRateTable)
5398 HT_FBK_CFG0_STRUC HtCfg0;
5399 HT_FBK_CFG1_STRUC HtCfg1;
5400 LG_FBK_CFG0_STRUC LgCfg0;
5401 LG_FBK_CFG1_STRUC LgCfg1;
5402 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5404 // set to initial value
5405 HtCfg0.word = 0x65432100;
5406 HtCfg1.word = 0xedcba988;
5407 LgCfg0.word = 0xedcba988;
5408 LgCfg1.word = 0x00002100;
5410 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5411 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5413 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5414 switch (pCurrTxRate->Mode)
5420 switch(pCurrTxRate->CurrMCS)
5423 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5426 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5429 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5432 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5435 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5438 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5441 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5444 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5449 #ifdef DOT11_N_SUPPORT
5453 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5455 switch(pCurrTxRate->CurrMCS)
5458 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5461 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5464 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5467 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5470 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5473 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5476 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5479 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5482 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5485 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5488 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5491 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5494 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5497 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5500 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5503 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5506 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5511 #endif // DOT11_N_SUPPORT //
5514 pNextTxRate = pCurrTxRate;
5517 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5518 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5519 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5520 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5524 ========================================================================
5526 Routine Description:
5527 Set MAC register value according operation mode.
5528 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5529 If MM or GF mask is not set, those passing argument doesn't not take effect.
5531 Operation mode meaning:
5532 = 0 : Pure HT, no preotection.
5533 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5534 = 0x10: No Transmission in 40M is protected.
5535 = 0x11: Transmission in both 40M and 20M shall be protected
5537 we should choose not to use GF. But still set correct ASIC registers.
5538 ========================================================================
5540 VOID AsicUpdateProtect(
5541 IN PRTMP_ADAPTER pAd,
5542 IN USHORT OperationMode,
5544 IN BOOLEAN bDisableBGProtect,
5545 IN BOOLEAN bNonGFExist)
5547 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5556 #endif // RALINK_ATE //
5558 #ifdef DOT11_N_SUPPORT
5559 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5564 if (pAd->BATable.numAsOriginator)
5567 // enable the RTS/CTS to avoid channel collision
5569 SetMask = ALLN_SETPROTECT;
5572 #endif // DOT11_N_SUPPORT //
5574 // Config ASIC RTS threshold register
5575 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5576 MacReg &= 0xFF0000FF;
5578 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5580 #ifdef DOT11_N_SUPPORT
5581 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5582 #endif // DOT11_N_SUPPORT //
5583 (pAd->CommonCfg.bAggregationCapable == TRUE))
5584 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5586 MacReg |= (0x1000 << 8);
5590 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5593 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5595 // Initial common protection settings
5596 RTMPZeroMemory(Protect, sizeof(Protect));
5599 ProtCfg.field.TxopAllowGF40 = 1;
5600 ProtCfg.field.TxopAllowGF20 = 1;
5601 ProtCfg.field.TxopAllowMM40 = 1;
5602 ProtCfg.field.TxopAllowMM20 = 1;
5603 ProtCfg.field.TxopAllowOfdm = 1;
5604 ProtCfg.field.TxopAllowCck = 1;
5605 ProtCfg.field.RTSThEn = 1;
5606 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5608 // update PHY mode and rate
5609 if (pAd->CommonCfg.Channel > 14)
5610 ProtCfg.field.ProtectRate = 0x4000;
5611 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5613 // Handle legacy(B/G) protection
5614 if (bDisableBGProtect)
5616 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5617 ProtCfg.field.ProtectCtrl = 0;
5618 Protect[0] = ProtCfg.word;
5619 Protect[1] = ProtCfg.word;
5623 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5624 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5625 Protect[0] = ProtCfg.word;
5626 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5627 Protect[1] = ProtCfg.word;
5630 #ifdef DOT11_N_SUPPORT
5631 // Decide HT frame protection.
5632 if ((SetMask & ALLN_SETPROTECT) != 0)
5634 switch(OperationMode)
5638 // 1.All STAs in the BSS are 20/40 MHz HT
5639 // 2. in ai 20/40MHz BSS
5640 // 3. all STAs are 20MHz in a 20MHz BSS
5641 // Pure HT. no protection.
5645 // PROT_TXOP(25:20) -- 010111
5646 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5647 // PROT_CTRL(17:16) -- 00 (None)
5648 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5649 Protect[2] = 0x01744004;
5653 // PROT_TXOP(25:20) -- 111111
5654 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5655 // PROT_CTRL(17:16) -- 00 (None)
5656 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5657 Protect[3] = 0x03f44084;
5661 // PROT_TXOP(25:20) -- 010111
5662 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5663 // PROT_CTRL(17:16) -- 00 (None)
5664 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5665 Protect[4] = 0x01744004;
5669 // PROT_TXOP(25:20) -- 111111
5670 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5671 // PROT_CTRL(17:16) -- 00 (None)
5672 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5673 Protect[5] = 0x03f44084;
5677 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5678 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5679 Protect[4] = 0x01754004;
5680 Protect[5] = 0x03f54084;
5682 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5686 // This is "HT non-member protection mode."
5687 // If there may be non-HT STAs my BSS
5688 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5689 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5690 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5692 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5693 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5695 //Assign Protection method for 20&40 MHz packets
5696 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5697 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5698 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5699 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5700 Protect[2] = ProtCfg.word;
5701 Protect[3] = ProtCfg4.word;
5702 Protect[4] = ProtCfg.word;
5703 Protect[5] = ProtCfg4.word;
5704 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5708 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5709 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5710 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5712 //Assign Protection method for 40MHz packets
5713 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5714 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5715 Protect[2] = ProtCfg.word;
5716 Protect[3] = ProtCfg4.word;
5719 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5720 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5722 Protect[4] = ProtCfg.word;
5723 Protect[5] = ProtCfg4.word;
5725 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5729 // HT mixed mode. PROTECT ALL!
5731 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5732 ProtCfg4.word = 0x03f44084;
5733 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5734 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5736 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5737 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5739 //Assign Protection method for 20&40 MHz packets
5740 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5741 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5742 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5743 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5744 Protect[2] = ProtCfg.word;
5745 Protect[3] = ProtCfg4.word;
5746 Protect[4] = ProtCfg.word;
5747 Protect[5] = ProtCfg4.word;
5748 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5752 Protect[2] = 0x01754004;
5753 Protect[3] = 0x03f54084;
5754 Protect[4] = 0x01754004;
5755 Protect[5] = 0x03f54084;
5756 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5760 #endif // DOT11_N_SUPPORT //
5762 offset = CCK_PROT_CFG;
5763 for (i = 0;i < 6;i++)
5765 if ((SetMask & (1<< i)))
5767 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5775 ========================================================================
5777 Routine Description: Write RT30xx RF register through MAC
5787 ========================================================================
5789 NTSTATUS RT30xxWriteRFRegister(
5790 IN PRTMP_ADAPTER pAd,
5794 RF_CSR_CFG_STRUC rfcsr;
5799 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5801 if (!rfcsr.field.RF_CSR_KICK)
5805 while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
5807 if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
5809 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
5810 return STATUS_UNSUCCESSFUL;
5813 rfcsr.field.RF_CSR_WR = 1;
5814 rfcsr.field.RF_CSR_KICK = 1;
5815 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5816 rfcsr.field.RF_CSR_DATA = Value;
5818 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5820 return STATUS_SUCCESS;
5825 ========================================================================
5827 Routine Description: Read RT30xx RF register through MAC
5837 ========================================================================
5839 NTSTATUS RT30xxReadRFRegister(
5840 IN PRTMP_ADAPTER pAd,
5844 RF_CSR_CFG_STRUC rfcsr;
5847 for (i=0; i<MAX_BUSY_COUNT; i++)
5849 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5851 if (rfcsr.field.RF_CSR_KICK == BUSY)
5856 rfcsr.field.RF_CSR_WR = 0;
5857 rfcsr.field.RF_CSR_KICK = 1;
5858 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5859 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5860 for (k=0; k<MAX_BUSY_COUNT; k++)
5862 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5864 if (rfcsr.field.RF_CSR_KICK == IDLE)
5867 if ((rfcsr.field.RF_CSR_KICK == IDLE) &&
5868 (rfcsr.field.TESTCSR_RFACC_REGNUM == RegID))
5870 *pValue = (UCHAR)rfcsr.field.RF_CSR_DATA;
5874 if (rfcsr.field.RF_CSR_KICK == BUSY)
5876 DBGPRINT_ERR(("RF read R%d=0x%x fail, i[%d], k[%d]\n", RegID, rfcsr.word,i,k));
5877 return STATUS_UNSUCCESSFUL;
5880 return STATUS_SUCCESS;
5885 // add by johnli, RF power sequence setup
5887 ==========================================================================
5890 Load RF normal operation-mode setup
5892 ==========================================================================
5894 VOID RT30xxLoadRFNormalModeSetup(
5895 IN PRTMP_ADAPTER pAd)
5899 // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1
5900 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5901 RFValue = (RFValue & (~0x0C)) | 0x31;
5902 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5904 // TX_LO2_en, RF R15 register Bit 3 to 0
5905 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5907 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5909 // TX_LO1_en, RF R17 register Bit 3 to 0
5910 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5912 // to fix rx long range issue
5913 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5917 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5919 // RX_LO1_en, RF R20 register Bit 3 to 0
5920 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5922 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5924 // RX_LO2_en, RF R21 register Bit 3 to 0
5925 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5927 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5929 // LDORF_VC, RF R27 register Bit 2 to 0
5930 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5931 if ((pAd->MACVersion & 0xffff) < 0x0211)
5932 RFValue = (RFValue & (~0x77)) | 0x3;
5934 RFValue = (RFValue & (~0x77));
5935 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5940 ==========================================================================
5943 Load RF sleep-mode setup
5945 ==========================================================================
5947 VOID RT30xxLoadRFSleepModeSetup(
5948 IN PRTMP_ADAPTER pAd)
5953 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5954 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5956 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5958 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5959 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5961 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5963 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5964 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5966 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5968 // RX_CTB_en, RF R21 register Bit 7 to 0
5969 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5971 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5973 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5974 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5976 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5978 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5979 MACValue |= 0x1D000000;
5980 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5984 ==========================================================================
5987 Reverse RF sleep-mode setup
5989 ==========================================================================
5991 VOID RT30xxReverseRFSleepModeSetup(
5992 IN PRTMP_ADAPTER pAd)
5997 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5998 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
6000 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
6002 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
6003 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
6005 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
6007 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
6008 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
6010 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
6012 // RX_CTB_en, RF R21 register Bit 7 to 1
6013 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
6015 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
6017 // LDORF_VC, RF R27 register Bit 2 to 0
6018 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
6019 if ((pAd->MACVersion & 0xffff) < 0x0211)
6020 RFValue = (RFValue & (~0x77)) | 0x3;
6022 RFValue = (RFValue & (~0x77));
6023 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
6025 // RT3071 version E has fixed this issue
6026 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
6028 // patch tx EVM issue temporarily
6029 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
6030 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
6031 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
6035 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
6036 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
6037 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
6044 ==========================================================================
6047 IRQL = PASSIVE_LEVEL
6048 IRQL = DISPATCH_LEVEL
6050 ==========================================================================
6052 VOID AsicSwitchChannel(
6053 IN PRTMP_ADAPTER pAd,
6057 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
6058 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
6060 UINT32 Value = 0; //BbpReg, Value;
6061 RTMP_RF_REGS *RFRegTable;
6063 // Search Tx power value
6065 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
6066 // in ChannelList, so use TxPower array instead.
6068 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
6070 if (Channel == pAd->TxPower[index].Channel)
6072 TxPwer = pAd->TxPower[index].Power;
6073 TxPwer2 = pAd->TxPower[index].Power2;
6078 for (index = 0; index < pAd->ChannelListNum; index++)
6080 if (Channel == pAd->ChannelList[index].Channel)
6082 TxPwer = pAd->ChannelList[index].Power;
6083 TxPwer2 = pAd->ChannelList[index].Power2;
6089 if (index == MAX_NUM_OF_CHANNELS)
6091 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
6095 // The RF programming sequence is difference between 3xxx and 2xxx
6096 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
6097 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
6099 /* modify by WY for Read RF Reg. error */
6102 for (index = 0; index < NUM_OF_3020_CHNL; index++)
6104 if (Channel == FreqItems3020[index].Channel)
6106 // Programming channel parameters
6107 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
6108 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
6109 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
6110 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
6111 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
6114 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
6115 RFValue = (RFValue & 0xE0) | TxPwer;
6116 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
6119 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
6120 RFValue = (RFValue & 0xE0) | TxPwer2;
6121 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
6123 // Tx/Rx Stream setting
6124 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
6125 //if (IS_RT3090(pAd))
6126 // RFValue |= 0x01; // Enable RF block.
6127 RFValue &= 0x03; //clear bit[7~2]
6128 if (pAd->Antenna.field.TxPath == 1)
6130 else if (pAd->Antenna.field.TxPath == 2)
6132 if (pAd->Antenna.field.RxPath == 1)
6134 else if (pAd->Antenna.field.RxPath == 2)
6136 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
6139 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
6140 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
6141 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
6144 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6146 RFValue = pAd->Mlme.CaliBW40RfR24;
6147 //DISABLE_11N_CHECK(pAd);
6151 RFValue = pAd->Mlme.CaliBW20RfR24;
6153 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
6154 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
6157 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
6158 RFValue = RFValue | 0x1;
6159 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
6161 // latch channel for future usage.
6162 pAd->LatchRfRegs.Channel = Channel;
6164 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
6169 pAd->Antenna.field.TxPath,
6170 FreqItems3020[index].N,
6171 FreqItems3020[index].K,
6172 FreqItems3020[index].R));
6182 RFRegTable = RF2850RegTable;
6184 switch (pAd->RfIcType)
6191 for (index = 0; index < NUM_OF_2850_CHNL; index++)
6193 if (Channel == RFRegTable[index].Channel)
6195 R2 = RFRegTable[index].R2;
6196 if (pAd->Antenna.field.TxPath == 1)
6198 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
6201 if (pAd->Antenna.field.RxPath == 2)
6203 R2 |= 0x40; // write 1 to off Rxpath.
6205 else if (pAd->Antenna.field.RxPath == 1)
6207 R2 |= 0x20040; // write 1 to off RxPath
6212 // initialize R3, R4
6213 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
6214 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
6216 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
6218 if ((TxPwer >= -7) && (TxPwer < 0))
6220 TxPwer = (7+TxPwer);
6221 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
6222 R3 |= (TxPwer << 10);
6223 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
6227 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
6228 R3 |= (TxPwer << 10) | (1 << 9);
6232 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
6234 TxPwer2 = (7+TxPwer2);
6235 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6236 R4 |= (TxPwer2 << 7);
6237 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
6241 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6242 R4 |= (TxPwer2 << 7) | (1 << 6);
6247 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
6248 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
6251 // Based on BBP current mode before changing RF channel.
6252 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6258 pAd->LatchRfRegs.Channel = Channel;
6259 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
6260 pAd->LatchRfRegs.R2 = R2;
6261 pAd->LatchRfRegs.R3 = R3;
6262 pAd->LatchRfRegs.R4 = R4;
6264 // Set RF value 1's set R3[bit2] = [0]
6265 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6266 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6267 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6268 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6272 // Set RF value 2's set R3[bit2] = [1]
6273 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6274 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6275 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
6276 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6280 // Set RF value 3's set R3[bit2] = [0]
6281 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6282 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6283 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6284 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6296 // Change BBP setting during siwtch from a->g, g->a
6299 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
6301 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6302 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6303 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6304 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.
6305 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6307 // Rx High power VGA offset for LNA select
6308 if (pAd->NicConfig2.field.ExternalLNAForG)
6310 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6311 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6315 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6316 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6319 // 5G band selection PIN, bit1 and bit2 are complement
6320 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6323 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6325 // Turn off unused PA or LNA when only 1T or 1R
6326 if (pAd->Antenna.field.TxPath == 1)
6328 TxPinCfg &= 0xFFFFFFF3;
6330 if (pAd->Antenna.field.RxPath == 1)
6332 TxPinCfg &= 0xFFFFF3FF;
6335 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6339 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6341 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6342 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6343 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6344 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.
6345 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6347 // Rx High power VGA offset for LNA select
6348 if (pAd->NicConfig2.field.ExternalLNAForA)
6350 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6354 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6357 // 5G band selection PIN, bit1 and bit2 are complement
6358 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6361 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6363 // Turn off unused PA or LNA when only 1T or 1R
6364 if (pAd->Antenna.field.TxPath == 1)
6366 TxPinCfg &= 0xFFFFFFF3;
6368 if (pAd->Antenna.field.RxPath == 1)
6370 TxPinCfg &= 0xFFFFF3FF;
6373 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6376 // R66 should be set according to Channel and use 20MHz when scanning
6377 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6379 RTMPSetAGCInitValue(pAd, BW_20);
6381 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6384 // On 11A, We should delay and wait RF/BBP to be stable
6385 // and the appropriate time should be 1000 micro seconds
6386 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6388 RTMPusecDelay(1000);
6390 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",
6393 (R3 & 0x00003e00) >> 9,
6394 (R4 & 0x000007c0) >> 6,
6395 pAd->Antenna.field.TxPath,
6396 pAd->LatchRfRegs.R1,
6397 pAd->LatchRfRegs.R2,
6398 pAd->LatchRfRegs.R3,
6399 pAd->LatchRfRegs.R4));
6403 ==========================================================================
6405 This function is required for 2421 only, and should not be used during
6406 site survey. It's only required after NIC decided to stay at a channel
6407 for a longer period.
6408 When this function is called, it's always after AsicSwitchChannel().
6410 IRQL = PASSIVE_LEVEL
6411 IRQL = DISPATCH_LEVEL
6413 ==========================================================================
6415 VOID AsicLockChannel(
6416 IN PRTMP_ADAPTER pAd,
6422 ==========================================================================
6425 IRQL = PASSIVE_LEVEL
6426 IRQL = DISPATCH_LEVEL
6428 ==========================================================================
6430 VOID AsicAntennaSelect(
6431 IN PRTMP_ADAPTER pAd,
6434 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6436 // patch for AsicSetRxAnt failed
6437 pAd->RxAnt.EvaluatePeriod = 0;
6439 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6440 // valid indication of the distance between this AP and its clients.
6441 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6445 // if no traffic then reset average rssi to trigger evaluation
6446 #ifdef CONFIG_STA_SUPPORT
6447 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6449 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6450 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6451 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6454 pAd->StaCfg.NumOfAvgRssiSample = 0;
6455 #endif // CONFIG_STA_SUPPORT //
6456 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6458 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6460 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6461 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6463 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6464 AsicEvaluateRxAnt(pAd);
6469 // if not connected, always switch antenna to try to connect
6472 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6473 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6474 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6476 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6478 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6484 ========================================================================
6486 Routine Description:
6487 Antenna miscellaneous setting.
6490 pAd Pointer to our adapter
6491 BandState Indicate current Band State.
6496 IRQL <= DISPATCH_LEVEL
6499 1.) Frame End type control
6500 only valid for G only (RF_2527 & RF_2529)
6501 0: means DPDT, set BBP R4 bit 5 to 1
6502 1: means SPDT, set BBP R4 bit 5 to 0
6505 ========================================================================
6507 VOID AsicAntennaSetting(
6508 IN PRTMP_ADAPTER pAd,
6509 IN ABGBAND_STATE BandState)
6513 VOID AsicRfTuningExec(
6514 IN PVOID SystemSpecific1,
6515 IN PVOID FunctionContext,
6516 IN PVOID SystemSpecific2,
6517 IN PVOID SystemSpecific3)
6522 ==========================================================================
6524 Gives CCK TX rate 2 more dB TX power.
6525 This routine works only in LINK UP in INFRASTRUCTURE mode.
6527 calculate desired Tx power in RF R3.Tx0~5, should consider -
6528 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6529 1. TxPowerPercentage
6530 2. auto calibration based on TSSI feedback
6531 3. extra 2 db for CCK
6532 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6534 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6535 it should be called AFTER MlmeDynamicTxRatSwitching()
6536 ==========================================================================
6538 VOID AsicAdjustTxPower(
6539 IN PRTMP_ADAPTER pAd)
6543 BOOLEAN bAutoTxAgc = FALSE;
6544 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6545 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6546 PCHAR pTxAgcCompensate;
6552 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6554 if (pAd->CommonCfg.CentralChannel > 14)
6556 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6557 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6558 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6559 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6560 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6564 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6565 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6566 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6567 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6568 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6573 if (pAd->CommonCfg.Channel > 14)
6575 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6576 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6577 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6578 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6579 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6583 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6584 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6585 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6586 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6587 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6591 // TX power compensation for temperature variation based on TSSI. try every 4 second
6592 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6594 if (pAd->CommonCfg.Channel <= 14)
6597 bAutoTxAgc = pAd->bAutoTxAgcG;
6598 TssiRef = pAd->TssiRefG;
6599 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6600 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6601 TxAgcStep = pAd->TxAgcStepG;
6602 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6607 bAutoTxAgc = pAd->bAutoTxAgcA;
6608 TssiRef = pAd->TssiRefA;
6609 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6610 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6611 TxAgcStep = pAd->TxAgcStepA;
6612 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6617 /* BbpR1 is unsigned char */
6618 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6620 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6621 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6622 /* step value is defined in pAd->TxAgcStepG for tx power value */
6624 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6625 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6626 above value are examined in mass factory production */
6627 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6629 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6630 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6631 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6633 if (BbpR49 > pTssiMinusBoundary[1])
6635 // Reading is larger than the reference value
6636 // check for how large we need to decrease the Tx power
6637 for (idx = 1; idx < 5; idx++)
6639 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6642 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6643 // if (R3 > (ULONG) (TxAgcStep * (idx-1)))
6644 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6646 // *pTxAgcCompensate = -((UCHAR)R3);
6648 DeltaPwr += (*pTxAgcCompensate);
6649 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6650 BbpR49, TssiRef, TxAgcStep, idx-1));
6652 else if (BbpR49 < pTssiPlusBoundary[1])
6654 // Reading is smaller than the reference value
6655 // check for how large we need to increase the Tx power
6656 for (idx = 1; idx < 5; idx++)
6658 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6661 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6662 *pTxAgcCompensate = TxAgcStep * (idx-1);
6663 DeltaPwr += (*pTxAgcCompensate);
6664 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6665 BbpR49, TssiRef, TxAgcStep, idx-1));
6669 *pTxAgcCompensate = 0;
6670 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6671 BbpR49, TssiRef, TxAgcStep, 0));
6677 if (pAd->CommonCfg.Channel <= 14)
6679 bAutoTxAgc = pAd->bAutoTxAgcG;
6680 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6684 bAutoTxAgc = pAd->bAutoTxAgcA;
6685 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6689 DeltaPwr += (*pTxAgcCompensate);
6692 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6696 // Handle regulatory max tx power constrain
6699 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6700 UCHAR AdjustMaxTxPwr[40];
6702 if (pAd->CommonCfg.Channel > 14) // 5G band
6703 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6705 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6706 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6708 // error handling, range check
6709 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6711 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6715 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6717 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6719 // Adjust max tx power according to the relationship of tx power in E2PROM
6722 // CCK will have 4dBm larger than OFDM
6723 // Therefore, we should separate to parse the tx power field
6728 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6732 // CCK will have 4dBm larger than OFDM
6733 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6737 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6739 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6746 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6748 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6749 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6754 // Adjust tx power according to the relationship
6757 if (TxPwr[i] != 0xffffffff)
6761 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6763 // The system tx power is larger than the regulatory, the power should be restrain
6764 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6766 // decrease to zero and don't need to take care BBPR1
6767 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6768 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6772 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6775 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6777 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6782 #endif // SINGLE_SKU //
6784 /* calculate delta power based on the percentage specified from UI */
6785 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6786 // We lower TX power here according to the percentage specified from UI
6787 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6789 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6791 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6795 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6799 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6803 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6808 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6813 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6815 /* reset different new tx power for different TX rate */
6818 if (TxPwr[i] != 0xffffffff)
6822 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6824 if ((Value + DeltaPwr) < 0)
6826 Value = 0; /* min */
6828 else if ((Value + DeltaPwr) > 0xF)
6830 Value = 0xF; /* max */
6834 Value += DeltaPwr; /* temperature compensation */
6837 /* fill new value to CSR offset */
6838 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6841 /* write tx power value to CSR */
6842 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6843 TX power for OFDM 6M/9M
6844 TX power for CCK5.5M/11M
6845 TX power for CCK1M/2M */
6846 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6847 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6854 #ifdef CONFIG_STA_SUPPORT
6856 ==========================================================================
6858 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6859 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6860 the wakeup timer timeout. Driver has to issue a separate command to wake
6863 IRQL = DISPATCH_LEVEL
6865 ==========================================================================
6867 VOID AsicSleepThenAutoWakeup(
6868 IN PRTMP_ADAPTER pAd,
6869 IN USHORT TbttNumToNextWakeUp)
6871 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6875 ==========================================================================
6877 AsicForceWakeup() is used whenever manual wakeup is required
6878 AsicForceSleep() should only be used when not in INFRA BSS. When
6879 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6880 ==========================================================================
6882 VOID AsicForceSleep(
6883 IN PRTMP_ADAPTER pAd)
6889 ==========================================================================
6891 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6894 IRQL = PASSIVE_LEVEL
6895 IRQL = DISPATCH_LEVEL
6896 ==========================================================================
6898 VOID AsicForceWakeup(
6899 IN PRTMP_ADAPTER pAd,
6902 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6903 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6905 #endif // CONFIG_STA_SUPPORT //
6907 ==========================================================================
6911 IRQL = DISPATCH_LEVEL
6913 ==========================================================================
6916 IN PRTMP_ADAPTER pAd,
6920 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6921 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6923 Addr4 = (ULONG)(pBssid[0]) |
6924 (ULONG)(pBssid[1] << 8) |
6925 (ULONG)(pBssid[2] << 16) |
6926 (ULONG)(pBssid[3] << 24);
6927 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6930 // always one BSSID in STA mode
6931 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6933 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6936 VOID AsicSetMcastWC(
6937 IN PRTMP_ADAPTER pAd)
6939 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6942 pEntry->Sst = SST_ASSOC;
6943 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6944 pEntry->PsMode = PWR_ACTIVE;
6945 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6946 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6950 ==========================================================================
6953 IRQL = DISPATCH_LEVEL
6955 ==========================================================================
6957 VOID AsicDelWcidTab(
6958 IN PRTMP_ADAPTER pAd,
6961 ULONG Addr0 = 0x0, Addr1 = 0x0;
6964 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6965 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6966 RTMP_IO_WRITE32(pAd, offset, Addr0);
6968 RTMP_IO_WRITE32(pAd, offset, Addr1);
6972 ==========================================================================
6975 IRQL = DISPATCH_LEVEL
6977 ==========================================================================
6980 IN PRTMP_ADAPTER pAd)
6982 TX_LINK_CFG_STRUC TxLinkCfg;
6985 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6986 TxLinkCfg.field.TxRDGEn = 1;
6987 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6989 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6992 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6994 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6998 ==========================================================================
7001 IRQL = DISPATCH_LEVEL
7003 ==========================================================================
7005 VOID AsicDisableRDG(
7006 IN PRTMP_ADAPTER pAd)
7008 TX_LINK_CFG_STRUC TxLinkCfg;
7012 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
7013 TxLinkCfg.field.TxRDGEn = 0;
7014 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
7016 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
7021 //if ( pAd->CommonCfg.bEnableTxBurst )
7022 // Data |= 0x60; // for performance issue not set the TXOP to 0
7024 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
7025 #ifdef DOT11_N_SUPPORT
7026 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
7027 #endif // DOT11_N_SUPPORT //
7030 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
7031 if (pAd->CommonCfg.bEnableTxBurst)
7034 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
7038 ==========================================================================
7041 IRQL = PASSIVE_LEVEL
7042 IRQL = DISPATCH_LEVEL
7044 ==========================================================================
7046 VOID AsicDisableSync(
7047 IN PRTMP_ADAPTER pAd)
7049 BCN_TIME_CFG_STRUC csr;
7051 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
7053 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
7054 // that NIC will never wakes up because TSF stops and no more
7056 pAd->TbttTickCount = 0;
7057 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
7058 csr.field.bBeaconGen = 0;
7059 csr.field.bTBTTEnable = 0;
7060 csr.field.TsfSyncMode = 0;
7061 csr.field.bTsfTicking = 0;
7062 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
7067 ==========================================================================
7070 IRQL = DISPATCH_LEVEL
7072 ==========================================================================
7074 VOID AsicEnableBssSync(
7075 IN PRTMP_ADAPTER pAd)
7077 BCN_TIME_CFG_STRUC csr;
7079 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
7081 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
7082 // RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);
7083 #ifdef CONFIG_STA_SUPPORT
7084 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7086 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
7087 csr.field.bTsfTicking = 1;
7088 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
7089 csr.field.bBeaconGen = 0; // do NOT generate BEACON
7090 csr.field.bTBTTEnable = 1;
7092 #endif // CONFIG_STA_SUPPORT //
7093 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
7097 ==========================================================================
7100 BEACON frame in shared memory should be built ok before this routine
7101 can be called. Otherwise, a garbage frame maybe transmitted out every
7104 IRQL = DISPATCH_LEVEL
7106 ==========================================================================
7108 VOID AsicEnableIbssSync(
7109 IN PRTMP_ADAPTER pAd)
7111 BCN_TIME_CFG_STRUC csr9;
7115 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
7117 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
7118 csr9.field.bBeaconGen = 0;
7119 csr9.field.bTBTTEnable = 0;
7120 csr9.field.bTsfTicking = 0;
7121 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
7125 // move BEACON TXD and frame content to on-chip memory
7126 ptr = (PUCHAR)&pAd->BeaconTxWI;
7127 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
7129 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
7130 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
7131 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
7135 // start right after the 16-byte TXWI field
7136 ptr = pAd->BeaconBuf;
7137 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
7139 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
7140 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
7141 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
7147 // For Wi-Fi faily generated beacons between participating stations.
7148 // Set TBTT phase adaptive adjustment step to 8us (default 16us)
7149 // don't change settings 2006-5- by Jerry
7150 //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);
7152 // start sending BEACON
7153 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
7154 csr9.field.bTsfTicking = 1;
7155 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
7156 csr9.field.bTBTTEnable = 1;
7157 csr9.field.bBeaconGen = 1;
7158 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
7162 ==========================================================================
7165 IRQL = PASSIVE_LEVEL
7166 IRQL = DISPATCH_LEVEL
7168 ==========================================================================
7170 VOID AsicSetEdcaParm(
7171 IN PRTMP_ADAPTER pAd,
7172 IN PEDCA_PARM pEdcaParm)
7174 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
7175 AC_TXOP_CSR0_STRUC csr0;
7176 AC_TXOP_CSR1_STRUC csr1;
7177 AIFSN_CSR_STRUC AifsnCsr;
7178 CWMIN_CSR_STRUC CwminCsr;
7179 CWMAX_CSR_STRUC CwmaxCsr;
7186 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
7188 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
7189 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
7190 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
7192 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
7193 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
7196 //========================================================
7197 // MAC Register has a copy .
7198 //========================================================
7200 if( pAd->CommonCfg.bEnableTxBurst )
7202 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
7203 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
7206 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
7208 // Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
7210 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
7211 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
7212 Ac0Cfg.field.Aifsn = 2;
7213 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7215 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
7216 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
7217 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
7218 Ac1Cfg.field.Aifsn = 2;
7219 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7221 if (pAd->CommonCfg.PhyMode == PHY_11B)
7223 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
7224 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
7228 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
7229 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
7231 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
7232 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
7233 Ac2Cfg.field.Aifsn = 2;
7234 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7235 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
7236 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
7237 Ac3Cfg.field.Aifsn = 2;
7238 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7240 //========================================================
7241 // DMA Register has a copy too.
7242 //========================================================
7243 csr0.field.Ac0Txop = 0; // QID_AC_BE
7244 csr0.field.Ac1Txop = 0; // QID_AC_BK
7245 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7246 if (pAd->CommonCfg.PhyMode == PHY_11B)
7248 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
7249 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
7253 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
7254 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
7256 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7259 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
7260 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
7261 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
7262 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
7263 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7266 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
7267 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
7268 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
7269 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
7270 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7272 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
7274 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
7278 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
7279 //========================================================
7280 // MAC Register has a copy.
7281 //========================================================
7283 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
7284 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
7286 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
7288 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
7289 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
7290 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
7291 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
7293 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7294 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
7295 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
7296 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
7298 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
7299 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
7300 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
7301 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
7302 #ifdef INF_AMAZON_SE
7303 #endif // INF_AMAZON_SE //
7306 #ifdef CONFIG_STA_SUPPORT
7307 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7309 // Tuning for Wi-Fi WMM S06
7310 if (pAd->CommonCfg.bWiFiTest &&
7311 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7312 Ac2Cfg.field.Aifsn -= 1;
7314 // Tuning for TGn Wi-Fi 5.2.32
7315 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
7316 if (STA_TGN_WIFI_ON(pAd) &&
7317 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7319 Ac0Cfg.field.Aifsn = 3;
7320 Ac2Cfg.field.AcTxop = 5;
7324 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7326 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
7327 Ac2Cfg.field.Aifsn = 5;
7331 #endif // CONFIG_STA_SUPPORT //
7333 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
7334 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
7335 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
7336 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
7339 if (pAd->CommonCfg.bWiFiTest)
7341 if (Ac3Cfg.field.AcTxop == 102)
7343 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
7344 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
7345 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7346 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
7347 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
7350 //#endif // WIFI_TEST //
7352 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7353 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7354 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7355 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7358 //========================================================
7359 // DMA Register has a copy too.
7360 //========================================================
7361 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
7362 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
7363 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7365 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
7366 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
7367 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7370 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
7371 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
7372 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
7373 #ifdef CONFIG_STA_SUPPORT
7374 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7375 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
7376 #endif // CONFIG_STA_SUPPORT //
7377 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7380 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
7381 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7382 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7383 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7384 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7387 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7388 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7389 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7390 #ifdef INF_AMAZON_SE
7391 #endif // INF_AMAZON_SE //
7394 #ifdef CONFIG_STA_SUPPORT
7395 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7397 // Tuning for Wi-Fi WMM S06
7398 if (pAd->CommonCfg.bWiFiTest &&
7399 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7400 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7402 // Tuning for TGn Wi-Fi 5.2.32
7403 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
7404 if (STA_TGN_WIFI_ON(pAd) &&
7405 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7407 AifsnCsr.field.Aifsn0 = 3;
7408 AifsnCsr.field.Aifsn2 = 7;
7412 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7414 #endif // CONFIG_STA_SUPPORT //
7416 #ifdef CONFIG_STA_SUPPORT
7417 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7418 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7420 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7422 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7423 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7426 #endif // CONFIG_STA_SUPPORT //
7427 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7429 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7432 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7433 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7434 pEdcaParm->Aifsn[0],
7435 pEdcaParm->Cwmin[0],
7436 pEdcaParm->Cwmax[0],
7437 pEdcaParm->Txop[0]<<5,
7438 pEdcaParm->bACM[0]));
7439 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7440 pEdcaParm->Aifsn[1],
7441 pEdcaParm->Cwmin[1],
7442 pEdcaParm->Cwmax[1],
7443 pEdcaParm->Txop[1]<<5,
7444 pEdcaParm->bACM[1]));
7445 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7446 pEdcaParm->Aifsn[2],
7447 pEdcaParm->Cwmin[2],
7448 pEdcaParm->Cwmax[2],
7449 pEdcaParm->Txop[2]<<5,
7450 pEdcaParm->bACM[2]));
7451 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7452 pEdcaParm->Aifsn[3],
7453 pEdcaParm->Cwmin[3],
7454 pEdcaParm->Cwmax[3],
7455 pEdcaParm->Txop[3]<<5,
7456 pEdcaParm->bACM[3]));
7462 ==========================================================================
7465 IRQL = PASSIVE_LEVEL
7466 IRQL = DISPATCH_LEVEL
7468 ==========================================================================
7470 VOID AsicSetSlotTime(
7471 IN PRTMP_ADAPTER pAd,
7472 IN BOOLEAN bUseShortSlotTime)
7475 UINT32 RegValue = 0;
7477 #ifdef CONFIG_STA_SUPPORT
7478 if (pAd->CommonCfg.Channel > 14)
7479 bUseShortSlotTime = TRUE;
7480 #endif // CONFIG_STA_SUPPORT //
7482 if (bUseShortSlotTime)
7483 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7485 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7487 SlotTime = (bUseShortSlotTime)? 9 : 20;
7489 #ifdef CONFIG_STA_SUPPORT
7490 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7492 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7493 if (pAd->CommonCfg.bEnableTxBurst)
7496 #endif // CONFIG_STA_SUPPORT //
7499 // For some reasons, always set it to short slot time.
7501 // ToDo: Should consider capability with 11B
7503 #ifdef CONFIG_STA_SUPPORT
7504 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7506 if (pAd->StaCfg.BssType == BSS_ADHOC)
7509 #endif // CONFIG_STA_SUPPORT //
7511 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7512 RegValue = RegValue & 0xFFFFFF00;
7514 RegValue |= SlotTime;
7516 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7520 ========================================================================
7522 Add Shared key information into ASIC.
7523 Update shared key, TxMic and RxMic to Asic Shared key table
7524 Update its cipherAlg to Asic Shared key Mode.
7527 ========================================================================
7529 VOID AsicAddSharedKeyEntry(
7530 IN PRTMP_ADAPTER pAd,
7538 ULONG offset; //, csr0;
7539 SHAREDKEY_MODE_STRUC csr1;
7541 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7542 //============================================================================================
7544 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7545 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7546 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]));
7549 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7550 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7554 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7555 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7557 //============================================================================================
7559 // fill key material - key + TX MIC + RX MIC
7564 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7565 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7567 offset += MAX_LEN_OF_SHARE_KEY;
7570 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7576 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7582 // Update cipher algorithm. WSTA always use BSS0
7584 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7585 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7586 if ((BssIndex%2) == 0)
7589 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7590 else if (KeyIdx == 1)
7591 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7592 else if (KeyIdx == 2)
7593 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7595 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7600 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7601 else if (KeyIdx == 1)
7602 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7603 else if (KeyIdx == 2)
7604 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7606 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7608 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7609 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7613 // IRQL = DISPATCH_LEVEL
7614 VOID AsicRemoveSharedKeyEntry(
7615 IN PRTMP_ADAPTER pAd,
7620 SHAREDKEY_MODE_STRUC csr1;
7622 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7624 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7625 if ((BssIndex%2) == 0)
7628 csr1.field.Bss0Key0CipherAlg = 0;
7629 else if (KeyIdx == 1)
7630 csr1.field.Bss0Key1CipherAlg = 0;
7631 else if (KeyIdx == 2)
7632 csr1.field.Bss0Key2CipherAlg = 0;
7634 csr1.field.Bss0Key3CipherAlg = 0;
7639 csr1.field.Bss1Key0CipherAlg = 0;
7640 else if (KeyIdx == 1)
7641 csr1.field.Bss1Key1CipherAlg = 0;
7642 else if (KeyIdx == 2)
7643 csr1.field.Bss1Key2CipherAlg = 0;
7645 csr1.field.Bss1Key3CipherAlg = 0;
7647 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7648 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7649 ASSERT(BssIndex < 4);
7655 VOID AsicUpdateWCIDAttribute(
7656 IN PRTMP_ADAPTER pAd,
7660 IN BOOLEAN bUsePairewiseKeyTable)
7662 ULONG WCIDAttri = 0, offset;
7665 // Update WCID attribute.
7666 // Only TxKey could update WCID attribute.
7668 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7669 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7670 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7673 VOID AsicUpdateWCIDIVEIV(
7674 IN PRTMP_ADAPTER pAd,
7681 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7683 RTMP_IO_WRITE32(pAd, offset, uIV);
7684 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7687 VOID AsicUpdateRxWCIDTable(
7688 IN PRTMP_ADAPTER pAd,
7695 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7696 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7697 RTMP_IO_WRITE32(pAd, offset, Addr);
7698 Addr = pAddr[4] + (pAddr[5] << 8);
7699 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7704 ========================================================================
7706 Routine Description:
7707 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7710 pAd Pointer to our adapter
7711 WCID WCID Entry number.
7712 BssIndex BSSID index, station or none multiple BSSID support
7713 this value should be 0.
7714 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7715 pCipherKey Pointer to Cipher Key.
7716 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7717 otherwise PairewiseKey table
7718 bTxKey This is the transmit key if enabled.
7724 This routine will set the relative key stuff to Asic including WCID attribute,
7725 Cipher Key, Cipher algorithm and IV/EIV.
7727 IV/EIV will be update if this CipherKey is the transmission key because
7728 ASIC will base on IV's KeyID value to select Cipher Key.
7730 If bTxKey sets to FALSE, this is not the TX key, but it could be
7733 For AP mode bTxKey must be always set to TRUE.
7734 ========================================================================
7736 VOID AsicAddKeyEntry(
7737 IN PRTMP_ADAPTER pAd,
7741 IN PCIPHER_KEY pCipherKey,
7742 IN BOOLEAN bUsePairewiseKeyTable,
7746 // ULONG WCIDAttri = 0;
7748 PUCHAR pKey = pCipherKey->Key;
7749 // ULONG KeyLen = pCipherKey->KeyLen;
7750 PUCHAR pTxMic = pCipherKey->TxMic;
7751 PUCHAR pRxMic = pCipherKey->RxMic;
7752 PUCHAR pTxtsc = pCipherKey->TxTsc;
7753 UCHAR CipherAlg = pCipherKey->CipherAlg;
7754 SHAREDKEY_MODE_STRUC csr1;
7756 // ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY);
7758 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7760 // 1.) decide key table offset
7762 if (bUsePairewiseKeyTable)
7763 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7765 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7768 // 2.) Set Key to Asic
7770 //for (i = 0; i < KeyLen; i++)
7773 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7774 offset += MAX_LEN_OF_PEER_KEY;
7777 // 3.) Set MIC key if available
7781 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7783 offset += LEN_TKIP_TXMICK;
7787 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7792 // 4.) Modify IV/EIV if needs
7793 // This will force Asic to use this key ID by setting IV.
7804 IV4 = (KeyIdx << 6);
7805 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7806 IV4 |= 0x20; // turn on extension bit means EIV existence
7808 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7809 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7815 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7817 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7820 if (!bUsePairewiseKeyTable)
7823 // Only update the shared key security mode
7825 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7826 if ((BssIndex % 2) == 0)
7829 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7830 else if (KeyIdx == 1)
7831 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7832 else if (KeyIdx == 2)
7833 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7835 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7840 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7841 else if (KeyIdx == 1)
7842 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7843 else if (KeyIdx == 2)
7844 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7846 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7848 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7851 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7856 ========================================================================
7858 Add Pair-wise key material into ASIC.
7859 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7862 ========================================================================
7864 VOID AsicAddPairwiseKeyEntry(
7865 IN PRTMP_ADAPTER pAd,
7868 IN CIPHER_KEY *pCipherKey)
7872 PUCHAR pKey = pCipherKey->Key;
7873 PUCHAR pTxMic = pCipherKey->TxMic;
7874 PUCHAR pRxMic = pCipherKey->RxMic;
7876 UCHAR CipherAlg = pCipherKey->CipherAlg;
7880 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7882 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7884 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7887 RTMP_IO_READ32(pAd, offset + i, &Value);
7890 offset += MAX_LEN_OF_PEER_KEY;
7896 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7903 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7907 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7908 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7909 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]));
7912 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7913 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7917 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7918 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7922 ========================================================================
7924 Remove Pair-wise key material from ASIC.
7927 ========================================================================
7929 VOID AsicRemovePairwiseKeyEntry(
7930 IN PRTMP_ADAPTER pAd,
7937 // re-set the entry's WCID attribute as OPEN-NONE.
7938 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7939 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7940 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7943 BOOLEAN AsicSendCommandToMcu(
7944 IN PRTMP_ADAPTER pAd,
7950 HOST_CMD_CSR_STRUC H2MCmd;
7951 H2M_MAILBOX_STRUC H2MMailbox;
7955 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7956 if (H2MMailbox.field.Owner == 0)
7965 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7971 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7972 H2MMailbox.field.CmdToken = Token;
7973 H2MMailbox.field.HighByte = Arg1;
7974 H2MMailbox.field.LowByte = Arg0;
7975 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7978 H2MCmd.field.HostCommand = Command;
7979 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7981 if (Command != 0x80)
7990 ========================================================================
7992 Routine Description:
7993 Verify the support rate for different PHY type
7996 pAd Pointer to our adapter
8001 IRQL = PASSIVE_LEVEL
8003 ========================================================================
8005 VOID RTMPCheckRates(
8006 IN PRTMP_ADAPTER pAd,
8007 IN OUT UCHAR SupRate[],
8008 IN OUT UCHAR *SupRateLen)
8010 UCHAR RateIdx, i, j;
8011 UCHAR NewRate[12], NewRateLen;
8015 if (pAd->CommonCfg.PhyMode == PHY_11B)
8020 // Check for support rates exclude basic rate bit
8021 for (i = 0; i < *SupRateLen; i++)
8022 for (j = 0; j < RateIdx; j++)
8023 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8024 NewRate[NewRateLen++] = SupRate[i];
8026 *SupRateLen = NewRateLen;
8027 NdisMoveMemory(SupRate, NewRate, NewRateLen);
8030 #ifdef CONFIG_STA_SUPPORT
8031 #ifdef DOT11_N_SUPPORT
8032 BOOLEAN RTMPCheckChannel(
8033 IN PRTMP_ADAPTER pAd,
8034 IN UCHAR CentralChannel,
8038 UCHAR UpperChannel = 0, LowerChannel = 0;
8039 UCHAR NoEffectChannelinList = 0;
8041 // Find upper and lower channel according to 40MHz current operation.
8042 if (CentralChannel < Channel)
8044 UpperChannel = Channel;
8045 if (CentralChannel > 2)
8046 LowerChannel = CentralChannel - 2;
8050 else if (CentralChannel > Channel)
8052 UpperChannel = CentralChannel + 2;
8053 LowerChannel = Channel;
8056 for (k = 0;k < pAd->ChannelListNum;k++)
8058 if (pAd->ChannelList[k].Channel == UpperChannel)
8060 NoEffectChannelinList ++;
8062 if (pAd->ChannelList[k].Channel == LowerChannel)
8064 NoEffectChannelinList ++;
8068 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
8069 if (NoEffectChannelinList == 2)
8076 ========================================================================
8078 Routine Description:
8079 Verify the support rate for HT phy type
8082 pAd Pointer to our adapter
8085 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
8087 IRQL = PASSIVE_LEVEL
8089 ========================================================================
8091 BOOLEAN RTMPCheckHt(
8092 IN PRTMP_ADAPTER pAd,
8094 IN HT_CAPABILITY_IE *pHtCapability,
8095 IN ADD_HT_INFO_IE *pAddHtInfo)
8097 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
8100 // If use AMSDU, set flag.
8101 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
8102 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
8103 // Save Peer Capability
8104 if (pHtCapability->HtCapInfo.ShortGIfor20)
8105 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
8106 if (pHtCapability->HtCapInfo.ShortGIfor40)
8107 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
8108 if (pHtCapability->HtCapInfo.TxSTBC)
8109 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
8110 if (pHtCapability->HtCapInfo.RxSTBC)
8111 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
8112 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
8114 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
8117 if (Wcid < MAX_LEN_OF_MAC_TABLE)
8119 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
8122 // Will check ChannelWidth for MCSSet[4] below
8123 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
8124 switch (pAd->CommonCfg.RxStream)
8127 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8128 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
8129 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
8130 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8133 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8134 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
8135 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
8136 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8139 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8140 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
8141 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
8142 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8146 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
8148 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
8149 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
8150 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
8152 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
8154 // Send Assoc Req with my HT capability.
8155 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
8156 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
8157 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
8158 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
8159 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
8160 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
8161 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
8162 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
8163 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8164 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8165 if (pAd->CommonCfg.bRdg)
8167 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
8168 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
8171 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
8172 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
8174 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
8177 #endif // DOT11_N_SUPPORT //
8178 #endif // CONFIG_STA_SUPPORT //
8181 ========================================================================
8183 Routine Description:
8184 Verify the support rate for different PHY type
8187 pAd Pointer to our adapter
8192 IRQL = PASSIVE_LEVEL
8194 ========================================================================
8196 VOID RTMPUpdateMlmeRate(
8197 IN PRTMP_ADAPTER pAd)
8200 UCHAR ProperMlmeRate; //= RATE_54;
8201 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
8202 BOOLEAN bMatch = FALSE;
8204 switch (pAd->CommonCfg.PhyMode)
8207 ProperMlmeRate = RATE_11;
8208 MinimumRate = RATE_1;
8210 case PHY_11BG_MIXED:
8211 #ifdef DOT11_N_SUPPORT
8212 case PHY_11ABGN_MIXED:
8213 case PHY_11BGN_MIXED:
8214 #endif // DOT11_N_SUPPORT //
8215 if ((pAd->MlmeAux.SupRateLen == 4) &&
8216 (pAd->MlmeAux.ExtRateLen == 0))
8218 ProperMlmeRate = RATE_11;
8220 ProperMlmeRate = RATE_24;
8222 if (pAd->MlmeAux.Channel <= 14)
8223 MinimumRate = RATE_1;
8225 MinimumRate = RATE_6;
8228 #ifdef DOT11_N_SUPPORT
8229 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
8230 case PHY_11GN_MIXED:
8231 case PHY_11AGN_MIXED:
8232 case PHY_11AN_MIXED:
8234 #endif // DOT11_N_SUPPORT //
8235 ProperMlmeRate = RATE_24;
8236 MinimumRate = RATE_6;
8238 case PHY_11ABG_MIXED:
8239 ProperMlmeRate = RATE_24;
8240 if (pAd->MlmeAux.Channel <= 14)
8241 MinimumRate = RATE_1;
8243 MinimumRate = RATE_6;
8246 ProperMlmeRate = RATE_1;
8247 MinimumRate = RATE_1;
8251 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8253 for (j = 0; j < RateIdx; j++)
8255 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8257 if (j == ProperMlmeRate)
8269 if (bMatch == FALSE)
8271 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8273 for (j = 0; j < RateIdx; j++)
8275 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8277 if (j == ProperMlmeRate)
8290 if (bMatch == FALSE)
8292 ProperMlmeRate = MinimumRate;
8295 pAd->CommonCfg.MlmeRate = MinimumRate;
8296 pAd->CommonCfg.RtsRate = ProperMlmeRate;
8297 if (pAd->CommonCfg.MlmeRate >= RATE_6)
8299 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8300 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8301 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8302 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8306 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8307 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8308 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8309 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8312 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8316 IN PRTMP_ADAPTER pAd,
8323 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8328 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8330 larger = max(Rssi0, Rssi1);
8333 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8335 larger = max(larger, Rssi2);
8345 // Antenna divesity use GPIO3 and EESK pin for control
8346 // Antenna and EEPROM access are both using EESK pin,
8347 // Therefor we should avoid accessing EESK at the same time
8348 // Then restore antenna after EEPROM access
8350 IN PRTMP_ADAPTER pAd,
8357 if ((pAd->EepromAccess) ||
8358 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
8359 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
8360 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
8361 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8366 // the antenna selection is through firmware and MAC register(GPIO3)
8370 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8372 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8374 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8376 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8377 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8382 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8384 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8386 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8389 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8390 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8397 ========================================================================
8398 Routine Description:
8399 Periodic evaluate antenna link status
8402 pAd - Adapter pointer
8407 ========================================================================
8409 VOID AsicEvaluateRxAnt(
8410 IN PRTMP_ADAPTER pAd)
8417 #endif // RALINK_ATE //
8419 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8420 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8421 fRTMP_ADAPTER_RADIO_OFF |
8422 fRTMP_ADAPTER_NIC_NOT_EXIST |
8423 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
8424 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8426 || (pAd->EepromAccess)
8432 #ifdef CONFIG_STA_SUPPORT
8433 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8435 //if (pAd->StaCfg.Psm == PWR_SAVE)
8438 #endif // CONFIG_STA_SUPPORT //
8440 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8441 // one is antenna diversity:there is only one antenna can rx and tx
8442 // the other is failed antenna remove:two physical antenna can rx and tx
8443 if (pAd->NicConfig2.field.AntDiversity)
8445 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8446 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8448 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8450 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8451 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8452 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8454 // a one-shot timer to end the evalution
8455 // dynamic adjust antenna evaluation period according to the traffic
8456 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8457 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8459 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8464 #ifdef CONFIG_STA_SUPPORT
8465 if (pAd->StaCfg.Psm == PWR_SAVE)
8467 #endif // CONFIG_STA_SUPPORT //
8469 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8471 if(pAd->Antenna.field.RxPath == 3)
8475 else if(pAd->Antenna.field.RxPath == 2)
8479 else if(pAd->Antenna.field.RxPath == 1)
8483 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8484 #ifdef CONFIG_STA_SUPPORT
8485 #endif // CONFIG_STA_SUPPORT //
8486 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8489 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8490 pAd->RalinkCounters.OneSecTxRetryOkCount +
8491 pAd->RalinkCounters.OneSecTxFailCount;
8493 // dynamic adjust antenna evaluation period according to the traffic
8494 if (TxTotalCnt > 50)
8496 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8497 pAd->Mlme.bLowThroughput = FALSE;
8501 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8502 pAd->Mlme.bLowThroughput = TRUE;
8509 ========================================================================
8510 Routine Description:
8511 After evaluation, check antenna link status
8514 pAd - Adapter pointer
8519 ========================================================================
8521 VOID AsicRxAntEvalTimeout(
8522 IN PVOID SystemSpecific1,
8523 IN PVOID FunctionContext,
8524 IN PVOID SystemSpecific2,
8525 IN PVOID SystemSpecific3)
8527 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8528 #ifdef CONFIG_STA_SUPPORT
8530 CHAR larger = -127, rssi0, rssi1, rssi2;
8531 #endif // CONFIG_STA_SUPPORT //
8536 #endif // RALINK_ATE //
8538 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8539 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8540 fRTMP_ADAPTER_RADIO_OFF |
8541 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
8542 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8544 || (pAd->EepromAccess)
8550 #ifdef CONFIG_STA_SUPPORT
8551 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8553 //if (pAd->StaCfg.Psm == PWR_SAVE)
8556 if (pAd->NicConfig2.field.AntDiversity)
8558 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8563 // select PrimaryRxAntPair
8564 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8565 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8567 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8568 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8569 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8571 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8572 pAd->RxAnt.EvaluateStableCnt = 0;
8576 // if the evaluated antenna is not better than original, switch back to original antenna
8577 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8578 pAd->RxAnt.EvaluateStableCnt ++;
8581 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8583 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8584 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8588 if (pAd->StaCfg.Psm == PWR_SAVE)
8591 // if the traffic is low, use average rssi as the criteria
8592 if (pAd->Mlme.bLowThroughput == TRUE)
8594 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8595 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8596 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8600 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8601 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8602 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8605 if(pAd->Antenna.field.RxPath == 3)
8607 larger = max(rssi0, rssi1);
8609 if (larger > (rssi2 + 20))
8610 pAd->Mlme.RealRxPath = 2;
8612 pAd->Mlme.RealRxPath = 3;
8614 else if(pAd->Antenna.field.RxPath == 2)
8616 if (rssi0 > (rssi1 + 20))
8617 pAd->Mlme.RealRxPath = 1;
8619 pAd->Mlme.RealRxPath = 2;
8622 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8624 if(pAd->Mlme.RealRxPath == 3)
8628 else if(pAd->Mlme.RealRxPath == 2)
8632 else if(pAd->Mlme.RealRxPath == 1)
8636 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8640 #endif // CONFIG_STA_SUPPORT //
8646 VOID APSDPeriodicExec(
8647 IN PVOID SystemSpecific1,
8648 IN PVOID FunctionContext,
8649 IN PVOID SystemSpecific2,
8650 IN PVOID SystemSpecific3)
8652 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8654 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8657 pAd->CommonCfg.TriggerTimerCount++;
8659 // Driver should not send trigger frame, it should be send by application layer
8661 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
8662 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
8663 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
8665 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
8666 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
8667 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
8668 pAd->CommonCfg.TriggerTimerCount = 0;
8669 pAd->CommonCfg.bInServicePeriod = TRUE;
8674 ========================================================================
8675 Routine Description:
8676 Set/reset MAC registers according to bPiggyBack parameter
8679 pAd - Adapter pointer
8680 bPiggyBack - Enable / Disable Piggy-Back
8685 ========================================================================
8687 VOID RTMPSetPiggyBack(
8688 IN PRTMP_ADAPTER pAd,
8689 IN BOOLEAN bPiggyBack)
8691 TX_LINK_CFG_STRUC TxLinkCfg;
8693 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8695 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8696 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8700 ========================================================================
8701 Routine Description:
8702 check if this entry need to switch rate automatically
8712 ========================================================================
8714 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8715 IN PRTMP_ADAPTER pAd,
8716 IN PMAC_TABLE_ENTRY pEntry)
8718 BOOLEAN result = TRUE;
8721 #ifdef CONFIG_STA_SUPPORT
8722 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8724 // only associated STA counts
8725 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8727 result = pAd->StaCfg.bAutoTxRateSwitch;
8732 #endif // CONFIG_STA_SUPPORT //
8740 BOOLEAN RTMPAutoRateSwitchCheck(
8741 IN PRTMP_ADAPTER pAd)
8744 #ifdef CONFIG_STA_SUPPORT
8745 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8747 if (pAd->StaCfg.bAutoTxRateSwitch)
8750 #endif // CONFIG_STA_SUPPORT //
8756 ========================================================================
8757 Routine Description:
8758 check if this entry need to fix tx legacy rate
8768 ========================================================================
8770 UCHAR RTMPStaFixedTxMode(
8771 IN PRTMP_ADAPTER pAd,
8772 IN PMAC_TABLE_ENTRY pEntry)
8774 UCHAR tx_mode = FIXED_TXMODE_HT;
8777 #ifdef CONFIG_STA_SUPPORT
8778 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8780 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8782 #endif // CONFIG_STA_SUPPORT //
8788 ========================================================================
8789 Routine Description:
8790 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8800 ========================================================================
8802 VOID RTMPUpdateLegacyTxSetting(
8803 UCHAR fixed_tx_mode,
8804 PMAC_TABLE_ENTRY pEntry)
8806 HTTRANSMIT_SETTING TransmitSetting;
8808 if (fixed_tx_mode == FIXED_TXMODE_HT)
8811 TransmitSetting.word = 0;
8813 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8814 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8816 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8818 TransmitSetting.field.MODE = MODE_CCK;
8819 // CCK mode allow MCS 0~3
8820 if (TransmitSetting.field.MCS > MCS_3)
8821 TransmitSetting.field.MCS = MCS_3;
8825 TransmitSetting.field.MODE = MODE_OFDM;
8826 // OFDM mode allow MCS 0~7
8827 if (TransmitSetting.field.MCS > MCS_7)
8828 TransmitSetting.field.MCS = MCS_7;
8831 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8833 pEntry->HTPhyMode.word = TransmitSetting.word;
8834 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8835 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8839 #ifdef CONFIG_STA_SUPPORT
8841 ==========================================================================
8843 dynamic tune BBP R66 to find a balance between sensibility and
8846 IRQL = DISPATCH_LEVEL
8848 ==========================================================================
8850 VOID AsicStaBbpTuning(
8851 IN PRTMP_ADAPTER pAd)
8853 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8856 // 2860C did not support Fase CCA, therefore can't tune
8857 if (pAd->MACVersion == 0x28600100)
8863 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8866 if ((pAd->OpMode == OPMODE_STA)
8867 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8869 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8872 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8875 if (pAd->Antenna.field.RxPath > 1)
8876 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8878 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8880 if (pAd->LatchRfRegs.Channel <= 14)
8883 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8884 // Otherwise, it will have some throughput side effect when low RSSI
8887 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8889 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8890 if (OrigR66Value != R66)
8892 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8897 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8898 if (OrigR66Value != R66)
8900 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8907 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8909 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8910 if (OrigR66Value != R66)
8912 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8917 R66 = 0x2E + GET_LNA_GAIN(pAd);
8918 if (OrigR66Value != R66)
8920 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8928 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8930 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8932 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8933 if (OrigR66Value != R66)
8935 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8940 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8941 if (OrigR66Value != R66)
8943 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8949 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8951 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8952 if (OrigR66Value != R66)
8954 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8959 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8960 if (OrigR66Value != R66)
8962 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8971 #endif // CONFIG_STA_SUPPORT //
8973 VOID RTMPSetAGCInitValue(
8974 IN PRTMP_ADAPTER pAd,
8979 if (pAd->LatchRfRegs.Channel <= 14)
8981 R66 = 0x2E + GET_LNA_GAIN(pAd);
8982 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8986 if (BandWidth == BW_20)
8988 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8989 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8991 #ifdef DOT11_N_SUPPORT
8994 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8995 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8997 #endif // DOT11_N_SUPPORT //
9002 VOID AsicTurnOffRFClk(
9003 IN PRTMP_ADAPTER pAd,
9007 UINT32 R1 = 0, R2 = 0, R3 = 0;
9009 RTMP_RF_REGS *RFRegTable;
9012 // The RF programming sequence is difference between 3xxx and 2xxx
9015 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
9020 RFRegTable = RF2850RegTable;
9022 switch (pAd->RfIcType)
9029 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9031 if (Channel == RFRegTable[index].Channel)
9033 R1 = RFRegTable[index].R1 & 0xffffdfff;
9034 R2 = RFRegTable[index].R2 & 0xfffbffff;
9035 R3 = RFRegTable[index].R3 & 0xfff3ffff;
9037 RTMP_RF_IO_WRITE32(pAd, R1);
9038 RTMP_RF_IO_WRITE32(pAd, R2);
9040 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
9041 // Set RF R2 bit18=0, R3 bit[18:19]=0
9042 //if (pAd->StaCfg.bRadio == FALSE)
9045 RTMP_RF_IO_WRITE32(pAd, R3);
9047 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
9048 Channel, pAd->RfIcType, R2, R3));
9051 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
9052 Channel, pAd->RfIcType, R2));
9068 VOID AsicTurnOnRFClk(
9069 IN PRTMP_ADAPTER pAd,
9073 UINT32 R1 = 0, R2 = 0, R3 = 0;
9075 RTMP_RF_REGS *RFRegTable;
9078 // The RF programming sequence is difference between 3xxx and 2xxx
9085 RFRegTable = RF2850RegTable;
9087 switch (pAd->RfIcType)
9094 for (index = 0; index < NUM_OF_2850_CHNL; index++)
9096 if (Channel == RFRegTable[index].Channel)
9098 R3 = pAd->LatchRfRegs.R3;
9101 RTMP_RF_IO_WRITE32(pAd, R3);
9103 R1 = RFRegTable[index].R1;
9104 RTMP_RF_IO_WRITE32(pAd, R1);
9106 R2 = RFRegTable[index].R2;
9107 if (pAd->Antenna.field.TxPath == 1)
9109 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
9112 if (pAd->Antenna.field.RxPath == 2)
9114 R2 |= 0x40; // write 1 to off Rxpath.
9116 else if (pAd->Antenna.field.RxPath == 1)
9118 R2 |= 0x20040; // write 1 to off RxPath
9120 RTMP_RF_IO_WRITE32(pAd, R2);