2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-08-25 Modify from RT2500 code base
36 John Chang 2004-09-06 modified for RT2600
39 #include "../rt_config.h"
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
44 UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45 UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
46 UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
47 UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
48 UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
49 UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
50 UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
51 UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
52 UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
53 #ifdef CONFIG_STA_SUPPORT
54 #ifdef DOT11_N_SUPPORT
55 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
56 #endif // DOT11_N_SUPPORT //
57 #endif // CONFIG_STA_SUPPORT //
59 UCHAR RateSwitchTable[] = {
60 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
61 0x11, 0x00, 0, 0, 0, // Initial used item after association
62 0x00, 0x00, 0, 40, 101,
63 0x01, 0x00, 1, 40, 50,
64 0x02, 0x00, 2, 35, 45,
65 0x03, 0x00, 3, 20, 45,
66 0x04, 0x21, 0, 30, 50,
67 0x05, 0x21, 1, 20, 50,
68 0x06, 0x21, 2, 20, 50,
69 0x07, 0x21, 3, 15, 50,
70 0x08, 0x21, 4, 15, 30,
71 0x09, 0x21, 5, 10, 25,
74 0x0c, 0x20, 12, 15, 30,
75 0x0d, 0x20, 13, 8, 20,
76 0x0e, 0x20, 14, 8, 20,
77 0x0f, 0x20, 15, 8, 25,
78 0x10, 0x22, 15, 8, 25,
96 UCHAR RateSwitchTable11B[] = {
97 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
98 0x04, 0x03, 0, 0, 0, // Initial used item after association
99 0x00, 0x00, 0, 40, 101,
100 0x01, 0x00, 1, 40, 50,
101 0x02, 0x00, 2, 35, 45,
102 0x03, 0x00, 3, 20, 45,
105 UCHAR RateSwitchTable11BG[] = {
106 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
107 0x0a, 0x00, 0, 0, 0, // Initial used item after association
108 0x00, 0x00, 0, 40, 101,
109 0x01, 0x00, 1, 40, 50,
110 0x02, 0x00, 2, 35, 45,
111 0x03, 0x00, 3, 20, 45,
112 0x04, 0x10, 2, 20, 35,
113 0x05, 0x10, 3, 16, 35,
114 0x06, 0x10, 4, 10, 25,
115 0x07, 0x10, 5, 16, 25,
116 0x08, 0x10, 6, 10, 25,
117 0x09, 0x10, 7, 10, 13,
120 UCHAR RateSwitchTable11G[] = {
121 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
122 0x08, 0x00, 0, 0, 0, // Initial used item after association
123 0x00, 0x10, 0, 20, 101,
124 0x01, 0x10, 1, 20, 35,
125 0x02, 0x10, 2, 20, 35,
126 0x03, 0x10, 3, 16, 35,
127 0x04, 0x10, 4, 10, 25,
128 0x05, 0x10, 5, 16, 25,
129 0x06, 0x10, 6, 10, 25,
130 0x07, 0x10, 7, 10, 13,
133 #ifdef DOT11_N_SUPPORT
134 UCHAR RateSwitchTable11N1S[] = {
135 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
136 0x09, 0x00, 0, 0, 0, // Initial used item after association
137 0x00, 0x21, 0, 30, 101,
138 0x01, 0x21, 1, 20, 50,
139 0x02, 0x21, 2, 20, 50,
140 0x03, 0x21, 3, 15, 50,
141 0x04, 0x21, 4, 15, 30,
142 0x05, 0x21, 5, 10, 25,
143 0x06, 0x21, 6, 8, 14,
144 0x07, 0x21, 7, 8, 14,
145 0x08, 0x23, 7, 8, 14,
148 UCHAR RateSwitchTable11N2S[] = {
149 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
150 0x0a, 0x00, 0, 0, 0, // Initial used item after association
151 0x00, 0x21, 0, 30, 101,
152 0x01, 0x21, 1, 20, 50,
153 0x02, 0x21, 2, 20, 50,
154 0x03, 0x21, 3, 15, 50,
155 0x04, 0x21, 4, 15, 30,
156 0x05, 0x20, 12, 15, 30,
157 0x06, 0x20, 13, 8, 20,
158 0x07, 0x20, 14, 8, 20,
159 0x08, 0x20, 15, 8, 25,
160 0x09, 0x22, 15, 8, 25,
163 UCHAR RateSwitchTable11N3S[] = {
164 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
165 0x0a, 0x00, 0, 0, 0, // Initial used item after association
166 0x00, 0x21, 0, 30, 101,
167 0x01, 0x21, 1, 20, 50,
168 0x02, 0x21, 2, 20, 50,
169 0x03, 0x21, 3, 15, 50,
170 0x04, 0x21, 4, 15, 30,
171 0x05, 0x20, 12, 15, 30,
172 0x06, 0x20, 13, 8, 20,
173 0x07, 0x20, 14, 8, 20,
174 0x08, 0x20, 15, 8, 25,
175 0x09, 0x22, 15, 8, 25,
178 UCHAR RateSwitchTable11N2SForABand[] = {
179 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
180 0x0b, 0x09, 0, 0, 0, // Initial used item after association
181 0x00, 0x21, 0, 30, 101,
182 0x01, 0x21, 1, 20, 50,
183 0x02, 0x21, 2, 20, 50,
184 0x03, 0x21, 3, 15, 50,
185 0x04, 0x21, 4, 15, 30,
186 0x05, 0x21, 5, 15, 30,
187 0x06, 0x20, 12, 15, 30,
188 0x07, 0x20, 13, 8, 20,
189 0x08, 0x20, 14, 8, 20,
190 0x09, 0x20, 15, 8, 25,
191 0x0a, 0x22, 15, 8, 25,
194 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
195 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
196 0x0b, 0x09, 0, 0, 0, // Initial used item after association
197 0x00, 0x21, 0, 30, 101,
198 0x01, 0x21, 1, 20, 50,
199 0x02, 0x21, 2, 20, 50,
200 0x03, 0x21, 3, 15, 50,
201 0x04, 0x21, 4, 15, 30,
202 0x05, 0x21, 5, 15, 30,
203 0x06, 0x20, 12, 15, 30,
204 0x07, 0x20, 13, 8, 20,
205 0x08, 0x20, 14, 8, 20,
206 0x09, 0x20, 15, 8, 25,
207 0x0a, 0x22, 15, 8, 25,
210 UCHAR RateSwitchTable11BGN1S[] = {
211 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
212 0x0d, 0x00, 0, 0, 0, // Initial used item after association
213 0x00, 0x00, 0, 40, 101,
214 0x01, 0x00, 1, 40, 50,
215 0x02, 0x00, 2, 35, 45,
216 0x03, 0x00, 3, 20, 45,
217 0x04, 0x21, 0, 30,101, //50
218 0x05, 0x21, 1, 20, 50,
219 0x06, 0x21, 2, 20, 50,
220 0x07, 0x21, 3, 15, 50,
221 0x08, 0x21, 4, 15, 30,
222 0x09, 0x21, 5, 10, 25,
223 0x0a, 0x21, 6, 8, 14,
224 0x0b, 0x21, 7, 8, 14,
225 0x0c, 0x23, 7, 8, 14,
228 UCHAR RateSwitchTable11BGN2S[] = {
229 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
230 0x0a, 0x00, 0, 0, 0, // Initial used item after association
231 0x00, 0x21, 0, 30,101, //50
232 0x01, 0x21, 1, 20, 50,
233 0x02, 0x21, 2, 20, 50,
234 0x03, 0x21, 3, 15, 50,
235 0x04, 0x21, 4, 15, 30,
236 0x05, 0x20, 12, 15, 30,
237 0x06, 0x20, 13, 8, 20,
238 0x07, 0x20, 14, 8, 20,
239 0x08, 0x20, 15, 8, 25,
240 0x09, 0x22, 15, 8, 25,
243 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
244 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
245 0x0a, 0x00, 0, 0, 0, // Initial used item after association
246 0x00, 0x21, 0, 30,101, //50
247 0x01, 0x21, 1, 20, 50,
248 0x02, 0x21, 2, 20, 50,
249 0x03, 0x21, 3, 20, 50,
250 0x04, 0x21, 4, 15, 50,
252 0x05, 0x20, 20, 15, 30,
253 0x06, 0x20, 21, 8, 20,
254 0x07, 0x20, 22, 8, 20,
255 0x08, 0x20, 23, 8, 25,
256 0x09, 0x22, 23, 8, 25,
257 #else // for RT2860 2*3 test
258 0x05, 0x20, 12, 15, 30,
259 0x06, 0x20, 13, 8, 20,
260 0x07, 0x20, 14, 8, 20,
261 0x08, 0x20, 15, 8, 25,
262 0x09, 0x22, 15, 8, 25,
266 UCHAR RateSwitchTable11BGN2SForABand[] = {
267 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
268 0x0b, 0x09, 0, 0, 0, // Initial used item after association
269 0x00, 0x21, 0, 30,101, //50
270 0x01, 0x21, 1, 20, 50,
271 0x02, 0x21, 2, 20, 50,
272 0x03, 0x21, 3, 15, 50,
273 0x04, 0x21, 4, 15, 30,
274 0x05, 0x21, 5, 15, 30,
275 0x06, 0x20, 12, 15, 30,
276 0x07, 0x20, 13, 8, 20,
277 0x08, 0x20, 14, 8, 20,
278 0x09, 0x20, 15, 8, 25,
279 0x0a, 0x22, 15, 8, 25,
282 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
283 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
284 0x0c, 0x09, 0, 0, 0, // Initial used item after association
285 0x00, 0x21, 0, 30,101, //50
286 0x01, 0x21, 1, 20, 50,
287 0x02, 0x21, 2, 20, 50,
288 0x03, 0x21, 3, 15, 50,
289 0x04, 0x21, 4, 15, 30,
290 0x05, 0x21, 5, 15, 30,
291 0x06, 0x21, 12, 15, 30,
292 0x07, 0x20, 20, 15, 30,
293 0x08, 0x20, 21, 8, 20,
294 0x09, 0x20, 22, 8, 20,
295 0x0a, 0x20, 23, 8, 25,
296 0x0b, 0x22, 23, 8, 25,
298 #endif // DOT11_N_SUPPORT //
300 PUCHAR ReasonString[] = {
302 /* 1 */ "Unspecified Reason",
303 /* 2 */ "Previous Auth no longer valid",
304 /* 3 */ "STA is leaving / has left",
305 /* 4 */ "DIS-ASSOC due to inactivity",
306 /* 5 */ "AP unable to hanle all associations",
307 /* 6 */ "class 2 error",
308 /* 7 */ "class 3 error",
309 /* 8 */ "STA is leaving / has left",
310 /* 9 */ "require auth before assoc/re-assoc",
314 /* 13 */ "invalid IE",
315 /* 14 */ "MIC error",
316 /* 15 */ "4-way handshake timeout",
317 /* 16 */ "2-way (group key) handshake timeout",
318 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
322 extern UCHAR OfdmRateToRxwiMCS[];
323 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
324 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
325 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
326 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
327 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
329 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
330 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
331 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
333 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
334 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
335 // clean environment.
336 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
337 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
339 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
340 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
342 UCHAR SsidIe = IE_SSID;
343 UCHAR SupRateIe = IE_SUPP_RATES;
344 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
345 #ifdef DOT11_N_SUPPORT
346 UCHAR HtCapIe = IE_HT_CAP;
347 UCHAR AddHtInfoIe = IE_ADD_HT;
348 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
350 UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
351 #endif // DOT11N_DRAFT3 //
352 #endif // DOT11_N_SUPPORT //
353 UCHAR ErpIe = IE_ERP;
354 UCHAR DsIe = IE_DS_PARM;
355 UCHAR TimIe = IE_TIM;
356 UCHAR WpaIe = IE_WPA;
357 UCHAR Wpa2Ie = IE_WPA2;
358 UCHAR IbssIe = IE_IBSS_PARM;
359 UCHAR Ccx2Ie = IE_CCX_V2;
360 UCHAR WapiIe = IE_WAPI;
362 extern UCHAR WPA_OUI[];
364 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
366 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
367 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
369 // Reset the RFIC setting to new series
370 RTMP_RF_REGS RF2850RegTable[] = {
371 // ch R1 R2 R3(TX0~4=0) R4
372 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
373 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
374 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
375 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
376 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
377 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
378 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
379 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
380 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
381 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
382 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
383 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
384 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
385 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
387 // 802.11 UNI / HyperLan 2
388 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
389 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
390 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
391 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
392 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
393 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
394 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
395 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
396 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
397 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
398 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
399 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
402 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
404 // 2008.04.30 modified
405 // The system team has AN to improve the EVM value
406 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
407 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
408 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
409 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
411 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
412 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
413 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
414 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
415 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
416 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
417 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
418 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
419 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
420 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
421 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
422 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
425 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
426 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
427 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
428 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
429 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
430 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
431 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
434 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
435 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
436 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
437 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
438 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
439 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
440 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
442 // still lack of MMAC(Japan) ch 34,38,42,46
444 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
446 FREQUENCY_ITEM FreqItems3020[] =
448 /**************************************************/
449 // ISM : 2.4 to 2.483 GHz //
450 /**************************************************/
452 /**************************************************/
453 //-CH---N-------R---K-----------
469 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
472 ==========================================================================
474 initialize the MLME task and its data structure (queue, spinlock,
475 timer, state machines).
480 always return NDIS_STATUS_SUCCESS
482 ==========================================================================
484 NDIS_STATUS MlmeInit(
485 IN PRTMP_ADAPTER pAd)
487 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
489 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
493 Status = MlmeQueueInit(&pAd->Mlme.Queue);
494 if(Status != NDIS_STATUS_SUCCESS)
497 pAd->Mlme.bRunning = FALSE;
498 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
500 #ifdef CONFIG_STA_SUPPORT
501 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
503 BssTableInit(&pAd->ScanTab);
505 // init STA state machines
506 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
507 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
508 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
509 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
510 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
511 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
513 #ifdef QOS_DLS_SUPPORT
514 DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc);
515 #endif // QOS_DLS_SUPPORT //
518 // Since we are using switch/case to implement it, the init is different from the above
519 // state machine init
520 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
522 #endif // CONFIG_STA_SUPPORT //
526 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
528 // Init mlme periodic timer
529 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
531 // Set mlme periodic timer
532 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
534 // software-based RX Antenna diversity
535 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
539 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
545 ==========================================================================
547 main loop of the MLME
549 Mlme has to be initialized, and there are something inside the queue
551 This function is invoked from MPSetInformation and MPReceive;
552 This task guarantee only one MlmeHandler will run.
554 IRQL = DISPATCH_LEVEL
556 ==========================================================================
559 IN PRTMP_ADAPTER pAd)
561 MLME_QUEUE_ELEM *Elem = NULL;
566 // Only accept MLME and Frame from peer side, no other (control/data) frame should
567 // get into this state machine
569 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
570 if(pAd->Mlme.bRunning)
572 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
577 pAd->Mlme.bRunning = TRUE;
579 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
581 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
583 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
584 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
585 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
587 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
594 DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n"));
597 #endif // RALINK_ATE //
599 //From message type, determine which state machine I should drive
600 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
603 if (Elem->MsgType == MT2_RESET_CONF)
605 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
606 MlmeRestartStateMachine(pAd);
607 Elem->Occupied = FALSE;
613 // if dequeue success
614 switch (Elem->Machine)
616 // STA state machines
617 #ifdef CONFIG_STA_SUPPORT
618 case ASSOC_STATE_MACHINE:
619 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
621 case AUTH_STATE_MACHINE:
622 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
624 case AUTH_RSP_STATE_MACHINE:
625 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
627 case SYNC_STATE_MACHINE:
628 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
630 case MLME_CNTL_STATE_MACHINE:
631 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
633 case WPA_PSK_STATE_MACHINE:
634 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
637 case LEAP_STATE_MACHINE:
638 LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
641 case AIRONET_STATE_MACHINE:
642 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
645 #ifdef QOS_DLS_SUPPORT
646 case DLS_STATE_MACHINE:
647 StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem);
649 #endif // QOS_DLS_SUPPORT //
650 #endif // CONFIG_STA_SUPPORT //
652 case ACTION_STATE_MACHINE:
653 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
660 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
665 Elem->Occupied = FALSE;
670 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
674 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
675 pAd->Mlme.bRunning = FALSE;
676 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
680 ==========================================================================
682 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
684 Adapter - NIC Adapter pointer
686 The MLME task will no longer work properly
690 ==========================================================================
693 IN PRTMP_ADAPTER pAd)
697 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
699 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
701 // disable BEACON generation and other BEACON related hardware timers
702 AsicDisableSync(pAd);
705 #ifdef CONFIG_STA_SUPPORT
706 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
708 #ifdef QOS_DLS_SUPPORT
710 #endif // QOS_DLS_SUPPORT //
711 // Cancel pending timers
712 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
713 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
714 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
715 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
716 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
717 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
719 #ifdef QOS_DLS_SUPPORT
720 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
722 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
724 #endif // QOS_DLS_SUPPORT //
726 #endif // CONFIG_STA_SUPPORT //
728 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
729 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
733 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
736 RTMPSetLED(pAd, LED_HALT);
737 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
740 LED_CFG_STRUC LedCfg;
741 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
742 LedCfg.field.LedPolar = 0;
743 LedCfg.field.RLedMode = 0;
744 LedCfg.field.GLedMode = 0;
745 LedCfg.field.YLedMode = 0;
746 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
751 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
753 MlmeQueueDestroy(&pAd->Mlme.Queue);
754 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
756 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
759 VOID MlmeResetRalinkCounters(
760 IN PRTMP_ADAPTER pAd)
762 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
763 // clear all OneSecxxx counters.
764 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
765 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
766 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
767 pAd->RalinkCounters.OneSecRxOkCnt = 0;
768 pAd->RalinkCounters.OneSecTxFailCount = 0;
769 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
770 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
771 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
773 // TODO: for debug only. to be removed
774 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
775 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
776 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
777 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
778 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
779 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
780 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
781 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
782 pAd->RalinkCounters.OneSecTxDoneCount = 0;
783 pAd->RalinkCounters.OneSecRxCount = 0;
784 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
785 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
790 unsigned long rx_AMSDU;
791 unsigned long rx_Total;
794 ==========================================================================
796 This routine is executed periodically to -
797 1. Decide if it's a right time to turn on PwrMgmt bit of all
799 2. Calculate ChannelQuality based on statistics of the last
800 period, so that TX rate won't toggling very frequently between a
801 successful TX and a failed TX.
802 3. If the calculated ChannelQuality indicated current connection not
803 healthy, then a ROAMing attempt is tried here.
805 IRQL = DISPATCH_LEVEL
807 ==========================================================================
809 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
810 VOID MlmePeriodicExec(
811 IN PVOID SystemSpecific1,
812 IN PVOID FunctionContext,
813 IN PVOID SystemSpecific2,
814 IN PVOID SystemSpecific3)
817 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
819 // Do nothing if the driver is starting halt state.
820 // This might happen when timer already been fired before cancel timer with mlmehalt
821 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
822 fRTMP_ADAPTER_RADIO_OFF |
823 fRTMP_ADAPTER_RADIO_MEASUREMENT |
824 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
827 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
830 /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */
833 if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1))
835 pAd->Mlme.PeriodicRound ++;
839 #endif // RALINK_ATE //
841 #ifdef CONFIG_STA_SUPPORT
842 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
844 // Do nothing if monitor mode is on
848 if (pAd->Mlme.PeriodicRound & 0x1)
850 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
851 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
852 (STA_TGN_WIFI_ON(pAd)) &&
853 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
856 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
857 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
859 else if ((STA_TGN_WIFI_ON(pAd)) &&
860 ((pAd->MACVersion & 0xffff) == 0x0101))
862 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
863 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
867 #endif // CONFIG_STA_SUPPORT //
869 pAd->bUpdateBcnCntDone = FALSE;
871 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
872 pAd->Mlme.PeriodicRound ++;
874 // execute every 500ms
875 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
877 #ifdef CONFIG_STA_SUPPORT
878 // perform dynamic tx rate switching based on past TX history
879 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
881 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
883 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
884 MlmeDynamicTxRateSwitching(pAd);
886 #endif // CONFIG_STA_SUPPORT //
889 // Normal 1 second Mlme PeriodicExec.
890 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
892 pAd->Mlme.OneSecPeriodicRound ++;
897 /* request from Baron : move this routine from later to here */
898 /* for showing Rx error count in ATE RXFRAME */
899 NICUpdateRawCounters(pAd);
900 if (pAd->ate.bRxFer == 1)
902 pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec;
903 ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt);
904 pAd->ate.RxCntPerSec = 0;
906 if (pAd->ate.RxAntennaSel == 0)
907 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n",
908 pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2);
910 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0);
912 MlmeResetRalinkCounters(pAd);
915 #endif // RALINK_ATE //
926 //ORIBATimerTimeout(pAd);
928 // Media status changed, report to NDIS
929 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
931 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
932 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
934 pAd->IndicateMediaState = NdisMediaStateConnected;
935 RTMP_IndicateMediaState(pAd);
940 pAd->IndicateMediaState = NdisMediaStateDisconnected;
941 RTMP_IndicateMediaState(pAd);
945 NdisGetSystemUpTime(&pAd->Mlme.Now32);
947 // add the most up-to-date h/w raw counters into software variable, so that
948 // the dynamic tuning mechanism below are based on most up-to-date information
949 NICUpdateRawCounters(pAd);
952 RT2870_WatchDog(pAd);
955 #ifdef DOT11_N_SUPPORT
956 // Need statistics after read counter. So put after NICUpdateRawCounters
957 ORIBATimerTimeout(pAd);
958 #endif // DOT11_N_SUPPORT //
960 // if MGMT RING is full more than twice within 1 second, we consider there's
961 // a hardware problem stucking the TX path. In this case, try a hardware reset
962 // to recover the system
963 // if (pAd->RalinkCounters.MgmtRingFullCount >= 2)
964 // RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR);
966 // pAd->RalinkCounters.MgmtRingFullCount = 0;
968 // The time period for checking antenna is according to traffic
969 if (pAd->Mlme.bEnableAutoAntennaCheck)
971 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
972 pAd->RalinkCounters.OneSecTxRetryOkCount +
973 pAd->RalinkCounters.OneSecTxFailCount;
977 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
979 AsicEvaluateRxAnt(pAd);
984 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
986 AsicEvaluateRxAnt(pAd);
991 #ifdef CONFIG_STA_SUPPORT
992 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
993 STAMlmePeriodicExec(pAd);
994 #endif // CONFIG_STA_SUPPORT //
996 MlmeResetRalinkCounters(pAd);
998 #ifdef CONFIG_STA_SUPPORT
999 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1002 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1003 // and sending CTS-to-self over and over.
1004 // Software Patch Solution:
1005 // 1. Polling debug state register 0x10F4 every one second.
1006 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1007 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1011 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1012 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1014 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1016 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1018 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1022 #endif // CONFIG_STA_SUPPORT //
1024 RT28XX_MLME_HANDLER(pAd);
1028 pAd->bUpdateBcnCntDone = FALSE;
1031 #ifdef CONFIG_STA_SUPPORT
1032 VOID STAMlmePeriodicExec(
1039 // We return here in ATE mode, because the statistics
1040 // that ATE needs are not collected via this routine.
1043 // It is supposed that we will never reach here in ATE mode.
1044 ASSERT(!(ATE_ON(pAd)));
1047 #endif // RALINK_ATE //
1049 #ifdef WPA_SUPPLICANT_SUPPORT
1050 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1051 #endif // WPA_SUPPLICANT_SUPPORT //
1053 // WPA MIC error should block association attempt for 60 seconds
1054 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1055 pAd->StaCfg.bBlockAssoc = FALSE;
1058 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1060 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1062 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1064 pAd->PreMediaState = pAd->IndicateMediaState;
1070 AsicStaBbpTuning(pAd);
1072 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1073 pAd->RalinkCounters.OneSecTxRetryOkCount +
1074 pAd->RalinkCounters.OneSecTxFailCount;
1076 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1078 // update channel quality for Roaming and UI LinkQuality display
1079 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1082 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1083 // Radio is currently in noisy environment
1084 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1085 AsicAdjustTxPower(pAd);
1089 #ifdef QOS_DLS_SUPPORT
1090 // Check DLS time out, then tear down those session
1091 RTMPCheckDLSTimeOut(pAd);
1092 #endif // QOS_DLS_SUPPORT //
1094 // Is PSM bit consistent with user power management policy?
1095 // This is the only place that will set PSM bit ON.
1096 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1097 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1099 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1101 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1102 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1103 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1105 RTMPSetAGCInitValue(pAd, BW_20);
1106 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1109 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1110 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1112 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1114 // When APSD is enabled, the period changes as 20 sec
1115 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1116 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1120 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1121 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1123 if (pAd->CommonCfg.bWmmCapable)
1124 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1126 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1131 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1133 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1134 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1135 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1137 // Lost AP, send disconnect & link down event
1138 LinkDown(pAd, FALSE);
1140 #ifdef WPA_SUPPLICANT_SUPPORT
1141 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1142 if (pAd->StaCfg.WpaSupplicantUP)
1144 union iwreq_data wrqu;
1145 //send disassociate event to wpa_supplicant
1146 memset(&wrqu, 0, sizeof(wrqu));
1147 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1148 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1150 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1151 #endif // WPA_SUPPLICANT_SUPPORT //
1153 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1155 union iwreq_data wrqu;
1156 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1157 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1159 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1161 // RTMPPatchMacBbpBug(pAd);
1162 MlmeAutoReconnectLastSSID(pAd);
1164 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1166 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1167 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1168 MlmeAutoReconnectLastSSID(pAd);
1171 // Add auto seamless roaming
1172 if (pAd->StaCfg.bFastRoaming)
1174 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1176 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));
1178 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1180 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1184 else if (ADHOC_ON(pAd))
1187 if ((pAd->CommonCfg.Channel > 14)
1188 && (pAd->CommonCfg.bIEEE80211H == 1)
1189 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1191 RadarDetectPeriodic(pAd);
1194 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1195 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1197 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1198 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1200 MLME_START_REQ_STRUCT StartReq;
1202 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1203 LinkDown(pAd, FALSE);
1205 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1206 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1207 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1210 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1212 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1214 if (pEntry->ValidAsCLI == FALSE)
1217 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1218 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1221 else // no INFRA nor ADHOC connection
1224 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1225 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1226 goto SKIP_AUTO_SCAN_CONN;
1228 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1230 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1231 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1232 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1234 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1236 MLME_SCAN_REQ_STRUCT ScanReq;
1238 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1240 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1241 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1242 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1243 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1244 // Reset Missed scan number
1245 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1247 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1248 MlmeAutoReconnectLastSSID(pAd);
1250 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1252 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1255 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1259 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1260 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1262 if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1)
1263 MlmeAutoReconnectLastSSID(pAd);
1266 #endif // CARRIER_DETECTION_SUPPORT //
1267 MlmeAutoReconnectLastSSID(pAd);
1273 SKIP_AUTO_SCAN_CONN:
1275 #ifdef DOT11_N_SUPPORT
1276 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1278 pAd->MacTab.fAnyBASession = TRUE;
1279 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1281 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1283 pAd->MacTab.fAnyBASession = FALSE;
1284 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1286 #endif // DOT11_N_SUPPORT //
1289 #ifdef DOT11_N_SUPPORT
1290 #ifdef DOT11N_DRAFT3
1291 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1292 TriEventCounterMaintenance(pAd);
1293 #endif // DOT11N_DRAFT3 //
1294 #endif // DOT11_N_SUPPORT //
1301 IN PVOID SystemSpecific1,
1302 IN PVOID FunctionContext,
1303 IN PVOID SystemSpecific2,
1304 IN PVOID SystemSpecific3)
1307 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1309 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1310 RTMP_IndicateMediaState(pAd);
1311 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1314 // IRQL = DISPATCH_LEVEL
1316 IN PRTMP_ADAPTER pAd)
1318 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1319 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1321 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1323 MLME_CNTL_STATE_MACHINE,
1324 OID_802_11_BSSID_LIST_SCAN,
1327 RT28XX_MLME_HANDLER(pAd);
1331 // IRQL = DISPATCH_LEVEL
1332 VOID MlmeAutoReconnectLastSSID(
1333 IN PRTMP_ADAPTER pAd)
1337 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1338 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1339 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1341 NDIS_802_11_SSID OidSsid;
1342 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1343 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1345 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1347 MLME_CNTL_STATE_MACHINE,
1349 sizeof(NDIS_802_11_SSID),
1351 RT28XX_MLME_HANDLER(pAd);
1354 #endif // CONFIG_STA_SUPPORT //
1357 ==========================================================================
1358 Validate SSID for connection try and rescan purpose
1359 Valid SSID will have visible chars only.
1360 The valid length is from 0 to 32.
1361 IRQL = DISPATCH_LEVEL
1362 ==========================================================================
1364 BOOLEAN MlmeValidateSSID(
1370 if (SsidLen > MAX_LEN_OF_SSID)
1373 // Check each character value
1374 for (index = 0; index < SsidLen; index++)
1376 if (pSsid[index] < 0x20)
1384 VOID MlmeSelectTxRateTable(
1385 IN PRTMP_ADAPTER pAd,
1386 IN PMAC_TABLE_ENTRY pEntry,
1388 IN PUCHAR pTableSize,
1389 IN PUCHAR pInitTxRateIdx)
1393 // decide the rate table for tuning
1394 if (pAd->CommonCfg.TxRateTableSize > 0)
1396 *ppTable = RateSwitchTable;
1397 *pTableSize = RateSwitchTable[0];
1398 *pInitTxRateIdx = RateSwitchTable[1];
1403 #ifdef CONFIG_STA_SUPPORT
1404 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1406 #ifdef DOT11_N_SUPPORT
1407 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1408 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1409 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1411 *ppTable = RateSwitchTable11N1S;
1412 *pTableSize = RateSwitchTable11N1S[0];
1413 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1416 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1417 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1418 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1419 (pAd->Antenna.field.TxPath == 2))
1421 if (pAd->LatchRfRegs.Channel <= 14)
1423 *ppTable = RateSwitchTable11N2S;
1424 *pTableSize = RateSwitchTable11N2S[0];
1425 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1429 *ppTable = RateSwitchTable11N2SForABand;
1430 *pTableSize = RateSwitchTable11N2SForABand[0];
1431 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1436 #endif // DOT11_N_SUPPORT //
1437 if ((pEntry->RateLen == 4)
1438 #ifdef DOT11_N_SUPPORT
1439 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1440 #endif // DOT11_N_SUPPORT //
1443 *ppTable = RateSwitchTable11B;
1444 *pTableSize = RateSwitchTable11B[0];
1445 *pInitTxRateIdx = RateSwitchTable11B[1];
1448 else if (pAd->LatchRfRegs.Channel <= 14)
1450 *ppTable = RateSwitchTable11BG;
1451 *pTableSize = RateSwitchTable11BG[0];
1452 *pInitTxRateIdx = RateSwitchTable11BG[1];
1457 *ppTable = RateSwitchTable11G;
1458 *pTableSize = RateSwitchTable11G[0];
1459 *pInitTxRateIdx = RateSwitchTable11G[1];
1464 #endif // CONFIG_STA_SUPPORT //
1466 #ifdef DOT11_N_SUPPORT
1467 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1468 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1469 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1470 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1472 *ppTable = RateSwitchTable11BGN1S;
1473 *pTableSize = RateSwitchTable11BGN1S[0];
1474 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1479 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1480 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1481 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1482 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1484 if (pAd->LatchRfRegs.Channel <= 14)
1486 *ppTable = RateSwitchTable11BGN2S;
1487 *pTableSize = RateSwitchTable11BGN2S[0];
1488 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1493 *ppTable = RateSwitchTable11BGN2SForABand;
1494 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1495 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1501 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1502 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1504 *ppTable = RateSwitchTable11N1S;
1505 *pTableSize = RateSwitchTable11N1S[0];
1506 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1511 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1512 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1514 if (pAd->LatchRfRegs.Channel <= 14)
1516 *ppTable = RateSwitchTable11N2S;
1517 *pTableSize = RateSwitchTable11N2S[0];
1518 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1522 *ppTable = RateSwitchTable11N2SForABand;
1523 *pTableSize = RateSwitchTable11N2SForABand[0];
1524 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1529 #endif // DOT11_N_SUPPORT //
1530 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1531 if ((pEntry->RateLen == 4)
1532 #ifdef DOT11_N_SUPPORT
1533 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1534 #endif // DOT11_N_SUPPORT //
1537 *ppTable = RateSwitchTable11B;
1538 *pTableSize = RateSwitchTable11B[0];
1539 *pInitTxRateIdx = RateSwitchTable11B[1];
1544 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1545 if ((pEntry->RateLen > 8)
1546 #ifdef DOT11_N_SUPPORT
1547 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1548 #endif // DOT11_N_SUPPORT //
1551 *ppTable = RateSwitchTable11BG;
1552 *pTableSize = RateSwitchTable11BG[0];
1553 *pInitTxRateIdx = RateSwitchTable11BG[1];
1558 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1559 if ((pEntry->RateLen == 8)
1560 #ifdef DOT11_N_SUPPORT
1561 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1562 #endif // DOT11_N_SUPPORT //
1565 *ppTable = RateSwitchTable11G;
1566 *pTableSize = RateSwitchTable11G[0];
1567 *pInitTxRateIdx = RateSwitchTable11G[1];
1571 #ifdef DOT11_N_SUPPORT
1572 #endif // DOT11_N_SUPPORT //
1574 #ifdef CONFIG_STA_SUPPORT
1575 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1577 #ifdef DOT11_N_SUPPORT
1578 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1579 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1580 #endif // DOT11_N_SUPPORT //
1582 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1584 *ppTable = RateSwitchTable11B;
1585 *pTableSize = RateSwitchTable11B[0];
1586 *pInitTxRateIdx = RateSwitchTable11B[1];
1588 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1590 *ppTable = RateSwitchTable11G;
1591 *pTableSize = RateSwitchTable11G[0];
1592 *pInitTxRateIdx = RateSwitchTable11G[1];
1597 *ppTable = RateSwitchTable11BG;
1598 *pTableSize = RateSwitchTable11BG[0];
1599 *pInitTxRateIdx = RateSwitchTable11BG[1];
1603 #ifdef DOT11_N_SUPPORT
1604 if (pAd->LatchRfRegs.Channel <= 14)
1606 if (pAd->CommonCfg.TxStream == 1)
1608 *ppTable = RateSwitchTable11N1S;
1609 *pTableSize = RateSwitchTable11N1S[0];
1610 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1611 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1615 *ppTable = RateSwitchTable11N2S;
1616 *pTableSize = RateSwitchTable11N2S[0];
1617 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1618 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1623 if (pAd->CommonCfg.TxStream == 1)
1625 *ppTable = RateSwitchTable11N1S;
1626 *pTableSize = RateSwitchTable11N1S[0];
1627 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1628 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1632 *ppTable = RateSwitchTable11N2SForABand;
1633 *pTableSize = RateSwitchTable11N2SForABand[0];
1634 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1635 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1638 #endif // DOT11_N_SUPPORT //
1639 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1640 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1642 #endif // CONFIG_STA_SUPPORT //
1646 #ifdef CONFIG_STA_SUPPORT
1648 ==========================================================================
1650 This routine checks if there're other APs out there capable for
1651 roaming. Caller should call this routine only when Link up in INFRA mode
1652 and channel quality is below CQI_GOOD_THRESHOLD.
1654 IRQL = DISPATCH_LEVEL
1657 ==========================================================================
1659 VOID MlmeCheckForRoaming(
1660 IN PRTMP_ADAPTER pAd,
1664 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1667 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1668 // put all roaming candidates into RoamTab, and sort in RSSI order
1669 BssTableInit(pRoamTab);
1670 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1672 pBss = &pAd->ScanTab.BssEntry[i];
1674 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1675 continue; // AP disappear
1676 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1677 continue; // RSSI too weak. forget it.
1678 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1679 continue; // skip current AP
1680 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1681 continue; // only AP with stronger RSSI is eligible for roaming
1683 // AP passing all above rules is put into roaming candidate table
1684 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1685 pRoamTab->BssNr += 1;
1688 if (pRoamTab->BssNr > 0)
1690 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1691 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1693 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1694 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1695 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1696 RT28XX_MLME_HANDLER(pAd);
1699 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1703 ==========================================================================
1705 This routine checks if there're other APs out there capable for
1706 roaming. Caller should call this routine only when link up in INFRA mode
1707 and channel quality is below CQI_GOOD_THRESHOLD.
1709 IRQL = DISPATCH_LEVEL
1712 ==========================================================================
1714 VOID MlmeCheckForFastRoaming(
1715 IN PRTMP_ADAPTER pAd,
1719 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1722 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1723 // put all roaming candidates into RoamTab, and sort in RSSI order
1724 BssTableInit(pRoamTab);
1725 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1727 pBss = &pAd->ScanTab.BssEntry[i];
1729 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1730 continue; // RSSI too weak. forget it.
1731 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1732 continue; // skip current AP
1733 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1734 continue; // skip different SSID
1735 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1736 continue; // skip AP without better RSSI
1738 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));
1739 // AP passing all above rules is put into roaming candidate table
1740 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1741 pRoamTab->BssNr += 1;
1744 if (pRoamTab->BssNr > 0)
1746 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1747 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1749 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1750 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1751 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1752 RT28XX_MLME_HANDLER(pAd);
1755 // Maybe site survey required
1758 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1760 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1761 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1762 pAd->StaCfg.ScanCnt = 2;
1763 pAd->StaCfg.LastScanTime = Now;
1768 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1772 ==========================================================================
1774 This routine calculates TxPER, RxPER of the past N-sec period. And
1775 according to the calculation result, ChannelQuality is calculated here
1776 to decide if current AP is still doing the job.
1778 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1780 StaCfg.ChannelQuality - 0..100
1782 IRQL = DISPATCH_LEVEL
1784 NOTE: This routine decide channle quality based on RX CRC error ratio.
1785 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1786 is performed right before this routine, so that this routine can decide
1787 channel quality based on the most up-to-date information
1788 ==========================================================================
1790 VOID MlmeCalculateChannelQuality(
1791 IN PRTMP_ADAPTER pAd,
1794 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1798 ULONG BeaconLostTime = BEACON_LOST_TIME;
1800 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1801 // longer beacon lost time when carrier detection enabled
1802 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1804 BeaconLostTime = BEACON_LOST_TIME + BEACON_LOST_TIME/2;
1806 #endif // CARRIER_DETECTION_SUPPORT //
1808 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1811 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1813 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1814 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1822 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1823 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1827 // calculate RX PER - don't take RxPER into consideration if too few sample
1829 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1833 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1836 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1838 if (INFRA_ON(pAd) &&
1839 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1840 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1842 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1843 pAd->Mlme.ChannelQuality = 0;
1850 else if (MaxRssi < -90)
1853 NorRssi = (MaxRssi + 90) * 2;
1855 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1856 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1857 TX_WEIGHTING * (100 - TxPRR) +
1858 RX_WEIGHTING* (100 - RxPER)) / 100;
1859 if (pAd->Mlme.ChannelQuality >= 100)
1860 pAd->Mlme.ChannelQuality = 100;
1866 IN PRTMP_ADAPTER pAd,
1867 IN PMAC_TABLE_ENTRY pEntry,
1868 IN PRTMP_TX_RATE_SWITCH pTxRate)
1870 UCHAR MaxMode = MODE_OFDM;
1872 #ifdef DOT11_N_SUPPORT
1873 MaxMode = MODE_HTGREENFIELD;
1875 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1876 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1878 #endif // DOT11_N_SUPPORT //
1879 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1881 if (pTxRate->CurrMCS < MCS_AUTO)
1882 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1884 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1885 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1889 // If peer adhoc is b-only mode, we can't send 11g rate.
1890 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1891 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1894 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1896 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1897 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1898 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1900 // Patch speed error in status page
1901 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1905 if (pTxRate->Mode <= MaxMode)
1906 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1908 #ifdef DOT11_N_SUPPORT
1909 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1910 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1912 #endif // DOT11_N_SUPPORT //
1913 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1915 #ifdef DOT11_N_SUPPORT
1916 // Reexam each bandwidth's SGI support.
1917 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1919 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1920 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1921 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1922 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1925 // Turn RTS/CTS rate to 6Mbps.
1926 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1928 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1929 if (pAd->MacTab.fAnyBASession)
1931 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1935 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1938 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1940 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1941 if (pAd->MacTab.fAnyBASession)
1943 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1947 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1950 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1952 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1955 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1957 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1959 #endif // DOT11_N_SUPPORT //
1961 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1962 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1963 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1964 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1965 #ifdef DOT11_N_SUPPORT
1966 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1967 pAd->WIFItestbed.bGreenField)
1968 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1969 #endif // DOT11_N_SUPPORT //
1972 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1976 ==========================================================================
1978 This routine calculates the acumulated TxPER of eaxh TxRate. And
1979 according to the calculation result, change CommonCfg.TxRate which
1980 is the stable TX Rate we expect the Radio situation could sustained.
1982 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1986 IRQL = DISPATCH_LEVEL
1989 call this routine every second
1990 ==========================================================================
1992 VOID MlmeDynamicTxRateSwitching(
1993 IN PRTMP_ADAPTER pAd)
1995 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1996 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1997 ULONG TxErrorRatio = 0;
1998 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1999 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2001 UCHAR TableSize = 0;
2002 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2003 CHAR Rssi, RssiOffset = 0;
2004 TX_STA_CNT1_STRUC StaTx1;
2005 TX_STA_CNT0_STRUC TxStaCnt0;
2006 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2007 MAC_TABLE_ENTRY *pEntry;
2014 #endif // RALINK_ATE //
2017 // walk through MAC table, see if need to change AP's TX rate toward each entry
2019 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2021 pEntry = &pAd->MacTab.Content[i];
2023 // check if this entry need to switch rate automatically
2024 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2027 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2029 Rssi = RTMPMaxRssi(pAd,
2030 pAd->StaCfg.RssiSample.AvgRssi0,
2031 pAd->StaCfg.RssiSample.AvgRssi1,
2032 pAd->StaCfg.RssiSample.AvgRssi2);
2034 // Update statistic counter
2035 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2036 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2037 pAd->bUpdateBcnCntDone = TRUE;
2038 TxRetransmit = StaTx1.field.TxRetransmit;
2039 TxSuccess = StaTx1.field.TxSuccess;
2040 TxFailCount = TxStaCnt0.field.TxFailCount;
2041 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2043 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2044 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2045 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2046 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2047 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2048 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2050 // if no traffic in the past 1-sec period, don't change TX rate,
2051 // but clear all bad history. because the bad history may affect the next
2052 // Chariot throughput test
2053 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2054 pAd->RalinkCounters.OneSecTxRetryOkCount +
2055 pAd->RalinkCounters.OneSecTxFailCount;
2058 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2062 if (INFRA_ON(pAd) && (i == 1))
2063 Rssi = RTMPMaxRssi(pAd,
2064 pAd->StaCfg.RssiSample.AvgRssi0,
2065 pAd->StaCfg.RssiSample.AvgRssi1,
2066 pAd->StaCfg.RssiSample.AvgRssi2);
2068 Rssi = RTMPMaxRssi(pAd,
2069 pEntry->RssiSample.AvgRssi0,
2070 pEntry->RssiSample.AvgRssi1,
2071 pEntry->RssiSample.AvgRssi2);
2073 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2074 pEntry->OneSecTxRetryOkCount +
2075 pEntry->OneSecTxFailCount;
2078 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2081 CurrRateIdx = pEntry->CurrTxRateIndex;
2083 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2085 if (CurrRateIdx >= TableSize)
2087 CurrRateIdx = TableSize - 1;
2090 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2091 // So need to sync here.
2092 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2093 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2094 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2098 // Need to sync Real Tx rate and our record.
2099 // Then return for next DRS.
2100 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2101 pEntry->CurrTxRateIndex = InitTxRateIdx;
2102 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2104 // reset all OneSecTx counters
2105 RESET_ONE_SEC_TX_CNT(pEntry);
2109 // decide the next upgrade rate and downgrade rate, if any
2110 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2112 UpRateIdx = CurrRateIdx + 1;
2113 DownRateIdx = CurrRateIdx -1;
2115 else if (CurrRateIdx == 0)
2117 UpRateIdx = CurrRateIdx + 1;
2118 DownRateIdx = CurrRateIdx;
2120 else if (CurrRateIdx == (TableSize - 1))
2122 UpRateIdx = CurrRateIdx;
2123 DownRateIdx = CurrRateIdx - 1;
2126 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2128 #ifdef DOT11_N_SUPPORT
2129 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2131 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2132 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2135 #endif // DOT11_N_SUPPORT //
2137 TrainUp = pCurrTxRate->TrainUp;
2138 TrainDown = pCurrTxRate->TrainDown;
2141 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2144 // Keep the last time TxRateChangeAction status.
2146 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2151 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2152 // (criteria copied from RT2500 for Netopia case)
2154 if (TxTotalCnt <= 15)
2158 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2159 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2160 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2161 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2163 // check the existence and index of each needed MCS
2164 while (idx < pTable[0])
2166 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2168 if (pCurrTxRate->CurrMCS == MCS_0)
2172 else if (pCurrTxRate->CurrMCS == MCS_1)
2176 else if (pCurrTxRate->CurrMCS == MCS_2)
2180 else if (pCurrTxRate->CurrMCS == MCS_3)
2184 else if (pCurrTxRate->CurrMCS == MCS_4)
2188 else if (pCurrTxRate->CurrMCS == MCS_5)
2192 else if (pCurrTxRate->CurrMCS == MCS_6)
2196 //else if (pCurrTxRate->CurrMCS == MCS_7)
2197 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2201 else if (pCurrTxRate->CurrMCS == MCS_12)
2205 else if (pCurrTxRate->CurrMCS == MCS_13)
2209 else if (pCurrTxRate->CurrMCS == MCS_14)
2213 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2214 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI
2218 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2222 else if (pCurrTxRate->CurrMCS == MCS_21)
2226 else if (pCurrTxRate->CurrMCS == MCS_22)
2230 else if (pCurrTxRate->CurrMCS == MCS_23)
2237 if (pAd->LatchRfRegs.Channel <= 14)
2239 if (pAd->NicConfig2.field.ExternalLNAForG)
2250 if (pAd->NicConfig2.field.ExternalLNAForA)
2259 #ifdef DOT11_N_SUPPORT
2261 if ((pTable == RateSwitchTable11BGN3S) ||
2262 (pTable == RateSwitchTable11N3S) ||
2263 (pTable == RateSwitchTable))
2264 {// N mode with 3 stream // 3*3
2265 if (MCS23 && (Rssi >= -70))
2267 else if (MCS22 && (Rssi >= -72))
2269 else if (MCS21 && (Rssi >= -76))
2271 else if (MCS20 && (Rssi >= -78))
2273 else if (MCS4 && (Rssi >= -82))
2275 else if (MCS3 && (Rssi >= -84))
2277 else if (MCS2 && (Rssi >= -86))
2279 else if (MCS1 && (Rssi >= -88))
2284 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2285 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2286 {// N mode with 2 stream
2287 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2289 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2291 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2293 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2295 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2297 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2299 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2301 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2306 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2307 {// N mode with 1 stream
2308 if (MCS7 && (Rssi > (-72+RssiOffset)))
2310 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2312 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2314 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2316 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2318 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2320 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2326 #endif // DOT11_N_SUPPORT //
2328 if (MCS7 && (Rssi > -70))
2330 else if (MCS6 && (Rssi > -74))
2332 else if (MCS5 && (Rssi > -78))
2334 else if (MCS4 && (Rssi > -82))
2336 else if (MCS4 == 0) // for B-only mode
2338 else if (MCS3 && (Rssi > -85))
2340 else if (MCS2 && (Rssi > -87))
2342 else if (MCS1 && (Rssi > -90))
2348 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2350 pEntry->CurrTxRateIndex = TxRateIdx;
2351 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2352 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2355 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2356 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2357 pEntry->fLastSecAccordingRSSI = TRUE;
2358 // reset all OneSecTx counters
2359 RESET_ONE_SEC_TX_CNT(pEntry);
2364 if (pEntry->fLastSecAccordingRSSI == TRUE)
2366 pEntry->fLastSecAccordingRSSI = FALSE;
2367 pEntry->LastSecTxRateChangeAction = 0;
2368 // reset all OneSecTx counters
2369 RESET_ONE_SEC_TX_CNT(pEntry);
2376 BOOLEAN bTrainUpDown = FALSE;
2378 pEntry->CurrTxRateStableTime ++;
2380 // downgrade TX quality if PER >= Rate-Down threshold
2381 if (TxErrorRatio >= TrainDown)
2383 bTrainUpDown = TRUE;
2384 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2386 // upgrade TX quality if PER <= Rate-Up threshold
2387 else if (TxErrorRatio <= TrainUp)
2389 bTrainUpDown = TRUE;
2390 bUpgradeQuality = TRUE;
2391 if (pEntry->TxQuality[CurrRateIdx])
2392 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2394 if (pEntry->TxRateUpPenalty)
2395 pEntry->TxRateUpPenalty --;
2396 else if (pEntry->TxQuality[UpRateIdx])
2397 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2400 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2404 // perform DRS - consider TxRate Down first, then rate up.
2405 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2407 pEntry->CurrTxRateIndex = DownRateIdx;
2409 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2411 pEntry->CurrTxRateIndex = UpRateIdx;
2416 // if rate-up happen, clear all bad history of all TX rates
2417 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2419 pEntry->CurrTxRateStableTime = 0;
2420 pEntry->TxRateUpPenalty = 0;
2421 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2422 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2423 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2426 // For TxRate fast train up
2428 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2430 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2432 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2434 bTxRateChanged = TRUE;
2436 // if rate-down happen, only clear DownRate's bad history
2437 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2439 pEntry->CurrTxRateStableTime = 0;
2440 pEntry->TxRateUpPenalty = 0; // no penalty
2441 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2442 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2443 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2446 // For TxRate fast train down
2448 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2450 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2452 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2454 bTxRateChanged = TRUE;
2458 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2459 bTxRateChanged = FALSE;
2462 pEntry->LastTxOkCount = TxSuccess;
2464 // reset all OneSecTx counters
2465 RESET_ONE_SEC_TX_CNT(pEntry);
2467 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2468 if (bTxRateChanged && pNextTxRate)
2470 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2476 ========================================================================
2477 Routine Description:
2478 Station side, Auto TxRate faster train up timer call back function.
2481 SystemSpecific1 - Not used.
2482 FunctionContext - Pointer to our Adapter context.
2483 SystemSpecific2 - Not used.
2484 SystemSpecific3 - Not used.
2489 ========================================================================
2491 VOID StaQuickResponeForRateUpExec(
2492 IN PVOID SystemSpecific1,
2493 IN PVOID FunctionContext,
2494 IN PVOID SystemSpecific2,
2495 IN PVOID SystemSpecific3)
2497 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2498 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2500 ULONG TxErrorRatio = 0;
2501 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2502 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2504 UCHAR TableSize = 0;
2505 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2506 TX_STA_CNT1_STRUC StaTx1;
2507 TX_STA_CNT0_STRUC TxStaCnt0;
2509 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2510 MAC_TABLE_ENTRY *pEntry;
2513 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2516 // walk through MAC table, see if need to change AP's TX rate toward each entry
2518 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2520 pEntry = &pAd->MacTab.Content[i];
2522 // check if this entry need to switch rate automatically
2523 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2526 if (INFRA_ON(pAd) && (i == 1))
2527 Rssi = RTMPMaxRssi(pAd,
2528 pAd->StaCfg.RssiSample.AvgRssi0,
2529 pAd->StaCfg.RssiSample.AvgRssi1,
2530 pAd->StaCfg.RssiSample.AvgRssi2);
2532 Rssi = RTMPMaxRssi(pAd,
2533 pEntry->RssiSample.AvgRssi0,
2534 pEntry->RssiSample.AvgRssi1,
2535 pEntry->RssiSample.AvgRssi2);
2537 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2539 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2541 // decide the next upgrade rate and downgrade rate, if any
2542 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2544 UpRateIdx = CurrRateIdx + 1;
2545 DownRateIdx = CurrRateIdx -1;
2547 else if (CurrRateIdx == 0)
2549 UpRateIdx = CurrRateIdx + 1;
2550 DownRateIdx = CurrRateIdx;
2552 else if (CurrRateIdx == (TableSize - 1))
2554 UpRateIdx = CurrRateIdx;
2555 DownRateIdx = CurrRateIdx - 1;
2558 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2560 #ifdef DOT11_N_SUPPORT
2561 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2563 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2564 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2567 #endif // DOT11_N_SUPPORT //
2569 TrainUp = pCurrTxRate->TrainUp;
2570 TrainDown = pCurrTxRate->TrainDown;
2573 if (pAd->MacTab.Size == 1)
2575 // Update statistic counter
2576 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2577 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2579 TxRetransmit = StaTx1.field.TxRetransmit;
2580 TxSuccess = StaTx1.field.TxSuccess;
2581 TxFailCount = TxStaCnt0.field.TxFailCount;
2582 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2584 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2585 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2586 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2587 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2588 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2589 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2591 #if 0 // test by Gary.
2592 // if no traffic in the past 1-sec period, don't change TX rate,
2593 // but clear all bad history. because the bad history may affect the next
2594 // Chariot throughput test
2595 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2596 pAd->RalinkCounters.OneSecTxRetryOkCount +
2597 pAd->RalinkCounters.OneSecTxFailCount;
2600 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2604 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2605 pEntry->OneSecTxRetryOkCount +
2606 pEntry->OneSecTxFailCount;
2609 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2614 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2615 // (criteria copied from RT2500 for Netopia case)
2617 if (TxTotalCnt <= 12)
2619 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2620 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2622 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2624 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2625 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2627 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2629 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2632 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2638 ULONG OneSecTxNoRetryOKRationCount;
2640 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2645 // downgrade TX quality if PER >= Rate-Down threshold
2646 if (TxErrorRatio >= TrainDown)
2648 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2651 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2653 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2655 // perform DRS - consider TxRate Down first, then rate up.
2656 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2658 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2660 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2661 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2666 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2668 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2672 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2674 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2679 // if rate-up happen, clear all bad history of all TX rates
2680 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2682 pAd->DrsCounters.TxRateUpPenalty = 0;
2683 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2684 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2685 bTxRateChanged = TRUE;
2687 // if rate-down happen, only clear DownRate's bad history
2688 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2690 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2692 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2693 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2694 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2695 bTxRateChanged = TRUE;
2699 bTxRateChanged = FALSE;
2702 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2703 if (bTxRateChanged && pNextTxRate)
2705 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2711 ==========================================================================
2713 This routine is executed periodically inside MlmePeriodicExec() after
2714 association with an AP.
2715 It checks if StaCfg.Psm is consistent with user policy (recorded in
2716 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2717 there're some conditions to consider:
2718 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2719 the time when Mibss==TRUE
2720 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2721 if outgoing traffic available in TxRing or MgmtRing.
2723 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2725 IRQL = DISPATCH_LEVEL
2727 ==========================================================================
2729 VOID MlmeCheckPsmChange(
2730 IN PRTMP_ADAPTER pAd,
2736 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2737 // 2. user wants either MAX_PSP or FAST_PSP
2738 // 3. but current psm is not in PWR_SAVE
2739 // 4. CNTL state machine is not doing SCANning
2740 // 5. no TX SUCCESS event for the past 1-sec period
2741 #ifdef NDIS51_MINIPORT
2742 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2743 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2746 PowerMode = pAd->StaCfg.WindowsPowerMode;
2748 if (INFRA_ON(pAd) &&
2749 (PowerMode != Ndis802_11PowerModeCAM) &&
2750 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2751 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2752 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2753 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2754 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2756 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2757 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2758 MlmeSetPsmBit(pAd, PWR_SAVE);
2759 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2761 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2765 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2770 // IRQL = PASSIVE_LEVEL
2771 // IRQL = DISPATCH_LEVEL
2773 IN PRTMP_ADAPTER pAd,
2776 AUTO_RSP_CFG_STRUC csr4;
2778 pAd->StaCfg.Psm = psm;
2779 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2780 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2781 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2782 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2784 #endif // CONFIG_STA_SUPPORT //
2787 // IRQL = DISPATCH_LEVEL
2788 VOID MlmeSetTxPreamble(
2789 IN PRTMP_ADAPTER pAd,
2790 IN USHORT TxPreamble)
2792 AUTO_RSP_CFG_STRUC csr4;
2795 // Always use Long preamble before verifiation short preamble functionality works well.
2796 // Todo: remove the following line if short preamble functionality works
2798 //TxPreamble = Rt802_11PreambleLong;
2800 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2801 if (TxPreamble == Rt802_11PreambleLong)
2803 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2804 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2805 csr4.field.AutoResponderPreamble = 0;
2809 // NOTE: 1Mbps should always use long preamble
2810 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2811 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2812 csr4.field.AutoResponderPreamble = 1;
2815 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2819 ==========================================================================
2821 Update basic rate bitmap
2822 ==========================================================================
2825 VOID UpdateBasicRateBitmap(
2826 IN PRTMP_ADAPTER pAdapter)
2829 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2830 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2831 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2832 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2833 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2836 /* if A mode, always use fix BasicRateBitMap */
2837 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2838 if (pAdapter->CommonCfg.Channel > 14)
2839 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2842 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2844 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2848 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2854 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2856 if (bitmap & (1 << i))
2858 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2860 if (sup_p[j] == rate[i])
2865 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2867 if (ext_p[j] == rate[i])
2873 } /* End of UpdateBasicRateBitmap */
2875 // IRQL = PASSIVE_LEVEL
2876 // IRQL = DISPATCH_LEVEL
2877 // bLinkUp is to identify the inital link speed.
2878 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2879 VOID MlmeUpdateTxRates(
2880 IN PRTMP_ADAPTER pAd,
2885 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2886 UCHAR MinSupport = RATE_54;
2887 ULONG BasicRateBitmap = 0;
2888 UCHAR CurrBasicRate = RATE_1;
2889 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2890 PHTTRANSMIT_SETTING pHtPhy = NULL;
2891 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2892 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2893 BOOLEAN *auto_rate_cur_p;
2894 UCHAR HtMcs = MCS_AUTO;
2896 // find max desired rate
2897 UpdateBasicRateBitmap(pAd);
2900 auto_rate_cur_p = NULL;
2901 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2903 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2905 case 2: Rate = RATE_1; num++; break;
2906 case 4: Rate = RATE_2; num++; break;
2907 case 11: Rate = RATE_5_5; num++; break;
2908 case 22: Rate = RATE_11; num++; break;
2909 case 12: Rate = RATE_6; num++; break;
2910 case 18: Rate = RATE_9; num++; break;
2911 case 24: Rate = RATE_12; num++; break;
2912 case 36: Rate = RATE_18; num++; break;
2913 case 48: Rate = RATE_24; num++; break;
2914 case 72: Rate = RATE_36; num++; break;
2915 case 96: Rate = RATE_48; num++; break;
2916 case 108: Rate = RATE_54; num++; break;
2917 //default: Rate = RATE_1; break;
2919 if (MaxDesire < Rate) MaxDesire = Rate;
2922 //===========================================================================
2923 //===========================================================================
2925 #ifdef CONFIG_STA_SUPPORT
2926 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2928 pHtPhy = &pAd->StaCfg.HTPhyMode;
2929 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2930 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2932 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2933 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2935 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2936 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2937 (MaxDesire > RATE_11))
2939 MaxDesire = RATE_11;
2942 #endif // CONFIG_STA_SUPPORT //
2944 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2945 pMinHtPhy->word = 0;
2946 pMaxHtPhy->word = 0;
2949 // Auto rate switching is enabled only if more than one DESIRED RATES are
2950 // specified; otherwise disabled
2953 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2954 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2955 *auto_rate_cur_p = FALSE;
2959 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2960 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2961 *auto_rate_cur_p = TRUE;
2965 if (HtMcs != MCS_AUTO)
2967 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2968 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2969 *auto_rate_cur_p = FALSE;
2973 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2974 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2975 *auto_rate_cur_p = TRUE;
2979 #ifdef CONFIG_STA_SUPPORT
2980 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2982 pSupRate = &pAd->StaActive.SupRate[0];
2983 pExtRate = &pAd->StaActive.ExtRate[0];
2984 SupRateLen = pAd->StaActive.SupRateLen;
2985 ExtRateLen = pAd->StaActive.ExtRateLen;
2988 #endif // CONFIG_STA_SUPPORT //
2990 pSupRate = &pAd->CommonCfg.SupRate[0];
2991 pExtRate = &pAd->CommonCfg.ExtRate[0];
2992 SupRateLen = pAd->CommonCfg.SupRateLen;
2993 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2996 // find max supported rate
2997 for (i=0; i<SupRateLen; i++)
2999 switch (pSupRate[i] & 0x7f)
3001 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3002 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3003 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3004 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3005 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3006 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3007 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3008 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3009 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3010 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3011 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3012 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3013 default: Rate = RATE_1; break;
3015 if (MaxSupport < Rate) MaxSupport = Rate;
3017 if (MinSupport > Rate) MinSupport = Rate;
3020 for (i=0; i<ExtRateLen; i++)
3022 switch (pExtRate[i] & 0x7f)
3024 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3025 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3026 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3027 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3028 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3029 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3030 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3031 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3032 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3033 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3034 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3035 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3036 default: Rate = RATE_1; break;
3038 if (MaxSupport < Rate) MaxSupport = Rate;
3040 if (MinSupport > Rate) MinSupport = Rate;
3043 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3046 // pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap;
3048 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3049 // the DURATION field of outgoing uniicast DATA/MGMT frame
3050 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3052 if (BasicRateBitmap & (0x01 << i))
3053 CurrBasicRate = (UCHAR)i;
3054 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3057 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3058 // max tx rate = min {max desire rate, max supported rate}
3059 if (MaxSupport < MaxDesire)
3060 pAd->CommonCfg.MaxTxRate = MaxSupport;
3062 pAd->CommonCfg.MaxTxRate = MaxDesire;
3064 pAd->CommonCfg.MinTxRate = MinSupport;
3065 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
3066 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
3068 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
3069 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
3070 // 3. -75 > RSSI, start at 11 Mbps (long distance)
3071 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
3072 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
3073 if (*auto_rate_cur_p)
3076 #ifdef CONFIG_STA_SUPPORT
3077 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3078 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3079 #endif // CONFIG_STA_SUPPORT //
3080 if (bLinkUp == TRUE)
3081 pAd->CommonCfg.TxRate = RATE_24;
3083 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3086 pAd->CommonCfg.TxRate = RATE_11;
3088 pAd->CommonCfg.TxRate = RATE_24;
3090 // should never exceed MaxTxRate (consider 11B-only mode)
3091 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3092 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3094 pAd->CommonCfg.TxRateIndex = 0;
3098 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3099 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3100 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3102 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3103 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3104 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3105 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3108 if (pAd->CommonCfg.TxRate <= RATE_11)
3110 pMaxHtPhy->field.MODE = MODE_CCK;
3111 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3112 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3116 pMaxHtPhy->field.MODE = MODE_OFDM;
3117 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3118 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3119 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3121 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3124 pHtPhy->word = (pMaxHtPhy->word);
3125 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3127 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3128 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3129 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3133 switch (pAd->CommonCfg.PhyMode)
3135 case PHY_11BG_MIXED:
3137 #ifdef DOT11_N_SUPPORT
3138 case PHY_11BGN_MIXED:
3139 #endif // DOT11_N_SUPPORT //
3140 pAd->CommonCfg.MlmeRate = RATE_1;
3141 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3142 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3145 pAd->CommonCfg.RtsRate = RATE_11;
3147 // pAd->CommonCfg.RtsRate = RATE_1;
3152 #ifdef DOT11_N_SUPPORT
3153 case PHY_11AGN_MIXED:
3154 case PHY_11GN_MIXED:
3156 case PHY_11AN_MIXED:
3158 #endif // DOT11_N_SUPPORT //
3159 pAd->CommonCfg.MlmeRate = RATE_6;
3160 pAd->CommonCfg.RtsRate = RATE_6;
3161 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3162 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3164 case PHY_11ABG_MIXED:
3165 #ifdef DOT11_N_SUPPORT
3166 case PHY_11ABGN_MIXED:
3167 #endif // DOT11_N_SUPPORT //
3168 if (pAd->CommonCfg.Channel <= 14)
3170 pAd->CommonCfg.MlmeRate = RATE_1;
3171 pAd->CommonCfg.RtsRate = RATE_1;
3172 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3173 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3177 pAd->CommonCfg.MlmeRate = RATE_6;
3178 pAd->CommonCfg.RtsRate = RATE_6;
3179 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3180 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3184 pAd->CommonCfg.MlmeRate = RATE_6;
3185 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3186 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3187 pAd->CommonCfg.RtsRate = RATE_1;
3191 // Keep Basic Mlme Rate.
3193 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3194 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3195 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3197 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3198 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3201 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3202 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3203 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3204 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3205 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3206 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3207 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 ));
3210 #ifdef DOT11_N_SUPPORT
3212 ==========================================================================
3214 This function update HT Rate setting.
3215 Input Wcid value is valid for 2 case :
3216 1. it's used for Station in infra mode that copy AP rate to Mactable.
3217 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3219 IRQL = DISPATCH_LEVEL
3221 ==========================================================================
3223 VOID MlmeUpdateHtTxRates(
3224 IN PRTMP_ADAPTER pAd,
3227 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3229 RT_HT_CAPABILITY *pRtHtCap = NULL;
3230 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3233 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3234 PHTTRANSMIT_SETTING pHtPhy = NULL;
3235 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3236 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3237 BOOLEAN *auto_rate_cur_p;
3239 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3241 auto_rate_cur_p = NULL;
3243 #ifdef CONFIG_STA_SUPPORT
3244 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3246 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3247 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3248 pHtPhy = &pAd->StaCfg.HTPhyMode;
3249 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3250 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3252 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3254 #endif // CONFIG_STA_SUPPORT //
3256 #ifdef CONFIG_STA_SUPPORT
3257 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3259 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3262 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3263 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3264 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3265 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3266 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3267 pMaxHtPhy->field.STBC = STBC_USE;
3269 pMaxHtPhy->field.STBC = STBC_NONE;
3272 #endif // CONFIG_STA_SUPPORT //
3274 if (pDesireHtPhy->bHtEnable == FALSE)
3277 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3278 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3279 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3280 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3281 pMaxHtPhy->field.STBC = STBC_USE;
3283 pMaxHtPhy->field.STBC = STBC_NONE;
3286 // Decide MAX ht rate.
3287 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3288 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3290 pMaxHtPhy->field.MODE = MODE_HTMIX;
3292 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3293 pMaxHtPhy->field.BW = BW_40;
3295 pMaxHtPhy->field.BW = BW_20;
3297 if (pMaxHtPhy->field.BW == BW_20)
3298 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3300 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3302 for (i=23; i>=0; i--) // 3*3
3305 bitmask = (1<<(i-(j*8)));
3307 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3309 pMaxHtPhy->field.MCS = i;
3317 // Copy MIN ht rate. rt2860???
3318 pMinHtPhy->field.BW = BW_20;
3319 pMinHtPhy->field.MCS = 0;
3320 pMinHtPhy->field.STBC = 0;
3321 pMinHtPhy->field.ShortGI = 0;
3322 //If STA assigns fixed rate. update to fixed here.
3323 #ifdef CONFIG_STA_SUPPORT
3324 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3326 if (pDesireHtPhy->MCSSet[4] != 0)
3328 pMaxHtPhy->field.MCS = 32;
3329 pMinHtPhy->field.MCS = 32;
3330 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3333 for (i=23; (CHAR)i >= 0; i--) // 3*3
3336 bitmask = (1<<(i-(j*8)));
3337 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3339 pMaxHtPhy->field.MCS = i;
3340 pMinHtPhy->field.MCS = i;
3347 #endif // CONFIG_STA_SUPPORT //
3351 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3352 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3353 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3354 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3355 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3357 // use default now. rt2860
3358 if (pDesireHtPhy->MCSSet[0] != 0xff)
3359 *auto_rate_cur_p = FALSE;
3361 *auto_rate_cur_p = TRUE;
3363 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3364 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3365 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3366 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3368 #endif // DOT11_N_SUPPORT //
3370 // IRQL = DISPATCH_LEVEL
3372 IN PRTMP_ADAPTER pAd)
3374 RT28XX_MLME_RADIO_OFF(pAd);
3377 // IRQL = DISPATCH_LEVEL
3379 IN PRTMP_ADAPTER pAd)
3381 RT28XX_MLME_RADIO_ON(pAd);
3384 // ===========================================================================================
3386 // ===========================================================================================
3389 /*! \brief initialize BSS table
3390 * \param p_tab pointer to the table
3395 IRQL = PASSIVE_LEVEL
3396 IRQL = DISPATCH_LEVEL
3405 Tab->BssOverlapNr = 0;
3406 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3408 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3409 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3413 #ifdef DOT11_N_SUPPORT
3415 IN PRTMP_ADAPTER pAd,
3420 Tab->numAsOriginator = 0;
3421 Tab->numAsRecipient = 0;
3422 NdisAllocateSpinLock(&pAd->BATabLock);
3423 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3425 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3426 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3428 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3430 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3433 #endif // DOT11_N_SUPPORT //
3435 /*! \brief search the BSS table by SSID
3436 * \param p_tab pointer to the bss table
3437 * \param ssid SSID string
3438 * \return index of the table, BSS_NOT_FOUND if not in the table
3441 * \note search by sequential search
3443 IRQL = DISPATCH_LEVEL
3446 ULONG BssTableSearch(
3453 for (i = 0; i < Tab->BssNr; i++)
3456 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3457 // We should distinguish this case.
3459 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3460 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3461 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3466 return (ULONG)BSS_NOT_FOUND;
3469 ULONG BssSsidTableSearch(
3478 for (i = 0; i < Tab->BssNr; i++)
3481 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3482 // We should distinguish this case.
3484 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3485 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3486 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3487 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3492 return (ULONG)BSS_NOT_FOUND;
3495 ULONG BssTableSearchWithSSID(
3504 for (i = 0; i < Tab->BssNr; i++)
3506 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3507 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3508 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3509 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3510 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3511 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3516 return (ULONG)BSS_NOT_FOUND;
3519 // IRQL = DISPATCH_LEVEL
3520 VOID BssTableDeleteEntry(
3521 IN OUT BSS_TABLE *Tab,
3527 for (i = 0; i < Tab->BssNr; i++)
3529 if ((Tab->BssEntry[i].Channel == Channel) &&
3530 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3532 for (j = i; j < Tab->BssNr - 1; j++)
3534 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3536 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3543 #ifdef DOT11_N_SUPPORT
3545 ========================================================================
3546 Routine Description:
3547 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3550 // IRQL = DISPATCH_LEVEL
3551 ========================================================================
3553 VOID BATableDeleteORIEntry(
3554 IN OUT PRTMP_ADAPTER pAd,
3555 IN BA_ORI_ENTRY *pBAORIEntry)
3558 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3560 NdisAcquireSpinLock(&pAd->BATabLock);
3561 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3563 pAd->BATable.numAsOriginator -= 1;
3564 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3565 // Erase Bitmap flag.
3567 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3568 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3569 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3570 pBAORIEntry->Token = 1;
3571 // Not clear Sequence here.
3572 NdisReleaseSpinLock(&pAd->BATabLock);
3575 #endif // DOT11_N_SUPPORT //
3583 IRQL = DISPATCH_LEVEL
3587 IN PRTMP_ADAPTER pAd,
3588 OUT BSS_ENTRY *pBss,
3593 IN USHORT BeaconPeriod,
3594 IN PCF_PARM pCfParm,
3596 IN USHORT CapabilityInfo,
3598 IN UCHAR SupRateLen,
3600 IN UCHAR ExtRateLen,
3601 IN HT_CAPABILITY_IE *pHtCapability,
3602 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3603 IN UCHAR HtCapabilityLen,
3604 IN UCHAR AddHtInfoLen,
3605 IN UCHAR NewExtChanOffset,
3608 IN LARGE_INTEGER TimeStamp,
3610 IN PEDCA_PARM pEdcaParm,
3611 IN PQOS_CAPABILITY_PARM pQosCapability,
3612 IN PQBSS_LOAD_PARM pQbssLoad,
3613 IN USHORT LengthVIE,
3614 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3616 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3617 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3621 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3622 // Or send beacon /probe response with SSID len matching real SSID length,
3623 // but SSID is all zero. such as "00-00-00-00" with length 4.
3624 // We have to prevent this case overwrite correct table
3625 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3627 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3628 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3629 pBss->SsidLen = SsidLen;
3635 pBss->BssType = BssType;
3636 pBss->BeaconPeriod = BeaconPeriod;
3637 if (BssType == BSS_INFRA)
3639 if (pCfParm->bValid)
3641 pBss->CfpCount = pCfParm->CfpCount;
3642 pBss->CfpPeriod = pCfParm->CfpPeriod;
3643 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3644 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3649 pBss->AtimWin = AtimWin;
3652 pBss->CapabilityInfo = CapabilityInfo;
3653 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3654 // Combine with AuthMode, they will decide the connection methods.
3655 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3656 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3657 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3658 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3660 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3661 pBss->SupRateLen = SupRateLen;
3662 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3663 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3664 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3665 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3666 pBss->NewExtChanOffset = NewExtChanOffset;
3667 pBss->ExtRateLen = ExtRateLen;
3668 pBss->Channel = Channel;
3669 pBss->CentralChannel = Channel;
3671 // Update CkipFlag. if not exists, the value is 0x0
3672 pBss->CkipFlag = CkipFlag;
3674 // New for microsoft Fixed IEs
3675 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3676 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3677 pBss->FixIEs.Capabilities = CapabilityInfo;
3679 // New for microsoft Variable IEs
3682 pBss->VarIELen = LengthVIE;
3683 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3690 pBss->AddHtInfoLen = 0;
3691 pBss->HtCapabilityLen = 0;
3692 #ifdef DOT11_N_SUPPORT
3693 if (HtCapabilityLen> 0)
3695 pBss->HtCapabilityLen = HtCapabilityLen;
3696 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3697 if (AddHtInfoLen > 0)
3699 pBss->AddHtInfoLen = AddHtInfoLen;
3700 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3702 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3704 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3706 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3708 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3712 #endif // DOT11_N_SUPPORT //
3714 BssCipherParse(pBss);
3718 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3720 pBss->EdcaParm.bValid = FALSE;
3722 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3724 pBss->QosCapability.bValid = FALSE;
3726 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3728 pBss->QbssLoad.bValid = FALSE;
3730 #ifdef CONFIG_STA_SUPPORT
3731 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3737 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3738 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3739 #ifdef EXT_BUILD_CHANNEL_LIST
3740 NdisZeroMemory(&pBss->CountryString[0], 3);
3741 pBss->bHasCountryIE = FALSE;
3742 #endif // EXT_BUILD_CHANNEL_LIST //
3743 pEid = (PEID_STRUCT) pVIE;
3744 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3749 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3751 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3753 pBss->WpaIE.IELen = 0;
3756 pBss->WpaIE.IELen = pEid->Len + 2;
3757 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3761 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3763 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3765 pBss->RsnIE.IELen = 0;
3768 pBss->RsnIE.IELen = pEid->Len + 2;
3769 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3772 #ifdef EXT_BUILD_CHANNEL_LIST
3774 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3775 pBss->bHasCountryIE = TRUE;
3777 #endif // EXT_BUILD_CHANNEL_LIST //
3779 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3780 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3783 #endif // CONFIG_STA_SUPPORT //
3787 * \brief insert an entry into the bss table
3788 * \param p_tab The BSS table
3789 * \param Bssid BSSID
3791 * \param ssid_len Length of SSID
3793 * \param beacon_period
3800 * \param channel_idx
3804 * \note If SSID is identical, the old entry will be replaced by the new one
3806 IRQL = DISPATCH_LEVEL
3809 ULONG BssTableSetEntry(
3810 IN PRTMP_ADAPTER pAd,
3816 IN USHORT BeaconPeriod,
3819 IN USHORT CapabilityInfo,
3821 IN UCHAR SupRateLen,
3823 IN UCHAR ExtRateLen,
3824 IN HT_CAPABILITY_IE *pHtCapability,
3825 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3826 IN UCHAR HtCapabilityLen,
3827 IN UCHAR AddHtInfoLen,
3828 IN UCHAR NewExtChanOffset,
3831 IN LARGE_INTEGER TimeStamp,
3833 IN PEDCA_PARM pEdcaParm,
3834 IN PQOS_CAPABILITY_PARM pQosCapability,
3835 IN PQBSS_LOAD_PARM pQbssLoad,
3836 IN USHORT LengthVIE,
3837 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3841 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3842 if (Idx == BSS_NOT_FOUND)
3844 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3847 // It may happen when BSS Table was full.
3848 // The desired AP will not be added into BSS Table
3849 // In this case, if we found the desired AP then overwrite BSS Table.
3851 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3853 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3854 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3856 Idx = Tab->BssOverlapNr;
3857 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3858 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3859 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3860 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3866 return BSS_NOT_FOUND;
3870 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3871 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3872 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3877 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3878 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3879 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3885 #ifdef CONFIG_STA_SUPPORT
3886 #ifdef DOT11_N_SUPPORT
3887 #ifdef DOT11N_DRAFT3
3889 IN PRTMP_ADAPTER pAd)
3893 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3894 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3896 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3897 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3900 ULONG TriEventTableSetEntry(
3901 IN PRTMP_ADAPTER pAd,
3902 OUT TRIGGER_EVENT_TAB *Tab,
3904 IN HT_CAPABILITY_IE *pHtCapability,
3905 IN UCHAR HtCapabilityLen,
3910 if (HtCapabilityLen == 0)
3912 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3914 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3915 Tab->EventA[Tab->EventANo].bValid = TRUE;
3916 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3917 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3920 // Beacon has Regulatory class IE. So use beacon's
3921 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3925 // Use Station's Regulatory class instead.
3926 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3928 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3930 Tab->EventA[Tab->EventANo].RegClass = 32;
3932 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3933 Tab->EventA[Tab->EventANo].RegClass = 33;
3936 Tab->EventA[Tab->EventANo].RegClass = ??;
3943 else if (pHtCapability->HtCapInfo.Intolerant40)
3945 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3951 ========================================================================
3952 Routine Description:
3953 Trigger Event table Maintainence called once every second.
3956 // IRQL = DISPATCH_LEVEL
3957 ========================================================================
3959 VOID TriEventCounterMaintenance(
3960 IN PRTMP_ADAPTER pAd)
3963 BOOLEAN bNotify = FALSE;
3964 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3966 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3968 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3969 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3971 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3972 pAd->CommonCfg.TriggerEventTab.EventANo --;
3973 // Need to send 20/40 Coexistence Notify frame if has status change.
3978 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
3980 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
3981 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
3985 if (bNotify == TRUE)
3986 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
3988 #endif // DOT11N_DRAFT3 //
3989 #endif // DOT11_N_SUPPORT //
3991 // IRQL = DISPATCH_LEVEL
3992 VOID BssTableSsidSort(
3993 IN PRTMP_ADAPTER pAd,
3994 OUT BSS_TABLE *OutTab,
3999 BssTableInit(OutTab);
4001 for (i = 0; i < pAd->ScanTab.BssNr; i++)
4003 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
4004 BOOLEAN bIsHiddenApIncluded = FALSE;
4006 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
4007 (pAd->MlmeAux.Channel > 14) &&
4008 RadarChannelCheck(pAd, pInBss->Channel))
4009 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
4010 || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
4011 #endif // CARRIER_DETECTION_SUPPORT //
4015 bIsHiddenApIncluded = TRUE;
4018 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
4019 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
4021 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4024 #ifdef EXT_BUILD_CHANNEL_LIST
4025 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
4026 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
4027 (pInBss->bHasCountryIE == FALSE))
4029 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
4032 #endif // EXT_BUILD_CHANNEL_LIST //
4034 #ifdef DOT11_N_SUPPORT
4035 // 2.4G/5G N only mode
4036 if ((pInBss->HtCapabilityLen == 0) &&
4037 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4039 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4042 #endif // DOT11_N_SUPPORT //
4045 // Check the Authmode first
4046 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4048 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4049 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4053 // Check cipher suite, AP must have more secured cipher than station setting
4054 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4056 // If it's not mixed mode, we should only let BSS pass with the same encryption
4057 if (pInBss->WPA.bMixMode == FALSE)
4058 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4061 // check group cipher
4062 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4063 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4064 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
4067 // check pairwise cipher, skip if none matched
4068 // If profile set to AES, let it pass without question.
4069 // If profile set to TKIP, we must find one mateched
4070 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4071 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4072 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4075 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4077 // If it's not mixed mode, we should only let BSS pass with the same encryption
4078 if (pInBss->WPA2.bMixMode == FALSE)
4079 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4082 // check group cipher
4083 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4084 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4085 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
4088 // check pairwise cipher, skip if none matched
4089 // If profile set to AES, let it pass without question.
4090 // If profile set to TKIP, we must find one mateched
4091 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4092 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4093 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4097 // Bss Type matched, SSID matched.
4098 // We will check wepstatus for qualification Bss
4099 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4101 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4103 // For the SESv2 case, we will not qualify WepStatus.
4109 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4110 // It definitely will fail. So, skip it.
4111 // CCX also require not even try to connect it!!
4115 #ifdef DOT11_N_SUPPORT
4116 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4117 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4118 if ((pInBss->CentralChannel != pInBss->Channel) &&
4119 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4121 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4123 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4125 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4129 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4135 #endif // DOT11_N_SUPPORT //
4137 // copy matching BSS from InTab to OutTab
4138 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4142 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4144 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4147 #ifdef DOT11_N_SUPPORT
4148 // 2.4G/5G N only mode
4149 if ((pInBss->HtCapabilityLen == 0) &&
4150 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4152 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4155 #endif // DOT11_N_SUPPORT //
4158 // Check the Authmode first
4159 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4161 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4162 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4166 // Check cipher suite, AP must have more secured cipher than station setting
4167 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4169 // If it's not mixed mode, we should only let BSS pass with the same encryption
4170 if (pInBss->WPA.bMixMode == FALSE)
4171 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4174 // check group cipher
4175 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4178 // check pairwise cipher, skip if none matched
4179 // If profile set to AES, let it pass without question.
4180 // If profile set to TKIP, we must find one mateched
4181 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4182 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4183 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4186 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4188 // If it's not mixed mode, we should only let BSS pass with the same encryption
4189 if (pInBss->WPA2.bMixMode == FALSE)
4190 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4193 // check group cipher
4194 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4197 // check pairwise cipher, skip if none matched
4198 // If profile set to AES, let it pass without question.
4199 // If profile set to TKIP, we must find one mateched
4200 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4201 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4202 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4206 // Bss Type matched, SSID matched.
4207 // We will check wepstatus for qualification Bss
4208 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4211 #ifdef DOT11_N_SUPPORT
4212 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4213 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4214 if ((pInBss->CentralChannel != pInBss->Channel) &&
4215 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4217 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4219 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4221 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4224 #endif // DOT11_N_SUPPORT //
4226 // copy matching BSS from InTab to OutTab
4227 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4232 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4236 BssTableSortByRssi(OutTab);
4240 // IRQL = DISPATCH_LEVEL
4241 VOID BssTableSortByRssi(
4242 IN OUT BSS_TABLE *OutTab)
4247 for (i = 0; i < OutTab->BssNr - 1; i++)
4249 for (j = i+1; j < OutTab->BssNr; j++)
4251 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4253 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4254 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4255 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4260 #endif // CONFIG_STA_SUPPORT //
4263 VOID BssCipherParse(
4264 IN OUT PBSS_ENTRY pBss)
4268 PRSN_IE_HEADER_STRUCT pRsnHeader;
4269 PCIPHER_SUITE_STRUCT pCipher;
4270 PAKM_SUITE_STRUCT pAKM;
4273 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4276 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4280 pBss->WepStatus = Ndis802_11WEPEnabled;
4284 pBss->WepStatus = Ndis802_11WEPDisabled;
4286 // Set default to disable & open authentication before parsing variable IE
4287 pBss->AuthMode = Ndis802_11AuthModeOpen;
4288 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4291 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4292 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4293 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4294 pBss->WPA.RsnCapability = 0;
4295 pBss->WPA.bMixMode = FALSE;
4297 // Init WPA2 setting
4298 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4299 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4300 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4301 pBss->WPA2.RsnCapability = 0;
4302 pBss->WPA2.bMixMode = FALSE;
4305 Length = (INT) pBss->VarIELen;
4309 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4310 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4311 pEid = (PEID_STRUCT) pTmp;
4315 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4316 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4322 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4323 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4324 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4325 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4328 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4329 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4330 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4333 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4334 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4335 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4341 // if Cisco IE_WPA, break
4344 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4349 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4351 // if unsupported vendor specific IE
4354 // Skip OUI, version, and multicast suite
4355 // This part should be improved in the future when AP supported multiple cipher suite.
4356 // For now, it's OK since almost all APs have fixed cipher suite supported.
4357 // pTmp = (PUCHAR) pEid->Octet;
4360 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4368 // Parse group cipher
4372 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4375 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4378 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4381 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4386 // number of unicast suite
4389 // skip all unicast cipher suites
4390 //Count = *(PUSHORT) pTmp;
4391 Count = (pTmp[1]<<8) + pTmp[0];
4392 pTmp += sizeof(USHORT);
4394 // Parsing all unicast cipher suite
4399 TmpCipher = Ndis802_11WEPDisabled;
4403 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4404 TmpCipher = Ndis802_11Encryption1Enabled;
4407 TmpCipher = Ndis802_11Encryption2Enabled;
4410 TmpCipher = Ndis802_11Encryption3Enabled;
4415 if (TmpCipher > pBss->WPA.PairCipher)
4417 // Move the lower cipher suite to PairCipherAux
4418 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4419 pBss->WPA.PairCipher = TmpCipher;
4423 pBss->WPA.PairCipherAux = TmpCipher;
4429 // 4. get AKM suite counts
4430 //Count = *(PUSHORT) pTmp;
4431 Count = (pTmp[1]<<8) + pTmp[0];
4432 pTmp += sizeof(USHORT);
4438 // Set AP support WPA mode
4439 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4440 pBss->AuthMode = Ndis802_11AuthModeWPA;
4442 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4445 // Set AP support WPA mode
4446 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4447 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4449 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4456 // Fixed for WPA-None
4457 if (pBss->BssType == BSS_ADHOC)
4459 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4460 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4461 pBss->WepStatus = pBss->WPA.GroupCipher;
4462 // Patched bugs for old driver
4463 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4464 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4467 pBss->WepStatus = pBss->WPA.PairCipher;
4469 // Check the Pair & Group, if different, turn on mixed mode flag
4470 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4471 pBss->WPA.bMixMode = TRUE;
4476 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4478 // 0. Version must be 1
4479 if (le2cpu16(pRsnHeader->Version) != 1)
4481 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4483 // 1. Check group cipher
4484 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4485 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4488 // Parse group cipher
4489 switch (pCipher->Type)
4492 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4495 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4498 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4501 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4506 // set to correct offset for next parsing
4507 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4509 // 2. Get pairwise cipher counts
4510 //Count = *(PUSHORT) pTmp;
4511 Count = (pTmp[1]<<8) + pTmp[0];
4512 pTmp += sizeof(USHORT);
4514 // 3. Get pairwise cipher
4515 // Parsing all unicast cipher suite
4519 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4520 TmpCipher = Ndis802_11WEPDisabled;
4521 switch (pCipher->Type)
4524 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4525 TmpCipher = Ndis802_11Encryption1Enabled;
4528 TmpCipher = Ndis802_11Encryption2Enabled;
4531 TmpCipher = Ndis802_11Encryption3Enabled;
4536 if (TmpCipher > pBss->WPA2.PairCipher)
4538 // Move the lower cipher suite to PairCipherAux
4539 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4540 pBss->WPA2.PairCipher = TmpCipher;
4544 pBss->WPA2.PairCipherAux = TmpCipher;
4546 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4550 // 4. get AKM suite counts
4551 //Count = *(PUSHORT) pTmp;
4552 Count = (pTmp[1]<<8) + pTmp[0];
4553 pTmp += sizeof(USHORT);
4555 // 5. Get AKM ciphers
4556 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4557 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4563 // Set AP support WPA mode
4564 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4565 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4567 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4570 // Set AP support WPA mode
4571 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4572 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4574 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4579 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4581 // Fixed for WPA-None
4582 if (pBss->BssType == BSS_ADHOC)
4584 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4585 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4586 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4587 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4588 pBss->WepStatus = pBss->WPA.GroupCipher;
4589 // Patched bugs for old driver
4590 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4591 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4593 pBss->WepStatus = pBss->WPA2.PairCipher;
4595 // 6. Get RSN capability
4596 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4597 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4598 pTmp += sizeof(USHORT);
4600 // Check the Pair & Group, if different, turn on mixed mode flag
4601 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4602 pBss->WPA2.bMixMode = TRUE;
4608 Length -= (pEid->Len + 2);
4612 // ===========================================================================================
4614 // ===========================================================================================
4616 /*! \brief generates a random mac address value for IBSS BSSID
4617 * \param Addr the bssid location
4622 VOID MacAddrRandomBssid(
4623 IN PRTMP_ADAPTER pAd,
4628 for (i = 0; i < MAC_ADDR_LEN; i++)
4630 pAddr[i] = RandomByte(pAd);
4633 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4636 /*! \brief init the management mac frame header
4637 * \param p_hdr mac header
4638 * \param subtype subtype of the frame
4639 * \param p_ds destination address, don't care if it is a broadcast address
4641 * \pre the station has the following information in the pAd->StaCfg
4645 * \note this function initializes the following field
4647 IRQL = PASSIVE_LEVEL
4648 IRQL = DISPATCH_LEVEL
4651 VOID MgtMacHeaderInit(
4652 IN PRTMP_ADAPTER pAd,
4653 IN OUT PHEADER_802_11 pHdr80211,
4659 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4661 pHdr80211->FC.Type = BTYPE_MGMT;
4662 pHdr80211->FC.SubType = SubType;
4663 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4664 // pHdr80211->FC.Type = BTYPE_CNTL;
4665 pHdr80211->FC.ToDs = ToDs;
4666 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4667 #ifdef CONFIG_STA_SUPPORT
4668 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4669 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4670 #endif // CONFIG_STA_SUPPORT //
4671 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4674 // ===========================================================================================
4676 // ===========================================================================================
4678 /*!***************************************************************************
4679 * This routine build an outgoing frame, and fill all information specified
4680 * in argument list to the frame body. The actual frame size is the summation
4683 * Buffer - pointer to a pre-allocated memory segment
4684 * args - a list of <int arg_size, arg> pairs.
4685 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4686 * function will FAIL!!!
4688 * Size of the buffer
4690 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4692 IRQL = PASSIVE_LEVEL
4693 IRQL = DISPATCH_LEVEL
4695 ****************************************************************************/
4696 ULONG MakeOutgoingFrame(
4698 OUT ULONG *FrameLen, ...)
4705 // calculates the total length
4707 va_start(Args, FrameLen);
4710 leng = va_arg(Args, int);
4711 if (leng == END_OF_ARGS)
4715 p = va_arg(Args, PVOID);
4716 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4717 TotLeng = TotLeng + leng;
4720 va_end(Args); /* clean up */
4721 *FrameLen = TotLeng;
4725 // ===========================================================================================
4727 // ===========================================================================================
4729 /*! \brief Initialize The MLME Queue, used by MLME Functions
4730 * \param *Queue The MLME Queue
4731 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4734 * \note Because this is done only once (at the init stage), no need to be locked
4736 IRQL = PASSIVE_LEVEL
4739 NDIS_STATUS MlmeQueueInit(
4740 IN MLME_QUEUE *Queue)
4744 NdisAllocateSpinLock(&Queue->Lock);
4750 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4752 Queue->Entry[i].Occupied = FALSE;
4753 Queue->Entry[i].MsgLen = 0;
4754 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4757 return NDIS_STATUS_SUCCESS;
4760 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4761 * \param *Queue The MLME Queue
4762 * \param Machine The State Machine Id
4763 * \param MsgType The Message Type
4764 * \param MsgLen The Message length
4765 * \param *Msg The message pointer
4766 * \return TRUE if enqueue is successful, FALSE if the queue is full
4769 * \note The message has to be initialized
4771 IRQL = PASSIVE_LEVEL
4772 IRQL = DISPATCH_LEVEL
4775 BOOLEAN MlmeEnqueue(
4776 IN PRTMP_ADAPTER pAd,
4783 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4785 // Do nothing if the driver is starting halt state.
4786 // This might happen when timer already been fired before cancel timer with mlmehalt
4787 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4790 // First check the size, it MUST not exceed the mlme queue size
4791 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4793 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4797 if (MlmeQueueFull(Queue))
4802 NdisAcquireSpinLock(&(Queue->Lock));
4806 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4811 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4812 Queue->Entry[Tail].Occupied = TRUE;
4813 Queue->Entry[Tail].Machine = Machine;
4814 Queue->Entry[Tail].MsgType = MsgType;
4815 Queue->Entry[Tail].MsgLen = MsgLen;
4819 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4822 NdisReleaseSpinLock(&(Queue->Lock));
4826 /*! \brief This function is used when Recv gets a MLME message
4827 * \param *Queue The MLME Queue
4828 * \param TimeStampHigh The upper 32 bit of timestamp
4829 * \param TimeStampLow The lower 32 bit of timestamp
4830 * \param Rssi The receiving RSSI strength
4831 * \param MsgLen The length of the message
4832 * \param *Msg The message pointer
4833 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4837 IRQL = DISPATCH_LEVEL
4840 BOOLEAN MlmeEnqueueForRecv(
4841 IN PRTMP_ADAPTER pAd,
4843 IN ULONG TimeStampHigh,
4844 IN ULONG TimeStampLow,
4853 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4855 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4858 /* Nothing to do in ATE mode */
4861 #endif // RALINK_ATE //
4863 // Do nothing if the driver is starting halt state.
4864 // This might happen when timer already been fired before cancel timer with mlmehalt
4865 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4867 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4871 // First check the size, it MUST not exceed the mlme queue size
4872 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4874 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4878 if (MlmeQueueFull(Queue))
4883 #ifdef CONFIG_STA_SUPPORT
4884 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4886 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4888 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4892 #endif // CONFIG_STA_SUPPORT //
4894 // OK, we got all the informations, it is time to put things into queue
4895 NdisAcquireSpinLock(&(Queue->Lock));
4899 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4903 Queue->Entry[Tail].Occupied = TRUE;
4904 Queue->Entry[Tail].Machine = Machine;
4905 Queue->Entry[Tail].MsgType = MsgType;
4906 Queue->Entry[Tail].MsgLen = MsgLen;
4907 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4908 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4909 Queue->Entry[Tail].Rssi0 = Rssi0;
4910 Queue->Entry[Tail].Rssi1 = Rssi1;
4911 Queue->Entry[Tail].Rssi2 = Rssi2;
4912 Queue->Entry[Tail].Signal = Signal;
4913 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4915 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4919 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4922 NdisReleaseSpinLock(&(Queue->Lock));
4924 RT28XX_MLME_HANDLER(pAd);
4930 /*! \brief Dequeue a message from the MLME Queue
4931 * \param *Queue The MLME Queue
4932 * \param *Elem The message dequeued from MLME Queue
4933 * \return TRUE if the Elem contains something, FALSE otherwise
4937 IRQL = DISPATCH_LEVEL
4940 BOOLEAN MlmeDequeue(
4941 IN MLME_QUEUE *Queue,
4942 OUT MLME_QUEUE_ELEM **Elem)
4944 NdisAcquireSpinLock(&(Queue->Lock));
4945 *Elem = &(Queue->Entry[Queue->Head]);
4948 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4952 NdisReleaseSpinLock(&(Queue->Lock));
4956 // IRQL = DISPATCH_LEVEL
4957 VOID MlmeRestartStateMachine(
4958 IN PRTMP_ADAPTER pAd)
4960 #ifdef CONFIG_STA_SUPPORT
4962 #endif // CONFIG_STA_SUPPORT //
4964 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4967 #ifdef CONFIG_STA_SUPPORT
4968 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4970 #ifdef QOS_DLS_SUPPORT
4972 #endif // QOS_DLS_SUPPORT //
4973 // Cancel all timer events
4974 // Be careful to cancel new added timer
4975 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4976 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4977 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4978 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4979 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4980 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4982 #ifdef QOS_DLS_SUPPORT
4983 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
4985 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
4987 #endif // QOS_DLS_SUPPORT //
4989 #endif // CONFIG_STA_SUPPORT //
4991 // Change back to original channel in case of doing scan
4992 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4993 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4995 // Resume MSDU which is turned off durning scan
4996 RTMPResumeMsduTransmission(pAd);
4998 #ifdef CONFIG_STA_SUPPORT
4999 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5001 // Set all state machines back IDLE
5002 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
5003 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
5004 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
5005 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
5006 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
5007 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
5008 #ifdef QOS_DLS_SUPPORT
5009 pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
5010 #endif // QOS_DLS_SUPPORT //
5012 #endif // CONFIG_STA_SUPPORT //
5016 /*! \brief test if the MLME Queue is empty
5017 * \param *Queue The MLME Queue
5018 * \return TRUE if the Queue is empty, FALSE otherwise
5022 IRQL = DISPATCH_LEVEL
5025 BOOLEAN MlmeQueueEmpty(
5026 IN MLME_QUEUE *Queue)
5030 NdisAcquireSpinLock(&(Queue->Lock));
5031 Ans = (Queue->Num == 0);
5032 NdisReleaseSpinLock(&(Queue->Lock));
5037 /*! \brief test if the MLME Queue is full
5038 * \param *Queue The MLME Queue
5039 * \return TRUE if the Queue is empty, FALSE otherwise
5043 IRQL = PASSIVE_LEVEL
5044 IRQL = DISPATCH_LEVEL
5047 BOOLEAN MlmeQueueFull(
5048 IN MLME_QUEUE *Queue)
5052 NdisAcquireSpinLock(&(Queue->Lock));
5053 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5054 NdisReleaseSpinLock(&(Queue->Lock));
5059 /*! \brief The destructor of MLME Queue
5064 * \note Clear Mlme Queue, Set Queue->Num to Zero.
5066 IRQL = PASSIVE_LEVEL
5069 VOID MlmeQueueDestroy(
5070 IN MLME_QUEUE *pQueue)
5072 NdisAcquireSpinLock(&(pQueue->Lock));
5076 NdisReleaseSpinLock(&(pQueue->Lock));
5077 NdisFreeSpinLock(&(pQueue->Lock));
5080 /*! \brief To substitute the message type if the message is coming from external
5081 * \param pFrame The frame received
5082 * \param *Machine The state machine
5083 * \param *MsgType the message type for the state machine
5084 * \return TRUE if the substitution is successful, FALSE otherwise
5088 IRQL = DISPATCH_LEVEL
5091 #ifdef CONFIG_STA_SUPPORT
5092 BOOLEAN MsgTypeSubst(
5093 IN PRTMP_ADAPTER pAd,
5094 IN PFRAME_802_11 pFrame,
5102 // Pointer to start of data frames including SNAP header
5103 pData = (PUCHAR) pFrame + LENGTH_802_11;
5105 // The only data type will pass to this function is EAPOL frame
5106 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5108 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5110 // Cisco Aironet SNAP header
5111 *Machine = AIRONET_STATE_MACHINE;
5112 *MsgType = MT2_AIRONET_MSG;
5116 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5119 *Machine = LEAP_STATE_MACHINE;
5120 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5121 return (LeapMsgTypeSubst(EAPType, MsgType));
5124 #endif // LEAP_SUPPORT //
5126 *Machine = WPA_PSK_STATE_MACHINE;
5127 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5128 return(WpaMsgTypeSubst(EAPType, MsgType));
5132 switch (pFrame->Hdr.FC.SubType)
5134 case SUBTYPE_ASSOC_REQ:
5135 *Machine = ASSOC_STATE_MACHINE;
5136 *MsgType = MT2_PEER_ASSOC_REQ;
5138 case SUBTYPE_ASSOC_RSP:
5139 *Machine = ASSOC_STATE_MACHINE;
5140 *MsgType = MT2_PEER_ASSOC_RSP;
5142 case SUBTYPE_REASSOC_REQ:
5143 *Machine = ASSOC_STATE_MACHINE;
5144 *MsgType = MT2_PEER_REASSOC_REQ;
5146 case SUBTYPE_REASSOC_RSP:
5147 *Machine = ASSOC_STATE_MACHINE;
5148 *MsgType = MT2_PEER_REASSOC_RSP;
5150 case SUBTYPE_PROBE_REQ:
5151 *Machine = SYNC_STATE_MACHINE;
5152 *MsgType = MT2_PEER_PROBE_REQ;
5154 case SUBTYPE_PROBE_RSP:
5155 *Machine = SYNC_STATE_MACHINE;
5156 *MsgType = MT2_PEER_PROBE_RSP;
5158 case SUBTYPE_BEACON:
5159 *Machine = SYNC_STATE_MACHINE;
5160 *MsgType = MT2_PEER_BEACON;
5163 *Machine = SYNC_STATE_MACHINE;
5164 *MsgType = MT2_PEER_ATIM;
5166 case SUBTYPE_DISASSOC:
5167 *Machine = ASSOC_STATE_MACHINE;
5168 *MsgType = MT2_PEER_DISASSOC_REQ;
5171 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5172 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5173 if (Seq == 1 || Seq == 3)
5175 *Machine = AUTH_RSP_STATE_MACHINE;
5176 *MsgType = MT2_PEER_AUTH_ODD;
5178 else if (Seq == 2 || Seq == 4)
5180 *Machine = AUTH_STATE_MACHINE;
5181 *MsgType = MT2_PEER_AUTH_EVEN;
5188 case SUBTYPE_DEAUTH:
5189 *Machine = AUTH_RSP_STATE_MACHINE;
5190 *MsgType = MT2_PEER_DEAUTH;
5192 case SUBTYPE_ACTION:
5193 *Machine = ACTION_STATE_MACHINE;
5194 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5195 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5197 *MsgType = MT2_ACT_INVALID;
5201 *MsgType = (pFrame->Octet[0]&0x7F);
5211 #endif // CONFIG_STA_SUPPORT //
5213 // ===========================================================================================
5215 // ===========================================================================================
5217 /*! \brief Initialize the state machine.
5218 * \param *S pointer to the state machine
5219 * \param Trans State machine transition function
5220 * \param StNr number of states
5221 * \param MsgNr number of messages
5222 * \param DefFunc default function, when there is invalid state/message combination
5223 * \param InitState initial state of the state machine
5224 * \param Base StateMachine base, internal use only
5225 * \pre p_sm should be a legal pointer
5228 IRQL = PASSIVE_LEVEL
5231 VOID StateMachineInit(
5232 IN STATE_MACHINE *S,
5233 IN STATE_MACHINE_FUNC Trans[],
5236 IN STATE_MACHINE_FUNC DefFunc,
5242 // set number of states and messages
5247 S->TransFunc = Trans;
5249 // init all state transition to default function
5250 for (i = 0; i < StNr; i++)
5252 for (j = 0; j < MsgNr; j++)
5254 S->TransFunc[i * MsgNr + j] = DefFunc;
5258 // set the starting state
5259 S->CurrState = InitState;
5262 /*! \brief This function fills in the function pointer into the cell in the state machine
5263 * \param *S pointer to the state machine
5265 * \param Msg incoming message
5266 * \param f the function to be executed when (state, message) combination occurs at the state machine
5267 * \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
5270 IRQL = PASSIVE_LEVEL
5273 VOID StateMachineSetAction(
5274 IN STATE_MACHINE *S,
5277 IN STATE_MACHINE_FUNC Func)
5281 MsgIdx = Msg - S->Base;
5283 if (St < S->NrState && MsgIdx < S->NrMsg)
5285 // boundary checking before setting the action
5286 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5290 /*! \brief This function does the state transition
5291 * \param *Adapter the NIC adapter pointer
5292 * \param *S the state machine
5293 * \param *Elem the message to be executed
5296 IRQL = DISPATCH_LEVEL
5299 VOID StateMachinePerformAction(
5300 IN PRTMP_ADAPTER pAd,
5301 IN STATE_MACHINE *S,
5302 IN MLME_QUEUE_ELEM *Elem)
5304 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5308 ==========================================================================
5310 The drop function, when machine executes this, the message is simply
5311 ignored. This function does nothing, the message is freed in
5312 StateMachinePerformAction()
5313 ==========================================================================
5316 IN PRTMP_ADAPTER pAd,
5317 IN MLME_QUEUE_ELEM *Elem)
5321 // ===========================================================================================
5323 // ===========================================================================================
5326 ==========================================================================
5329 IRQL = PASSIVE_LEVEL
5331 ==========================================================================
5334 IN PRTMP_ADAPTER pAd,
5338 pAd->Mlme.ShiftReg = 1;
5340 pAd->Mlme.ShiftReg = Seed;
5344 ==========================================================================
5346 ==========================================================================
5349 IN PRTMP_ADAPTER pAd)
5356 if (pAd->Mlme.ShiftReg == 0)
5357 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5359 for (i = 0; i < 8; i++)
5361 if (pAd->Mlme.ShiftReg & 0x00000001)
5363 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5368 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5371 R = (R << 1) | Result;
5377 VOID AsicUpdateAutoFallBackTable(
5378 IN PRTMP_ADAPTER pAd,
5379 IN PUCHAR pRateTable)
5382 HT_FBK_CFG0_STRUC HtCfg0;
5383 HT_FBK_CFG1_STRUC HtCfg1;
5384 LG_FBK_CFG0_STRUC LgCfg0;
5385 LG_FBK_CFG1_STRUC LgCfg1;
5386 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5388 // set to initial value
5389 HtCfg0.word = 0x65432100;
5390 HtCfg1.word = 0xedcba988;
5391 LgCfg0.word = 0xedcba988;
5392 LgCfg1.word = 0x00002100;
5394 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5395 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5397 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5398 switch (pCurrTxRate->Mode)
5404 switch(pCurrTxRate->CurrMCS)
5407 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5410 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5413 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5416 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5419 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5422 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5425 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5428 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5433 #ifdef DOT11_N_SUPPORT
5437 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5439 switch(pCurrTxRate->CurrMCS)
5442 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5445 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5448 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5451 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5454 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5457 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5460 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5463 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5466 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5469 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5472 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5475 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5478 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5481 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5484 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5487 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5490 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5495 #endif // DOT11_N_SUPPORT //
5498 pNextTxRate = pCurrTxRate;
5501 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5502 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5503 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5504 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5508 ========================================================================
5510 Routine Description:
5511 Set MAC register value according operation mode.
5512 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5513 If MM or GF mask is not set, those passing argument doesn't not take effect.
5515 Operation mode meaning:
5516 = 0 : Pure HT, no preotection.
5517 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5518 = 0x10: No Transmission in 40M is protected.
5519 = 0x11: Transmission in both 40M and 20M shall be protected
5521 we should choose not to use GF. But still set correct ASIC registers.
5522 ========================================================================
5524 VOID AsicUpdateProtect(
5525 IN PRTMP_ADAPTER pAd,
5526 IN USHORT OperationMode,
5528 IN BOOLEAN bDisableBGProtect,
5529 IN BOOLEAN bNonGFExist)
5531 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5540 #endif // RALINK_ATE //
5542 #ifdef DOT11_N_SUPPORT
5543 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5548 if (pAd->BATable.numAsOriginator)
5551 // enable the RTS/CTS to avoid channel collision
5553 SetMask = ALLN_SETPROTECT;
5556 #endif // DOT11_N_SUPPORT //
5558 // Config ASIC RTS threshold register
5559 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5560 MacReg &= 0xFF0000FF;
5562 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5564 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5566 #ifdef DOT11_N_SUPPORT
5567 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5568 #endif // DOT11_N_SUPPORT //
5569 (pAd->CommonCfg.bAggregationCapable == TRUE))
5570 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5572 MacReg |= (0x1000 << 8);
5576 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5580 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5582 // Initial common protection settings
5583 RTMPZeroMemory(Protect, sizeof(Protect));
5586 ProtCfg.field.TxopAllowGF40 = 1;
5587 ProtCfg.field.TxopAllowGF20 = 1;
5588 ProtCfg.field.TxopAllowMM40 = 1;
5589 ProtCfg.field.TxopAllowMM20 = 1;
5590 ProtCfg.field.TxopAllowOfdm = 1;
5591 ProtCfg.field.TxopAllowCck = 1;
5592 ProtCfg.field.RTSThEn = 1;
5593 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5595 // update PHY mode and rate
5596 if (pAd->CommonCfg.Channel > 14)
5597 ProtCfg.field.ProtectRate = 0x4000;
5598 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5600 // Handle legacy(B/G) protection
5601 if (bDisableBGProtect)
5603 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5604 ProtCfg.field.ProtectCtrl = 0;
5605 Protect[0] = ProtCfg.word;
5606 Protect[1] = ProtCfg.word;
5610 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5611 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5612 Protect[0] = ProtCfg.word;
5613 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5614 Protect[1] = ProtCfg.word;
5617 #ifdef DOT11_N_SUPPORT
5618 // Decide HT frame protection.
5619 if ((SetMask & ALLN_SETPROTECT) != 0)
5621 switch(OperationMode)
5625 // 1.All STAs in the BSS are 20/40 MHz HT
5626 // 2. in ai 20/40MHz BSS
5627 // 3. all STAs are 20MHz in a 20MHz BSS
5628 // Pure HT. no protection.
5632 // PROT_TXOP(25:20) -- 010111
5633 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5634 // PROT_CTRL(17:16) -- 00 (None)
5635 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5636 Protect[2] = 0x01744004;
5640 // PROT_TXOP(25:20) -- 111111
5641 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5642 // PROT_CTRL(17:16) -- 00 (None)
5643 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5644 Protect[3] = 0x03f44084;
5648 // PROT_TXOP(25:20) -- 010111
5649 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5650 // PROT_CTRL(17:16) -- 00 (None)
5651 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5652 Protect[4] = 0x01744004;
5656 // PROT_TXOP(25:20) -- 111111
5657 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5658 // PROT_CTRL(17:16) -- 00 (None)
5659 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5660 Protect[5] = 0x03f44084;
5664 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5665 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5666 Protect[4] = 0x01754004;
5667 Protect[5] = 0x03f54084;
5669 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5673 // This is "HT non-member protection mode."
5674 // If there may be non-HT STAs my BSS
5675 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5676 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5677 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5679 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5680 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5682 //Assign Protection method for 20&40 MHz packets
5683 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5684 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5685 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5686 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5687 Protect[2] = ProtCfg.word;
5688 Protect[3] = ProtCfg4.word;
5689 Protect[4] = ProtCfg.word;
5690 Protect[5] = ProtCfg4.word;
5691 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5695 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5696 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5697 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5699 //Assign Protection method for 40MHz packets
5700 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5701 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5702 Protect[2] = ProtCfg.word;
5703 Protect[3] = ProtCfg4.word;
5706 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5707 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5709 Protect[4] = ProtCfg.word;
5710 Protect[5] = ProtCfg4.word;
5712 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5716 // HT mixed mode. PROTECT ALL!
5718 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5719 ProtCfg4.word = 0x03f44084;
5720 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5721 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5723 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5724 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5726 //Assign Protection method for 20&40 MHz packets
5727 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5728 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5729 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5730 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5731 Protect[2] = ProtCfg.word;
5732 Protect[3] = ProtCfg4.word;
5733 Protect[4] = ProtCfg.word;
5734 Protect[5] = ProtCfg4.word;
5735 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5739 // Special on for Atheros problem n chip.
5740 Protect[2] = 0x01754004;
5741 Protect[3] = 0x03f54084;
5742 Protect[4] = 0x01754004;
5743 Protect[5] = 0x03f54084;
5744 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5748 #endif // DOT11_N_SUPPORT //
5750 offset = CCK_PROT_CFG;
5751 for (i = 0;i < 6;i++)
5753 if ((SetMask & (1<< i)))
5755 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5761 ==========================================================================
5764 IRQL = PASSIVE_LEVEL
5765 IRQL = DISPATCH_LEVEL
5767 ==========================================================================
5769 VOID AsicSwitchChannel(
5770 IN PRTMP_ADAPTER pAd,
5774 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5775 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5777 UINT32 Value = 0; //BbpReg, Value;
5778 RTMP_RF_REGS *RFRegTable;
5780 // Search Tx power value
5781 for (index = 0; index < pAd->ChannelListNum; index++)
5783 if (Channel == pAd->ChannelList[index].Channel)
5785 TxPwer = pAd->ChannelList[index].Power;
5786 TxPwer2 = pAd->ChannelList[index].Power2;
5791 if (index == MAX_NUM_OF_CHANNELS)
5793 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5797 // The RF programming sequence is difference between 3xxx and 2xxx
5798 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5800 /* modify by WY for Read RF Reg. error */
5803 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5805 if (Channel == FreqItems3020[index].Channel)
5807 // Programming channel parameters
5808 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5809 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5811 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5812 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5813 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5816 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5817 RFValue = (RFValue & 0xE0) | TxPwer;
5818 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5821 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5822 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5823 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5826 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5828 RFValue = pAd->Mlme.CaliBW40RfR24;
5829 //DISABLE_11N_CHECK(pAd);
5833 RFValue = pAd->Mlme.CaliBW20RfR24;
5835 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5838 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5839 RFValue = RFValue | 0x1;
5840 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5842 // latch channel for future usage.
5843 pAd->LatchRfRegs.Channel = Channel;
5849 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5854 pAd->Antenna.field.TxPath,
5855 FreqItems3020[index].N,
5856 FreqItems3020[index].K,
5857 FreqItems3020[index].R));
5862 RFRegTable = RF2850RegTable;
5864 switch (pAd->RfIcType)
5871 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5873 if (Channel == RFRegTable[index].Channel)
5875 R2 = RFRegTable[index].R2;
5876 if (pAd->Antenna.field.TxPath == 1)
5878 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5881 if (pAd->Antenna.field.RxPath == 2)
5883 R2 |= 0x40; // write 1 to off Rxpath.
5885 else if (pAd->Antenna.field.RxPath == 1)
5887 R2 |= 0x20040; // write 1 to off RxPath
5892 // initialize R3, R4
5893 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5894 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5896 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5898 if ((TxPwer >= -7) && (TxPwer < 0))
5900 TxPwer = (7+TxPwer);
5901 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5902 R3 |= (TxPwer << 10);
5903 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5907 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5908 R3 |= (TxPwer << 10) | (1 << 9);
5912 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5914 TxPwer2 = (7+TxPwer2);
5915 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5916 R4 |= (TxPwer2 << 7);
5917 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5921 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5922 R4 |= (TxPwer2 << 7) | (1 << 6);
5927 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5928 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5931 // Based on BBP current mode before changing RF channel.
5932 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5938 pAd->LatchRfRegs.Channel = Channel;
5939 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5940 pAd->LatchRfRegs.R2 = R2;
5941 pAd->LatchRfRegs.R3 = R3;
5942 pAd->LatchRfRegs.R4 = R4;
5944 // Set RF value 1's set R3[bit2] = [0]
5945 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5946 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5947 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5948 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5952 // Set RF value 2's set R3[bit2] = [1]
5953 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5954 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5955 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5956 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5960 // Set RF value 3's set R3[bit2] = [0]
5961 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5962 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5963 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5964 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5976 // Change BBP setting during siwtch from a->g, g->a
5979 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5981 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5982 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5983 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5984 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.
5985 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5987 // Rx High power VGA offset for LNA select
5988 if (pAd->NicConfig2.field.ExternalLNAForG)
5990 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5991 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5995 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5996 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5999 // 5G band selection PIN, bit1 and bit2 are complement
6000 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6003 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6005 // Turn off unused PA or LNA when only 1T or 1R
6006 if (pAd->Antenna.field.TxPath == 1)
6008 TxPinCfg &= 0xFFFFFFF3;
6010 if (pAd->Antenna.field.RxPath == 1)
6012 TxPinCfg &= 0xFFFFF3FF;
6015 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6019 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6021 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6022 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6023 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6024 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.
6025 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6027 // Rx High power VGA offset for LNA select
6028 if (pAd->NicConfig2.field.ExternalLNAForA)
6030 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6034 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6037 // 5G band selection PIN, bit1 and bit2 are complement
6038 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6041 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6043 // Turn off unused PA or LNA when only 1T or 1R
6044 if (pAd->Antenna.field.TxPath == 1)
6046 TxPinCfg &= 0xFFFFFFF3;
6048 if (pAd->Antenna.field.RxPath == 1)
6050 TxPinCfg &= 0xFFFFF3FF;
6053 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6056 // R66 should be set according to Channel and use 20MHz when scanning
6057 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6059 RTMPSetAGCInitValue(pAd, BW_20);
6061 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6064 // On 11A, We should delay and wait RF/BBP to be stable
6065 // and the appropriate time should be 1000 micro seconds
6066 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6068 RTMPusecDelay(1000);
6070 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",
6073 (R3 & 0x00003e00) >> 9,
6074 (R4 & 0x000007c0) >> 6,
6075 pAd->Antenna.field.TxPath,
6076 pAd->LatchRfRegs.R1,
6077 pAd->LatchRfRegs.R2,
6078 pAd->LatchRfRegs.R3,
6079 pAd->LatchRfRegs.R4));
6083 ==========================================================================
6085 This function is required for 2421 only, and should not be used during
6086 site survey. It's only required after NIC decided to stay at a channel
6087 for a longer period.
6088 When this function is called, it's always after AsicSwitchChannel().
6090 IRQL = PASSIVE_LEVEL
6091 IRQL = DISPATCH_LEVEL
6093 ==========================================================================
6095 VOID AsicLockChannel(
6096 IN PRTMP_ADAPTER pAd,
6102 ==========================================================================
6105 IRQL = PASSIVE_LEVEL
6106 IRQL = DISPATCH_LEVEL
6108 ==========================================================================
6110 VOID AsicAntennaSelect(
6111 IN PRTMP_ADAPTER pAd,
6117 ========================================================================
6119 Routine Description:
6120 Antenna miscellaneous setting.
6123 pAd Pointer to our adapter
6124 BandState Indicate current Band State.
6129 IRQL <= DISPATCH_LEVEL
6132 1.) Frame End type control
6133 only valid for G only (RF_2527 & RF_2529)
6134 0: means DPDT, set BBP R4 bit 5 to 1
6135 1: means SPDT, set BBP R4 bit 5 to 0
6138 ========================================================================
6140 VOID AsicAntennaSetting(
6141 IN PRTMP_ADAPTER pAd,
6142 IN ABGBAND_STATE BandState)
6146 VOID AsicRfTuningExec(
6147 IN PVOID SystemSpecific1,
6148 IN PVOID FunctionContext,
6149 IN PVOID SystemSpecific2,
6150 IN PVOID SystemSpecific3)
6155 ==========================================================================
6157 Gives CCK TX rate 2 more dB TX power.
6158 This routine works only in LINK UP in INFRASTRUCTURE mode.
6160 calculate desired Tx power in RF R3.Tx0~5, should consider -
6161 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6162 1. TxPowerPercentage
6163 2. auto calibration based on TSSI feedback
6164 3. extra 2 db for CCK
6165 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6167 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6168 it should be called AFTER MlmeDynamicTxRatSwitching()
6169 ==========================================================================
6171 VOID AsicAdjustTxPower(
6172 IN PRTMP_ADAPTER pAd)
6176 BOOLEAN bAutoTxAgc = FALSE;
6177 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6178 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6179 PCHAR pTxAgcCompensate;
6183 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6185 if (pAd->CommonCfg.CentralChannel > 14)
6187 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6188 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6189 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6190 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6191 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6195 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6196 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6197 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6198 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6199 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6204 if (pAd->CommonCfg.Channel > 14)
6206 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6207 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6208 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6209 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6210 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6214 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6215 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6216 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6217 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6218 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6222 // TX power compensation for temperature variation based on TSSI. try every 4 second
6223 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6225 if (pAd->CommonCfg.Channel <= 14)
6228 bAutoTxAgc = pAd->bAutoTxAgcG;
6229 TssiRef = pAd->TssiRefG;
6230 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6231 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6232 TxAgcStep = pAd->TxAgcStepG;
6233 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6238 bAutoTxAgc = pAd->bAutoTxAgcA;
6239 TssiRef = pAd->TssiRefA;
6240 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6241 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6242 TxAgcStep = pAd->TxAgcStepA;
6243 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6248 /* BbpR1 is unsigned char */
6249 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6251 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6252 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6253 /* step value is defined in pAd->TxAgcStepG for tx power value */
6255 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6256 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6257 above value are examined in mass factory production */
6258 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6260 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6261 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6262 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6264 if (BbpR49 > pTssiMinusBoundary[1])
6266 // Reading is larger than the reference value
6267 // check for how large we need to decrease the Tx power
6268 for (idx = 1; idx < 5; idx++)
6270 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6273 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6274 // if (R3 > (ULONG) (TxAgcStep * (idx-1)))
6275 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6277 // *pTxAgcCompensate = -((UCHAR)R3);
6279 DeltaPwr += (*pTxAgcCompensate);
6280 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6281 BbpR49, TssiRef, TxAgcStep, idx-1));
6283 else if (BbpR49 < pTssiPlusBoundary[1])
6285 // Reading is smaller than the reference value
6286 // check for how large we need to increase the Tx power
6287 for (idx = 1; idx < 5; idx++)
6289 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6292 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6293 *pTxAgcCompensate = TxAgcStep * (idx-1);
6294 DeltaPwr += (*pTxAgcCompensate);
6295 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6296 BbpR49, TssiRef, TxAgcStep, idx-1));
6300 *pTxAgcCompensate = 0;
6301 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6302 BbpR49, TssiRef, TxAgcStep, 0));
6308 if (pAd->CommonCfg.Channel <= 14)
6310 bAutoTxAgc = pAd->bAutoTxAgcG;
6311 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6315 bAutoTxAgc = pAd->bAutoTxAgcA;
6316 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6320 DeltaPwr += (*pTxAgcCompensate);
6323 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6327 // Handle regulatory max tx power constrain
6330 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6331 UCHAR AdjustMaxTxPwr[40];
6333 if (pAd->CommonCfg.Channel > 14) // 5G band
6334 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6336 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6337 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6339 // error handling, range check
6340 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6342 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6346 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6348 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6350 // Adjust max tx power according to the relationship of tx power in E2PROM
6353 // CCK will have 4dBm larger than OFDM
6354 // Therefore, we should separate to parse the tx power field
6359 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6363 // CCK will have 4dBm larger than OFDM
6364 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6368 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6370 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6377 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6379 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6380 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6385 // Adjust tx power according to the relationship
6388 if (TxPwr[i] != 0xffffffff)
6392 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6394 // The system tx power is larger than the regulatory, the power should be restrain
6395 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6397 // decrease to zero and don't need to take care BBPR1
6398 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6399 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6403 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6406 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6408 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6413 #endif // SINGLE_SKU //
6415 /* calculate delta power based on the percentage specified from UI */
6416 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6417 // We lower TX power here according to the percentage specified from UI
6418 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6420 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6422 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6426 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6430 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6434 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6439 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6444 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6446 /* reset different new tx power for different TX rate */
6449 if (TxPwr[i] != 0xffffffff)
6453 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6455 if ((Value + DeltaPwr) < 0)
6457 Value = 0; /* min */
6459 else if ((Value + DeltaPwr) > 0xF)
6461 Value = 0xF; /* max */
6465 Value += DeltaPwr; /* temperature compensation */
6468 /* fill new value to CSR offset */
6469 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6472 /* write tx power value to CSR */
6473 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6474 TX power for OFDM 6M/9M
6475 TX power for CCK5.5M/11M
6476 TX power for CCK1M/2M */
6477 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6478 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6484 #ifdef CONFIG_STA_SUPPORT
6486 ==========================================================================
6488 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6489 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6490 the wakeup timer timeout. Driver has to issue a separate command to wake
6493 IRQL = DISPATCH_LEVEL
6495 ==========================================================================
6497 VOID AsicSleepThenAutoWakeup(
6498 IN PRTMP_ADAPTER pAd,
6499 IN USHORT TbttNumToNextWakeUp)
6501 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6505 ==========================================================================
6507 AsicForceWakeup() is used whenever manual wakeup is required
6508 AsicForceSleep() should only be used when not in INFRA BSS. When
6509 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6510 ==========================================================================
6512 VOID AsicForceSleep(
6513 IN PRTMP_ADAPTER pAd)
6519 ==========================================================================
6521 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6524 IRQL = PASSIVE_LEVEL
6525 IRQL = DISPATCH_LEVEL
6526 ==========================================================================
6528 VOID AsicForceWakeup(
6529 IN PRTMP_ADAPTER pAd,
6532 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6533 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6535 #endif // CONFIG_STA_SUPPORT //
6537 ==========================================================================
6541 IRQL = DISPATCH_LEVEL
6543 ==========================================================================
6546 IN PRTMP_ADAPTER pAd,
6550 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6551 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6553 Addr4 = (ULONG)(pBssid[0]) |
6554 (ULONG)(pBssid[1] << 8) |
6555 (ULONG)(pBssid[2] << 16) |
6556 (ULONG)(pBssid[3] << 24);
6557 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6560 // always one BSSID in STA mode
6561 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6563 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6566 VOID AsicSetMcastWC(
6567 IN PRTMP_ADAPTER pAd)
6569 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6572 pEntry->Sst = SST_ASSOC;
6573 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6574 pEntry->PsMode = PWR_ACTIVE;
6575 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6576 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6580 ==========================================================================
6583 IRQL = DISPATCH_LEVEL
6585 ==========================================================================
6587 VOID AsicDelWcidTab(
6588 IN PRTMP_ADAPTER pAd,
6591 ULONG Addr0 = 0x0, Addr1 = 0x0;
6594 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6595 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6596 RTMP_IO_WRITE32(pAd, offset, Addr0);
6598 RTMP_IO_WRITE32(pAd, offset, Addr1);
6602 ==========================================================================
6605 IRQL = DISPATCH_LEVEL
6607 ==========================================================================
6610 IN PRTMP_ADAPTER pAd)
6612 TX_LINK_CFG_STRUC TxLinkCfg;
6615 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6616 TxLinkCfg.field.TxRDGEn = 1;
6617 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6619 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6622 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6624 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6628 ==========================================================================
6631 IRQL = DISPATCH_LEVEL
6633 ==========================================================================
6635 VOID AsicDisableRDG(
6636 IN PRTMP_ADAPTER pAd)
6638 TX_LINK_CFG_STRUC TxLinkCfg;
6642 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6643 TxLinkCfg.field.TxRDGEn = 0;
6644 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6646 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6651 //if ( pAd->CommonCfg.bEnableTxBurst )
6652 // Data |= 0x60; // for performance issue not set the TXOP to 0
6654 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6655 #ifdef DOT11_N_SUPPORT
6656 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6657 #endif // DOT11_N_SUPPORT //
6660 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6661 if (pAd->CommonCfg.bEnableTxBurst)
6664 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6668 ==========================================================================
6671 IRQL = PASSIVE_LEVEL
6672 IRQL = DISPATCH_LEVEL
6674 ==========================================================================
6676 VOID AsicDisableSync(
6677 IN PRTMP_ADAPTER pAd)
6679 BCN_TIME_CFG_STRUC csr;
6681 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6683 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6684 // that NIC will never wakes up because TSF stops and no more
6686 pAd->TbttTickCount = 0;
6687 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6688 csr.field.bBeaconGen = 0;
6689 csr.field.bTBTTEnable = 0;
6690 csr.field.TsfSyncMode = 0;
6691 csr.field.bTsfTicking = 0;
6692 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6697 ==========================================================================
6700 IRQL = DISPATCH_LEVEL
6702 ==========================================================================
6704 VOID AsicEnableBssSync(
6705 IN PRTMP_ADAPTER pAd)
6707 BCN_TIME_CFG_STRUC csr;
6709 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6711 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6712 // RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);
6713 #ifdef CONFIG_STA_SUPPORT
6714 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6716 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6717 csr.field.bTsfTicking = 1;
6718 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6719 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6720 csr.field.bTBTTEnable = 1;
6722 #endif // CONFIG_STA_SUPPORT //
6723 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6727 ==========================================================================
6730 BEACON frame in shared memory should be built ok before this routine
6731 can be called. Otherwise, a garbage frame maybe transmitted out every
6734 IRQL = DISPATCH_LEVEL
6736 ==========================================================================
6738 VOID AsicEnableIbssSync(
6739 IN PRTMP_ADAPTER pAd)
6741 BCN_TIME_CFG_STRUC csr9;
6745 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6747 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6748 csr9.field.bBeaconGen = 0;
6749 csr9.field.bTBTTEnable = 0;
6750 csr9.field.bTsfTicking = 0;
6751 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6755 // move BEACON TXD and frame content to on-chip memory
6756 ptr = (PUCHAR)&pAd->BeaconTxWI;
6757 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6759 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6760 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6761 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6765 // start right after the 16-byte TXWI field
6766 ptr = pAd->BeaconBuf;
6767 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6769 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6770 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6771 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6777 // For Wi-Fi faily generated beacons between participating stations.
6778 // Set TBTT phase adaptive adjustment step to 8us (default 16us)
6779 // don't change settings 2006-5- by Jerry
6780 //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);
6782 // start sending BEACON
6783 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6784 csr9.field.bTsfTicking = 1;
6785 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6786 csr9.field.bTBTTEnable = 1;
6787 csr9.field.bBeaconGen = 1;
6788 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6792 ==========================================================================
6795 IRQL = PASSIVE_LEVEL
6796 IRQL = DISPATCH_LEVEL
6798 ==========================================================================
6800 VOID AsicSetEdcaParm(
6801 IN PRTMP_ADAPTER pAd,
6802 IN PEDCA_PARM pEdcaParm)
6804 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6805 AC_TXOP_CSR0_STRUC csr0;
6806 AC_TXOP_CSR1_STRUC csr1;
6807 AIFSN_CSR_STRUC AifsnCsr;
6808 CWMIN_CSR_STRUC CwminCsr;
6809 CWMAX_CSR_STRUC CwmaxCsr;
6816 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6818 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6819 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6820 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6822 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6823 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6826 //========================================================
6827 // MAC Register has a copy .
6828 //========================================================
6830 if( pAd->CommonCfg.bEnableTxBurst )
6832 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6833 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6836 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6838 // Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6840 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6841 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6842 Ac0Cfg.field.Aifsn = 2;
6843 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6845 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6846 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6847 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6848 Ac1Cfg.field.Aifsn = 2;
6849 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6851 if (pAd->CommonCfg.PhyMode == PHY_11B)
6853 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6854 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6858 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6859 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6861 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6862 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6863 Ac2Cfg.field.Aifsn = 2;
6864 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6865 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6866 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6867 Ac3Cfg.field.Aifsn = 2;
6868 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6870 //========================================================
6871 // DMA Register has a copy too.
6872 //========================================================
6873 csr0.field.Ac0Txop = 0; // QID_AC_BE
6874 csr0.field.Ac1Txop = 0; // QID_AC_BK
6875 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6876 if (pAd->CommonCfg.PhyMode == PHY_11B)
6878 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6879 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6883 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6884 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6886 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6889 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6890 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6891 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6892 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6893 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6896 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6897 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6898 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6899 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6900 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6902 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6904 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6908 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6909 //========================================================
6910 // MAC Register has a copy.
6911 //========================================================
6913 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6914 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6916 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6918 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6919 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6920 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6921 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6923 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6924 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6925 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6926 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6928 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6929 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6930 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6931 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6932 #ifdef CONFIG_STA_SUPPORT
6933 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6935 // Tuning for Wi-Fi WMM S06
6936 if (pAd->CommonCfg.bWiFiTest &&
6937 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6938 Ac2Cfg.field.Aifsn -= 1;
6940 // Tuning for TGn Wi-Fi 5.2.32
6941 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6942 if (STA_TGN_WIFI_ON(pAd) &&
6943 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6945 Ac0Cfg.field.Aifsn = 3;
6946 Ac2Cfg.field.AcTxop = 5;
6949 #endif // CONFIG_STA_SUPPORT //
6951 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6952 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6953 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6954 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6957 if (pAd->CommonCfg.bWiFiTest)
6959 if (Ac3Cfg.field.AcTxop == 102)
6961 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6962 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6963 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6964 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6965 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6968 //#endif // WIFI_TEST //
6970 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6971 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6972 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6973 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6976 //========================================================
6977 // DMA Register has a copy too.
6978 //========================================================
6979 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6980 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6981 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6983 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6984 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6985 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6988 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6989 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6990 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6991 #ifdef CONFIG_STA_SUPPORT
6992 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6993 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6994 #endif // CONFIG_STA_SUPPORT //
6995 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6998 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6999 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7000 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7001 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7002 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7005 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7006 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7007 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7008 #ifdef CONFIG_STA_SUPPORT
7009 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7011 // Tuning for Wi-Fi WMM S06
7012 if (pAd->CommonCfg.bWiFiTest &&
7013 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7014 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7016 // Tuning for TGn Wi-Fi 5.2.32
7017 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
7018 if (STA_TGN_WIFI_ON(pAd) &&
7019 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7021 AifsnCsr.field.Aifsn0 = 3;
7022 AifsnCsr.field.Aifsn2 = 7;
7026 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7028 #endif // CONFIG_STA_SUPPORT //
7030 #ifdef CONFIG_STA_SUPPORT
7031 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7032 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7033 #endif // CONFIG_STA_SUPPORT //
7034 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7036 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7039 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7040 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7041 pEdcaParm->Aifsn[0],
7042 pEdcaParm->Cwmin[0],
7043 pEdcaParm->Cwmax[0],
7044 pEdcaParm->Txop[0]<<5,
7045 pEdcaParm->bACM[0]));
7046 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7047 pEdcaParm->Aifsn[1],
7048 pEdcaParm->Cwmin[1],
7049 pEdcaParm->Cwmax[1],
7050 pEdcaParm->Txop[1]<<5,
7051 pEdcaParm->bACM[1]));
7052 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7053 pEdcaParm->Aifsn[2],
7054 pEdcaParm->Cwmin[2],
7055 pEdcaParm->Cwmax[2],
7056 pEdcaParm->Txop[2]<<5,
7057 pEdcaParm->bACM[2]));
7058 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7059 pEdcaParm->Aifsn[3],
7060 pEdcaParm->Cwmin[3],
7061 pEdcaParm->Cwmax[3],
7062 pEdcaParm->Txop[3]<<5,
7063 pEdcaParm->bACM[3]));
7069 ==========================================================================
7072 IRQL = PASSIVE_LEVEL
7073 IRQL = DISPATCH_LEVEL
7075 ==========================================================================
7077 VOID AsicSetSlotTime(
7078 IN PRTMP_ADAPTER pAd,
7079 IN BOOLEAN bUseShortSlotTime)
7082 UINT32 RegValue = 0;
7084 #ifdef CONFIG_STA_SUPPORT
7085 if (pAd->CommonCfg.Channel > 14)
7086 bUseShortSlotTime = TRUE;
7087 #endif // CONFIG_STA_SUPPORT //
7089 if (bUseShortSlotTime)
7090 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7092 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7094 SlotTime = (bUseShortSlotTime)? 9 : 20;
7096 #ifdef CONFIG_STA_SUPPORT
7097 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7099 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7100 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7101 #ifdef DOT11_N_SUPPORT
7102 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7103 #endif // DOT11_N_SUPPORT //
7106 // In this case, we will think it is doing Wi-Fi test
7107 // And we will not set to short slot when bEnableTxBurst is TRUE.
7109 else if (pAd->CommonCfg.bEnableTxBurst)
7112 #endif // CONFIG_STA_SUPPORT //
7115 // For some reasons, always set it to short slot time.
7117 // ToDo: Should consider capability with 11B
7119 #ifdef CONFIG_STA_SUPPORT
7120 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7122 if (pAd->StaCfg.BssType == BSS_ADHOC)
7125 #endif // CONFIG_STA_SUPPORT //
7127 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7128 RegValue = RegValue & 0xFFFFFF00;
7130 RegValue |= SlotTime;
7132 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7136 ========================================================================
7138 Add Shared key information into ASIC.
7139 Update shared key, TxMic and RxMic to Asic Shared key table
7140 Update its cipherAlg to Asic Shared key Mode.
7143 ========================================================================
7145 VOID AsicAddSharedKeyEntry(
7146 IN PRTMP_ADAPTER pAd,
7154 ULONG offset; //, csr0;
7155 SHAREDKEY_MODE_STRUC csr1;
7157 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7158 //============================================================================================
7160 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7161 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7162 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]));
7165 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7166 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7170 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7171 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7173 //============================================================================================
7175 // fill key material - key + TX MIC + RX MIC
7180 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7181 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7183 offset += MAX_LEN_OF_SHARE_KEY;
7186 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7192 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7198 // Update cipher algorithm. WSTA always use BSS0
7200 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7201 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7202 if ((BssIndex%2) == 0)
7205 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7206 else if (KeyIdx == 1)
7207 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7208 else if (KeyIdx == 2)
7209 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7211 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7216 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7217 else if (KeyIdx == 1)
7218 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7219 else if (KeyIdx == 2)
7220 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7222 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7224 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7225 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7229 // IRQL = DISPATCH_LEVEL
7230 VOID AsicRemoveSharedKeyEntry(
7231 IN PRTMP_ADAPTER pAd,
7236 SHAREDKEY_MODE_STRUC csr1;
7238 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7240 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7241 if ((BssIndex%2) == 0)
7244 csr1.field.Bss0Key0CipherAlg = 0;
7245 else if (KeyIdx == 1)
7246 csr1.field.Bss0Key1CipherAlg = 0;
7247 else if (KeyIdx == 2)
7248 csr1.field.Bss0Key2CipherAlg = 0;
7250 csr1.field.Bss0Key3CipherAlg = 0;
7255 csr1.field.Bss1Key0CipherAlg = 0;
7256 else if (KeyIdx == 1)
7257 csr1.field.Bss1Key1CipherAlg = 0;
7258 else if (KeyIdx == 2)
7259 csr1.field.Bss1Key2CipherAlg = 0;
7261 csr1.field.Bss1Key3CipherAlg = 0;
7263 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7264 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7265 ASSERT(BssIndex < 4);
7271 VOID AsicUpdateWCIDAttribute(
7272 IN PRTMP_ADAPTER pAd,
7276 IN BOOLEAN bUsePairewiseKeyTable)
7278 ULONG WCIDAttri = 0, offset;
7281 // Update WCID attribute.
7282 // Only TxKey could update WCID attribute.
7284 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7285 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7286 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7289 VOID AsicUpdateWCIDIVEIV(
7290 IN PRTMP_ADAPTER pAd,
7297 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7299 RTMP_IO_WRITE32(pAd, offset, uIV);
7300 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7303 VOID AsicUpdateRxWCIDTable(
7304 IN PRTMP_ADAPTER pAd,
7311 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7312 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7313 RTMP_IO_WRITE32(pAd, offset, Addr);
7314 Addr = pAddr[4] + (pAddr[5] << 8);
7315 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7320 ========================================================================
7322 Routine Description:
7323 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7326 pAd Pointer to our adapter
7327 WCID WCID Entry number.
7328 BssIndex BSSID index, station or none multiple BSSID support
7329 this value should be 0.
7330 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7331 pCipherKey Pointer to Cipher Key.
7332 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7333 otherwise PairewiseKey table
7334 bTxKey This is the transmit key if enabled.
7340 This routine will set the relative key stuff to Asic including WCID attribute,
7341 Cipher Key, Cipher algorithm and IV/EIV.
7343 IV/EIV will be update if this CipherKey is the transmission key because
7344 ASIC will base on IV's KeyID value to select Cipher Key.
7346 If bTxKey sets to FALSE, this is not the TX key, but it could be
7349 For AP mode bTxKey must be always set to TRUE.
7350 ========================================================================
7352 VOID AsicAddKeyEntry(
7353 IN PRTMP_ADAPTER pAd,
7357 IN PCIPHER_KEY pCipherKey,
7358 IN BOOLEAN bUsePairewiseKeyTable,
7362 // ULONG WCIDAttri = 0;
7364 PUCHAR pKey = pCipherKey->Key;
7365 // ULONG KeyLen = pCipherKey->KeyLen;
7366 PUCHAR pTxMic = pCipherKey->TxMic;
7367 PUCHAR pRxMic = pCipherKey->RxMic;
7368 PUCHAR pTxtsc = pCipherKey->TxTsc;
7369 UCHAR CipherAlg = pCipherKey->CipherAlg;
7370 SHAREDKEY_MODE_STRUC csr1;
7372 // ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY);
7374 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7376 // 1.) decide key table offset
7378 if (bUsePairewiseKeyTable)
7379 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7381 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7384 // 2.) Set Key to Asic
7386 //for (i = 0; i < KeyLen; i++)
7389 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7390 offset += MAX_LEN_OF_PEER_KEY;
7393 // 3.) Set MIC key if available
7397 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7399 offset += LEN_TKIP_TXMICK;
7403 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7408 // 4.) Modify IV/EIV if needs
7409 // This will force Asic to use this key ID by setting IV.
7420 IV4 = (KeyIdx << 6);
7421 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7422 IV4 |= 0x20; // turn on extension bit means EIV existence
7424 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7425 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7431 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7433 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7436 if (!bUsePairewiseKeyTable)
7439 // Only update the shared key security mode
7441 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7442 if ((BssIndex % 2) == 0)
7445 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7446 else if (KeyIdx == 1)
7447 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7448 else if (KeyIdx == 2)
7449 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7451 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7456 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7457 else if (KeyIdx == 1)
7458 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7459 else if (KeyIdx == 2)
7460 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7462 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7464 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7467 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7472 ========================================================================
7474 Add Pair-wise key material into ASIC.
7475 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7478 ========================================================================
7480 VOID AsicAddPairwiseKeyEntry(
7481 IN PRTMP_ADAPTER pAd,
7484 IN CIPHER_KEY *pCipherKey)
7488 PUCHAR pKey = pCipherKey->Key;
7489 PUCHAR pTxMic = pCipherKey->TxMic;
7490 PUCHAR pRxMic = pCipherKey->RxMic;
7492 UCHAR CipherAlg = pCipherKey->CipherAlg;
7496 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7498 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7500 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7503 RTMP_IO_READ32(pAd, offset + i, &Value);
7506 offset += MAX_LEN_OF_PEER_KEY;
7512 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7519 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7523 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7524 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7525 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]));
7528 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7529 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7533 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7534 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7538 ========================================================================
7540 Remove Pair-wise key material from ASIC.
7543 ========================================================================
7545 VOID AsicRemovePairwiseKeyEntry(
7546 IN PRTMP_ADAPTER pAd,
7553 // re-set the entry's WCID attribute as OPEN-NONE.
7554 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7555 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7556 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7559 BOOLEAN AsicSendCommandToMcu(
7560 IN PRTMP_ADAPTER pAd,
7566 HOST_CMD_CSR_STRUC H2MCmd;
7567 H2M_MAILBOX_STRUC H2MMailbox;
7571 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7572 if (H2MMailbox.field.Owner == 0)
7581 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7587 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7588 H2MMailbox.field.CmdToken = Token;
7589 H2MMailbox.field.HighByte = Arg1;
7590 H2MMailbox.field.LowByte = Arg0;
7591 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7594 H2MCmd.field.HostCommand = Command;
7595 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7597 if (Command != 0x80)
7606 ========================================================================
7608 Routine Description:
7609 Verify the support rate for different PHY type
7612 pAd Pointer to our adapter
7617 IRQL = PASSIVE_LEVEL
7619 ========================================================================
7621 VOID RTMPCheckRates(
7622 IN PRTMP_ADAPTER pAd,
7623 IN OUT UCHAR SupRate[],
7624 IN OUT UCHAR *SupRateLen)
7626 UCHAR RateIdx, i, j;
7627 UCHAR NewRate[12], NewRateLen;
7631 if (pAd->CommonCfg.PhyMode == PHY_11B)
7636 // Check for support rates exclude basic rate bit
7637 for (i = 0; i < *SupRateLen; i++)
7638 for (j = 0; j < RateIdx; j++)
7639 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7640 NewRate[NewRateLen++] = SupRate[i];
7642 *SupRateLen = NewRateLen;
7643 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7646 #ifdef CONFIG_STA_SUPPORT
7647 #ifdef DOT11_N_SUPPORT
7648 BOOLEAN RTMPCheckChannel(
7649 IN PRTMP_ADAPTER pAd,
7650 IN UCHAR CentralChannel,
7654 UCHAR UpperChannel = 0, LowerChannel = 0;
7655 UCHAR NoEffectChannelinList = 0;
7657 // Find upper and lower channel according to 40MHz current operation.
7658 if (CentralChannel < Channel)
7660 UpperChannel = Channel;
7661 if (CentralChannel > 2)
7662 LowerChannel = CentralChannel - 2;
7666 else if (CentralChannel > Channel)
7668 UpperChannel = CentralChannel + 2;
7669 LowerChannel = Channel;
7672 for (k = 0;k < pAd->ChannelListNum;k++)
7674 if (pAd->ChannelList[k].Channel == UpperChannel)
7676 NoEffectChannelinList ++;
7678 if (pAd->ChannelList[k].Channel == LowerChannel)
7680 NoEffectChannelinList ++;
7684 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7685 if (NoEffectChannelinList == 2)
7692 ========================================================================
7694 Routine Description:
7695 Verify the support rate for HT phy type
7698 pAd Pointer to our adapter
7701 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7703 IRQL = PASSIVE_LEVEL
7705 ========================================================================
7707 BOOLEAN RTMPCheckHt(
7708 IN PRTMP_ADAPTER pAd,
7710 IN HT_CAPABILITY_IE *pHtCapability,
7711 IN ADD_HT_INFO_IE *pAddHtInfo)
7713 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7716 // If use AMSDU, set flag.
7717 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7718 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7719 // Save Peer Capability
7720 if (pHtCapability->HtCapInfo.ShortGIfor20)
7721 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7722 if (pHtCapability->HtCapInfo.ShortGIfor40)
7723 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7724 if (pHtCapability->HtCapInfo.TxSTBC)
7725 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7726 if (pHtCapability->HtCapInfo.RxSTBC)
7727 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7728 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7730 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7733 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7735 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7738 // Will check ChannelWidth for MCSSet[4] below
7739 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7740 switch (pAd->CommonCfg.RxStream)
7743 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7744 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7745 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7746 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7749 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7750 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7751 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7752 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7755 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7756 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7757 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7758 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7762 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7764 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7765 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7766 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7768 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7770 // Send Assoc Req with my HT capability.
7771 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7772 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7773 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7774 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7775 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7776 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7777 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7778 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7779 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7780 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7781 if (pAd->CommonCfg.bRdg)
7783 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7784 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7787 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7788 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7790 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7793 #endif // DOT11_N_SUPPORT //
7794 #endif // CONFIG_STA_SUPPORT //
7797 ========================================================================
7799 Routine Description:
7800 Verify the support rate for different PHY type
7803 pAd Pointer to our adapter
7808 IRQL = PASSIVE_LEVEL
7810 ========================================================================
7812 VOID RTMPUpdateMlmeRate(
7813 IN PRTMP_ADAPTER pAd)
7816 UCHAR ProperMlmeRate; //= RATE_54;
7817 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7818 BOOLEAN bMatch = FALSE;
7820 switch (pAd->CommonCfg.PhyMode)
7823 ProperMlmeRate = RATE_11;
7824 MinimumRate = RATE_1;
7826 case PHY_11BG_MIXED:
7827 #ifdef DOT11_N_SUPPORT
7828 case PHY_11ABGN_MIXED:
7829 case PHY_11BGN_MIXED:
7830 #endif // DOT11_N_SUPPORT //
7831 if ((pAd->MlmeAux.SupRateLen == 4) &&
7832 (pAd->MlmeAux.ExtRateLen == 0))
7834 ProperMlmeRate = RATE_11;
7836 ProperMlmeRate = RATE_24;
7838 if (pAd->MlmeAux.Channel <= 14)
7839 MinimumRate = RATE_1;
7841 MinimumRate = RATE_6;
7844 #ifdef DOT11_N_SUPPORT
7845 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7846 case PHY_11GN_MIXED:
7847 case PHY_11AGN_MIXED:
7848 case PHY_11AN_MIXED:
7850 #endif // DOT11_N_SUPPORT //
7851 ProperMlmeRate = RATE_24;
7852 MinimumRate = RATE_6;
7854 case PHY_11ABG_MIXED:
7855 ProperMlmeRate = RATE_24;
7856 if (pAd->MlmeAux.Channel <= 14)
7857 MinimumRate = RATE_1;
7859 MinimumRate = RATE_6;
7862 ProperMlmeRate = RATE_1;
7863 MinimumRate = RATE_1;
7867 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7869 for (j = 0; j < RateIdx; j++)
7871 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7873 if (j == ProperMlmeRate)
7885 if (bMatch == FALSE)
7887 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7889 for (j = 0; j < RateIdx; j++)
7891 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7893 if (j == ProperMlmeRate)
7906 if (bMatch == FALSE)
7908 ProperMlmeRate = MinimumRate;
7911 pAd->CommonCfg.MlmeRate = MinimumRate;
7912 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7913 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7915 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7916 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7917 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7918 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7922 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7923 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7924 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7925 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7928 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7932 IN PRTMP_ADAPTER pAd,
7939 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7944 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7946 larger = max(Rssi0, Rssi1);
7949 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7951 larger = max(larger, Rssi2);
7961 ========================================================================
7962 Routine Description:
7963 Periodic evaluate antenna link status
7966 pAd - Adapter pointer
7971 ========================================================================
7973 VOID AsicEvaluateRxAnt(
7974 IN PRTMP_ADAPTER pAd)
7981 #endif // RALINK_ATE //
7984 #ifdef CONFIG_STA_SUPPORT
7985 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7987 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7988 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7989 fRTMP_ADAPTER_RADIO_OFF |
7990 fRTMP_ADAPTER_NIC_NOT_EXIST |
7991 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7994 if (pAd->StaCfg.Psm == PWR_SAVE)
7997 #endif // CONFIG_STA_SUPPORT //
7999 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8001 if(pAd->Antenna.field.RxPath == 3)
8005 else if(pAd->Antenna.field.RxPath == 2)
8009 else if(pAd->Antenna.field.RxPath == 1)
8013 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8014 #ifdef CONFIG_STA_SUPPORT
8015 #endif // CONFIG_STA_SUPPORT //
8016 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8019 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8020 pAd->RalinkCounters.OneSecTxRetryOkCount +
8021 pAd->RalinkCounters.OneSecTxFailCount;
8023 if (TxTotalCnt > 50)
8025 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8026 pAd->Mlme.bLowThroughput = FALSE;
8030 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8031 pAd->Mlme.bLowThroughput = TRUE;
8037 ========================================================================
8038 Routine Description:
8039 After evaluation, check antenna link status
8042 pAd - Adapter pointer
8047 ========================================================================
8049 VOID AsicRxAntEvalTimeout(
8050 IN PVOID SystemSpecific1,
8051 IN PVOID FunctionContext,
8052 IN PVOID SystemSpecific2,
8053 IN PVOID SystemSpecific3)
8055 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8056 #ifdef CONFIG_STA_SUPPORT
8058 CHAR larger = -127, rssi0, rssi1, rssi2;
8059 #endif // CONFIG_STA_SUPPORT //
8064 #endif // RALINK_ATE //
8067 #ifdef CONFIG_STA_SUPPORT
8068 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8070 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8071 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8072 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8073 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8076 if (pAd->StaCfg.Psm == PWR_SAVE)
8080 // if the traffic is low, use average rssi as the criteria
8081 if (pAd->Mlme.bLowThroughput == TRUE)
8083 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8084 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8085 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8089 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8090 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8091 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8094 if(pAd->Antenna.field.RxPath == 3)
8096 larger = max(rssi0, rssi1);
8098 if (larger > (rssi2 + 20))
8099 pAd->Mlme.RealRxPath = 2;
8101 pAd->Mlme.RealRxPath = 3;
8103 else if(pAd->Antenna.field.RxPath == 2)
8105 if (rssi0 > (rssi1 + 20))
8106 pAd->Mlme.RealRxPath = 1;
8108 pAd->Mlme.RealRxPath = 2;
8111 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8113 if(pAd->Mlme.RealRxPath == 3)
8117 else if(pAd->Mlme.RealRxPath == 2)
8121 else if(pAd->Mlme.RealRxPath == 1)
8125 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8128 #endif // CONFIG_STA_SUPPORT //
8134 VOID APSDPeriodicExec(
8135 IN PVOID SystemSpecific1,
8136 IN PVOID FunctionContext,
8137 IN PVOID SystemSpecific2,
8138 IN PVOID SystemSpecific3)
8140 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8142 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8145 pAd->CommonCfg.TriggerTimerCount++;
8147 // Driver should not send trigger frame, it should be send by application layer
8149 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
8150 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
8151 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
8153 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
8154 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
8155 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
8156 pAd->CommonCfg.TriggerTimerCount = 0;
8157 pAd->CommonCfg.bInServicePeriod = TRUE;
8162 ========================================================================
8163 Routine Description:
8164 Set/reset MAC registers according to bPiggyBack parameter
8167 pAd - Adapter pointer
8168 bPiggyBack - Enable / Disable Piggy-Back
8173 ========================================================================
8175 VOID RTMPSetPiggyBack(
8176 IN PRTMP_ADAPTER pAd,
8177 IN BOOLEAN bPiggyBack)
8179 TX_LINK_CFG_STRUC TxLinkCfg;
8181 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8183 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8184 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8188 ========================================================================
8189 Routine Description:
8190 check if this entry need to switch rate automatically
8200 ========================================================================
8202 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8203 IN PRTMP_ADAPTER pAd,
8204 IN PMAC_TABLE_ENTRY pEntry)
8206 BOOLEAN result = TRUE;
8209 #ifdef CONFIG_STA_SUPPORT
8210 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8212 // only associated STA counts
8213 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8215 result = pAd->StaCfg.bAutoTxRateSwitch;
8220 #ifdef QOS_DLS_SUPPORT
8221 if (pEntry && (pEntry->ValidAsDls))
8222 result = pAd->StaCfg.bAutoTxRateSwitch;
8223 #endif // QOS_DLS_SUPPORT //
8225 #endif // CONFIG_STA_SUPPORT //
8233 BOOLEAN RTMPAutoRateSwitchCheck(
8234 IN PRTMP_ADAPTER pAd)
8237 #ifdef CONFIG_STA_SUPPORT
8238 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8240 if (pAd->StaCfg.bAutoTxRateSwitch)
8243 #endif // CONFIG_STA_SUPPORT //
8249 ========================================================================
8250 Routine Description:
8251 check if this entry need to fix tx legacy rate
8261 ========================================================================
8263 UCHAR RTMPStaFixedTxMode(
8264 IN PRTMP_ADAPTER pAd,
8265 IN PMAC_TABLE_ENTRY pEntry)
8267 UCHAR tx_mode = FIXED_TXMODE_HT;
8270 #ifdef CONFIG_STA_SUPPORT
8271 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8273 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8275 #endif // CONFIG_STA_SUPPORT //
8281 ========================================================================
8282 Routine Description:
8283 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8293 ========================================================================
8295 VOID RTMPUpdateLegacyTxSetting(
8296 UCHAR fixed_tx_mode,
8297 PMAC_TABLE_ENTRY pEntry)
8299 HTTRANSMIT_SETTING TransmitSetting;
8301 if (fixed_tx_mode == FIXED_TXMODE_HT)
8304 TransmitSetting.word = 0;
8306 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8307 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8309 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8311 TransmitSetting.field.MODE = MODE_CCK;
8312 // CCK mode allow MCS 0~3
8313 if (TransmitSetting.field.MCS > MCS_3)
8314 TransmitSetting.field.MCS = MCS_3;
8318 TransmitSetting.field.MODE = MODE_OFDM;
8319 // OFDM mode allow MCS 0~7
8320 if (TransmitSetting.field.MCS > MCS_7)
8321 TransmitSetting.field.MCS = MCS_7;
8324 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8326 pEntry->HTPhyMode.word = TransmitSetting.word;
8327 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8328 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8332 #ifdef CONFIG_STA_SUPPORT
8334 ==========================================================================
8336 dynamic tune BBP R66 to find a balance between sensibility and
8339 IRQL = DISPATCH_LEVEL
8341 ==========================================================================
8343 VOID AsicStaBbpTuning(
8344 IN PRTMP_ADAPTER pAd)
8346 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8349 // 2860C did not support Fase CCA, therefore can't tune
8350 if (pAd->MACVersion == 0x28600100)
8356 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8359 if ((pAd->OpMode == OPMODE_STA)
8360 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8362 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8365 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8368 if (pAd->Antenna.field.RxPath > 1)
8369 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8371 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8373 if (pAd->LatchRfRegs.Channel <= 14)
8376 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8377 // Otherwise, it will have some throughput side effect when low RSSI
8380 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8382 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8383 if (OrigR66Value != R66)
8385 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8390 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8391 if (OrigR66Value != R66)
8393 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8400 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8402 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8403 if (OrigR66Value != R66)
8405 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8410 R66 = 0x2E + GET_LNA_GAIN(pAd);
8411 if (OrigR66Value != R66)
8413 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8420 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8422 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8424 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8425 if (OrigR66Value != R66)
8427 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8432 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8433 if (OrigR66Value != R66)
8435 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8441 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8443 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8444 if (OrigR66Value != R66)
8446 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8451 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8452 if (OrigR66Value != R66)
8454 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8463 #endif // CONFIG_STA_SUPPORT //
8465 VOID RTMPSetAGCInitValue(
8466 IN PRTMP_ADAPTER pAd,
8471 if (pAd->LatchRfRegs.Channel <= 14)
8473 R66 = 0x2E + GET_LNA_GAIN(pAd);
8474 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8478 if (BandWidth == BW_20)
8480 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8481 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8483 #ifdef DOT11_N_SUPPORT
8486 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8487 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8489 #endif // DOT11_N_SUPPORT //
8494 VOID AsicTurnOffRFClk(
8495 IN PRTMP_ADAPTER pAd,
8500 UINT32 R1 = 0, R2 = 0, R3 = 0;
8502 RTMP_RF_REGS *RFRegTable;
8504 RFRegTable = RF2850RegTable;
8506 switch (pAd->RfIcType)
8513 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8515 if (Channel == RFRegTable[index].Channel)
8517 R1 = RFRegTable[index].R1 & 0xffffdfff;
8518 R2 = RFRegTable[index].R2 & 0xfffbffff;
8519 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8521 RTMP_RF_IO_WRITE32(pAd, R1);
8522 RTMP_RF_IO_WRITE32(pAd, R2);
8524 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8525 // Set RF R2 bit18=0, R3 bit[18:19]=0
8526 //if (pAd->StaCfg.bRadio == FALSE)
8529 RTMP_RF_IO_WRITE32(pAd, R3);
8531 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8532 Channel, pAd->RfIcType, R2, R3));
8535 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8536 Channel, pAd->RfIcType, R2));
8548 VOID AsicTurnOnRFClk(
8549 IN PRTMP_ADAPTER pAd,
8554 UINT32 R1 = 0, R2 = 0, R3 = 0;
8556 RTMP_RF_REGS *RFRegTable;
8558 RFRegTable = RF2850RegTable;
8560 switch (pAd->RfIcType)
8567 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8569 if (Channel == RFRegTable[index].Channel)
8571 R3 = pAd->LatchRfRegs.R3;
8574 RTMP_RF_IO_WRITE32(pAd, R3);
8576 R1 = RFRegTable[index].R1;
8577 RTMP_RF_IO_WRITE32(pAd, R1);
8579 R2 = RFRegTable[index].R2;
8580 if (pAd->Antenna.field.TxPath == 1)
8582 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8585 if (pAd->Antenna.field.RxPath == 2)
8587 R2 |= 0x40; // write 1 to off Rxpath.
8589 else if (pAd->Antenna.field.RxPath == 1)
8591 R2 |= 0x20040; // write 1 to off RxPath
8593 RTMP_RF_IO_WRITE32(pAd, R2);
8604 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",