2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-08-25 Modify from RT2500 code base
36 John Chang 2004-09-06 modified for RT2600
39 #include "../rt_config.h"
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
44 UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45 UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
46 UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
47 UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
48 UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
49 UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
50 UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
51 UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
52 UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
53 #ifdef CONFIG_STA_SUPPORT
54 #ifdef DOT11_N_SUPPORT
55 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
56 #endif // DOT11_N_SUPPORT //
57 #endif // CONFIG_STA_SUPPORT //
59 UCHAR RateSwitchTable[] = {
60 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
61 0x11, 0x00, 0, 0, 0, // Initial used item after association
62 0x00, 0x00, 0, 40, 101,
63 0x01, 0x00, 1, 40, 50,
64 0x02, 0x00, 2, 35, 45,
65 0x03, 0x00, 3, 20, 45,
66 0x04, 0x21, 0, 30, 50,
67 0x05, 0x21, 1, 20, 50,
68 0x06, 0x21, 2, 20, 50,
69 0x07, 0x21, 3, 15, 50,
70 0x08, 0x21, 4, 15, 30,
71 0x09, 0x21, 5, 10, 25,
74 0x0c, 0x20, 12, 15, 30,
75 0x0d, 0x20, 13, 8, 20,
76 0x0e, 0x20, 14, 8, 20,
77 0x0f, 0x20, 15, 8, 25,
78 0x10, 0x22, 15, 8, 25,
96 UCHAR RateSwitchTable11B[] = {
97 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
98 0x04, 0x03, 0, 0, 0, // Initial used item after association
99 0x00, 0x00, 0, 40, 101,
100 0x01, 0x00, 1, 40, 50,
101 0x02, 0x00, 2, 35, 45,
102 0x03, 0x00, 3, 20, 45,
105 UCHAR RateSwitchTable11BG[] = {
106 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
107 0x0a, 0x00, 0, 0, 0, // Initial used item after association
108 0x00, 0x00, 0, 40, 101,
109 0x01, 0x00, 1, 40, 50,
110 0x02, 0x00, 2, 35, 45,
111 0x03, 0x00, 3, 20, 45,
112 0x04, 0x10, 2, 20, 35,
113 0x05, 0x10, 3, 16, 35,
114 0x06, 0x10, 4, 10, 25,
115 0x07, 0x10, 5, 16, 25,
116 0x08, 0x10, 6, 10, 25,
117 0x09, 0x10, 7, 10, 13,
120 UCHAR RateSwitchTable11G[] = {
121 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
122 0x08, 0x00, 0, 0, 0, // Initial used item after association
123 0x00, 0x10, 0, 20, 101,
124 0x01, 0x10, 1, 20, 35,
125 0x02, 0x10, 2, 20, 35,
126 0x03, 0x10, 3, 16, 35,
127 0x04, 0x10, 4, 10, 25,
128 0x05, 0x10, 5, 16, 25,
129 0x06, 0x10, 6, 10, 25,
130 0x07, 0x10, 7, 10, 13,
133 #ifdef DOT11_N_SUPPORT
134 UCHAR RateSwitchTable11N1S[] = {
135 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
136 0x09, 0x00, 0, 0, 0, // Initial used item after association
137 0x00, 0x21, 0, 30, 101,
138 0x01, 0x21, 1, 20, 50,
139 0x02, 0x21, 2, 20, 50,
140 0x03, 0x21, 3, 15, 50,
141 0x04, 0x21, 4, 15, 30,
142 0x05, 0x21, 5, 10, 25,
143 0x06, 0x21, 6, 8, 14,
144 0x07, 0x21, 7, 8, 14,
145 0x08, 0x23, 7, 8, 14,
148 UCHAR RateSwitchTable11N2S[] = {
149 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
150 0x0a, 0x00, 0, 0, 0, // Initial used item after association
151 0x00, 0x21, 0, 30, 101,
152 0x01, 0x21, 1, 20, 50,
153 0x02, 0x21, 2, 20, 50,
154 0x03, 0x21, 3, 15, 50,
155 0x04, 0x21, 4, 15, 30,
156 0x05, 0x20, 12, 15, 30,
157 0x06, 0x20, 13, 8, 20,
158 0x07, 0x20, 14, 8, 20,
159 0x08, 0x20, 15, 8, 25,
160 0x09, 0x22, 15, 8, 25,
163 UCHAR RateSwitchTable11N3S[] = {
164 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
165 0x0a, 0x00, 0, 0, 0, // Initial used item after association
166 0x00, 0x21, 0, 30, 101,
167 0x01, 0x21, 1, 20, 50,
168 0x02, 0x21, 2, 20, 50,
169 0x03, 0x21, 3, 15, 50,
170 0x04, 0x21, 4, 15, 30,
171 0x05, 0x20, 12, 15, 30,
172 0x06, 0x20, 13, 8, 20,
173 0x07, 0x20, 14, 8, 20,
174 0x08, 0x20, 15, 8, 25,
175 0x09, 0x22, 15, 8, 25,
178 UCHAR RateSwitchTable11N2SForABand[] = {
179 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
180 0x0b, 0x09, 0, 0, 0, // Initial used item after association
181 0x00, 0x21, 0, 30, 101,
182 0x01, 0x21, 1, 20, 50,
183 0x02, 0x21, 2, 20, 50,
184 0x03, 0x21, 3, 15, 50,
185 0x04, 0x21, 4, 15, 30,
186 0x05, 0x21, 5, 15, 30,
187 0x06, 0x20, 12, 15, 30,
188 0x07, 0x20, 13, 8, 20,
189 0x08, 0x20, 14, 8, 20,
190 0x09, 0x20, 15, 8, 25,
191 0x0a, 0x22, 15, 8, 25,
194 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
195 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
196 0x0b, 0x09, 0, 0, 0, // Initial used item after association
197 0x00, 0x21, 0, 30, 101,
198 0x01, 0x21, 1, 20, 50,
199 0x02, 0x21, 2, 20, 50,
200 0x03, 0x21, 3, 15, 50,
201 0x04, 0x21, 4, 15, 30,
202 0x05, 0x21, 5, 15, 30,
203 0x06, 0x20, 12, 15, 30,
204 0x07, 0x20, 13, 8, 20,
205 0x08, 0x20, 14, 8, 20,
206 0x09, 0x20, 15, 8, 25,
207 0x0a, 0x22, 15, 8, 25,
210 UCHAR RateSwitchTable11BGN1S[] = {
211 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
212 0x0d, 0x00, 0, 0, 0, // Initial used item after association
213 0x00, 0x00, 0, 40, 101,
214 0x01, 0x00, 1, 40, 50,
215 0x02, 0x00, 2, 35, 45,
216 0x03, 0x00, 3, 20, 45,
217 0x04, 0x21, 0, 30,101, //50
218 0x05, 0x21, 1, 20, 50,
219 0x06, 0x21, 2, 20, 50,
220 0x07, 0x21, 3, 15, 50,
221 0x08, 0x21, 4, 15, 30,
222 0x09, 0x21, 5, 10, 25,
223 0x0a, 0x21, 6, 8, 14,
224 0x0b, 0x21, 7, 8, 14,
225 0x0c, 0x23, 7, 8, 14,
228 UCHAR RateSwitchTable11BGN2S[] = {
229 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
230 0x0a, 0x00, 0, 0, 0, // Initial used item after association
231 0x00, 0x21, 0, 30,101, //50
232 0x01, 0x21, 1, 20, 50,
233 0x02, 0x21, 2, 20, 50,
234 0x03, 0x21, 3, 15, 50,
235 0x04, 0x21, 4, 15, 30,
236 0x05, 0x20, 12, 15, 30,
237 0x06, 0x20, 13, 8, 20,
238 0x07, 0x20, 14, 8, 20,
239 0x08, 0x20, 15, 8, 25,
240 0x09, 0x22, 15, 8, 25,
243 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
244 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
245 0x0a, 0x00, 0, 0, 0, // Initial used item after association
246 0x00, 0x21, 0, 30,101, //50
247 0x01, 0x21, 1, 20, 50,
248 0x02, 0x21, 2, 20, 50,
249 0x03, 0x21, 3, 20, 50,
250 0x04, 0x21, 4, 15, 50,
251 0x05, 0x20, 20, 15, 30,
252 0x06, 0x20, 21, 8, 20,
253 0x07, 0x20, 22, 8, 20,
254 0x08, 0x20, 23, 8, 25,
255 0x09, 0x22, 23, 8, 25,
258 UCHAR RateSwitchTable11BGN2SForABand[] = {
259 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
260 0x0b, 0x09, 0, 0, 0, // Initial used item after association
261 0x00, 0x21, 0, 30,101, //50
262 0x01, 0x21, 1, 20, 50,
263 0x02, 0x21, 2, 20, 50,
264 0x03, 0x21, 3, 15, 50,
265 0x04, 0x21, 4, 15, 30,
266 0x05, 0x21, 5, 15, 30,
267 0x06, 0x20, 12, 15, 30,
268 0x07, 0x20, 13, 8, 20,
269 0x08, 0x20, 14, 8, 20,
270 0x09, 0x20, 15, 8, 25,
271 0x0a, 0x22, 15, 8, 25,
274 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
275 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
276 0x0c, 0x09, 0, 0, 0, // Initial used item after association
277 0x00, 0x21, 0, 30,101, //50
278 0x01, 0x21, 1, 20, 50,
279 0x02, 0x21, 2, 20, 50,
280 0x03, 0x21, 3, 15, 50,
281 0x04, 0x21, 4, 15, 30,
282 0x05, 0x21, 5, 15, 30,
283 0x06, 0x21, 12, 15, 30,
284 0x07, 0x20, 20, 15, 30,
285 0x08, 0x20, 21, 8, 20,
286 0x09, 0x20, 22, 8, 20,
287 0x0a, 0x20, 23, 8, 25,
288 0x0b, 0x22, 23, 8, 25,
290 #endif // DOT11_N_SUPPORT //
292 PUCHAR ReasonString[] = {
294 /* 1 */ "Unspecified Reason",
295 /* 2 */ "Previous Auth no longer valid",
296 /* 3 */ "STA is leaving / has left",
297 /* 4 */ "DIS-ASSOC due to inactivity",
298 /* 5 */ "AP unable to hanle all associations",
299 /* 6 */ "class 2 error",
300 /* 7 */ "class 3 error",
301 /* 8 */ "STA is leaving / has left",
302 /* 9 */ "require auth before assoc/re-assoc",
306 /* 13 */ "invalid IE",
307 /* 14 */ "MIC error",
308 /* 15 */ "4-way handshake timeout",
309 /* 16 */ "2-way (group key) handshake timeout",
310 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
314 extern UCHAR OfdmRateToRxwiMCS[];
315 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
316 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
317 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
318 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
319 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
321 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
322 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
323 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
325 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
326 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
327 // clean environment.
328 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
329 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
331 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
332 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
334 UCHAR SsidIe = IE_SSID;
335 UCHAR SupRateIe = IE_SUPP_RATES;
336 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
337 #ifdef DOT11_N_SUPPORT
338 UCHAR HtCapIe = IE_HT_CAP;
339 UCHAR AddHtInfoIe = IE_ADD_HT;
340 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
342 UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
343 #endif // DOT11N_DRAFT3 //
344 #endif // DOT11_N_SUPPORT //
345 UCHAR ErpIe = IE_ERP;
346 UCHAR DsIe = IE_DS_PARM;
347 UCHAR TimIe = IE_TIM;
348 UCHAR WpaIe = IE_WPA;
349 UCHAR Wpa2Ie = IE_WPA2;
350 UCHAR IbssIe = IE_IBSS_PARM;
351 UCHAR Ccx2Ie = IE_CCX_V2;
353 extern UCHAR WPA_OUI[];
355 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
357 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
358 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
360 // Reset the RFIC setting to new series
361 RTMP_RF_REGS RF2850RegTable[] = {
362 // ch R1 R2 R3(TX0~4=0) R4
363 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
364 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
365 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
366 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
367 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
368 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
369 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
370 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
371 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
372 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
373 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
374 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
375 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
376 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
378 // 802.11 UNI / HyperLan 2
379 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
380 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
381 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
382 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
383 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
384 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
385 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
386 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
387 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
388 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
389 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
390 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
393 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
395 // 2008.04.30 modified
396 // The system team has AN to improve the EVM value
397 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
398 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
399 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
400 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
402 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
403 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
404 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
405 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
406 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
407 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
408 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
409 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
410 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
411 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
412 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
413 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
416 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
417 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
418 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
419 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
420 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
421 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
422 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
425 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
426 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
427 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
428 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
429 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
430 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
431 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
433 // still lack of MMAC(Japan) ch 34,38,42,46
435 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
437 FREQUENCY_ITEM FreqItems3020[] =
439 /**************************************************/
440 // ISM : 2.4 to 2.483 GHz //
441 /**************************************************/
443 /**************************************************/
444 //-CH---N-------R---K-----------
460 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
463 ==========================================================================
465 initialize the MLME task and its data structure (queue, spinlock,
466 timer, state machines).
471 always return NDIS_STATUS_SUCCESS
473 ==========================================================================
475 NDIS_STATUS MlmeInit(
476 IN PRTMP_ADAPTER pAd)
478 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
480 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
484 Status = MlmeQueueInit(&pAd->Mlme.Queue);
485 if(Status != NDIS_STATUS_SUCCESS)
488 pAd->Mlme.bRunning = FALSE;
489 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
491 #ifdef CONFIG_STA_SUPPORT
492 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
494 BssTableInit(&pAd->ScanTab);
496 // init STA state machines
497 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
498 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
499 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
500 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
501 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
502 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
504 #ifdef QOS_DLS_SUPPORT
505 DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc);
506 #endif // QOS_DLS_SUPPORT //
509 // Since we are using switch/case to implement it, the init is different from the above
510 // state machine init
511 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
513 #endif // CONFIG_STA_SUPPORT //
517 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
519 // Init mlme periodic timer
520 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
522 // Set mlme periodic timer
523 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
525 // software-based RX Antenna diversity
526 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
529 #ifdef CONFIG_STA_SUPPORT
530 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
532 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
534 // only PCIe cards need these two timers
535 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
536 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
539 #endif // CONFIG_STA_SUPPORT //
543 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
549 ==========================================================================
551 main loop of the MLME
553 Mlme has to be initialized, and there are something inside the queue
555 This function is invoked from MPSetInformation and MPReceive;
556 This task guarantee only one MlmeHandler will run.
558 IRQL = DISPATCH_LEVEL
560 ==========================================================================
563 IN PRTMP_ADAPTER pAd)
565 MLME_QUEUE_ELEM *Elem = NULL;
567 // Only accept MLME and Frame from peer side, no other (control/data) frame should
568 // get into this state machine
570 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
571 if(pAd->Mlme.bRunning)
573 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
578 pAd->Mlme.bRunning = TRUE;
580 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
582 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
584 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
585 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
586 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
588 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
592 //From message type, determine which state machine I should drive
593 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
596 // if dequeue success
597 switch (Elem->Machine)
599 // STA state machines
600 #ifdef CONFIG_STA_SUPPORT
601 case ASSOC_STATE_MACHINE:
602 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
604 case AUTH_STATE_MACHINE:
605 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
607 case AUTH_RSP_STATE_MACHINE:
608 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
610 case SYNC_STATE_MACHINE:
611 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
613 case MLME_CNTL_STATE_MACHINE:
614 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
616 case WPA_PSK_STATE_MACHINE:
617 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
620 case LEAP_STATE_MACHINE:
621 LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
624 case AIRONET_STATE_MACHINE:
625 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
628 #ifdef QOS_DLS_SUPPORT
629 case DLS_STATE_MACHINE:
630 StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem);
632 #endif // QOS_DLS_SUPPORT //
633 #endif // CONFIG_STA_SUPPORT //
635 case ACTION_STATE_MACHINE:
636 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
643 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
648 Elem->Occupied = FALSE;
653 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
657 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
658 pAd->Mlme.bRunning = FALSE;
659 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
663 ==========================================================================
665 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
667 Adapter - NIC Adapter pointer
669 The MLME task will no longer work properly
673 ==========================================================================
676 IN PRTMP_ADAPTER pAd)
680 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
682 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
684 // disable BEACON generation and other BEACON related hardware timers
685 AsicDisableSync(pAd);
688 #ifdef CONFIG_STA_SUPPORT
689 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
691 #ifdef QOS_DLS_SUPPORT
693 #endif // QOS_DLS_SUPPORT //
694 // Cancel pending timers
695 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
696 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
697 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
698 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
699 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
700 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
701 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
703 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
704 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
707 #ifdef QOS_DLS_SUPPORT
708 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
710 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
712 #endif // QOS_DLS_SUPPORT //
714 #endif // CONFIG_STA_SUPPORT //
716 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
717 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
721 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
724 RTMPSetLED(pAd, LED_HALT);
725 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
728 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
730 MlmeQueueDestroy(&pAd->Mlme.Queue);
731 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
733 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
736 VOID MlmeResetRalinkCounters(
737 IN PRTMP_ADAPTER pAd)
739 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
740 // clear all OneSecxxx counters.
741 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
742 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
743 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
744 pAd->RalinkCounters.OneSecRxOkCnt = 0;
745 pAd->RalinkCounters.OneSecTxFailCount = 0;
746 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
747 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
748 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
750 // TODO: for debug only. to be removed
751 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
752 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
753 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
754 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
755 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
756 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
757 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
758 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
759 pAd->RalinkCounters.OneSecTxDoneCount = 0;
760 pAd->RalinkCounters.OneSecRxCount = 0;
761 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
762 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
767 unsigned long rx_AMSDU;
768 unsigned long rx_Total;
771 ==========================================================================
773 This routine is executed periodically to -
774 1. Decide if it's a right time to turn on PwrMgmt bit of all
776 2. Calculate ChannelQuality based on statistics of the last
777 period, so that TX rate won't toggling very frequently between a
778 successful TX and a failed TX.
779 3. If the calculated ChannelQuality indicated current connection not
780 healthy, then a ROAMing attempt is tried here.
782 IRQL = DISPATCH_LEVEL
784 ==========================================================================
786 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
787 VOID MlmePeriodicExec(
788 IN PVOID SystemSpecific1,
789 IN PVOID FunctionContext,
790 IN PVOID SystemSpecific2,
791 IN PVOID SystemSpecific3)
794 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
797 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
798 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
799 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
800 if(pAd->StaCfg.WepStatus<2)
802 pAd->StaCfg.WpaSupplicantUP = 0;
806 pAd->StaCfg.WpaSupplicantUP = 1;
809 #ifdef CONFIG_STA_SUPPORT
810 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
812 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
813 // Move code to here, because following code will return when radio is off
814 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
815 (pAd->StaCfg.bHardwareRadio == TRUE) &&
816 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
817 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
818 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
822 // Read GPIO pin2 as Hardware controlled radio state
823 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
826 pAd->StaCfg.bHwRadio = TRUE;
830 pAd->StaCfg.bHwRadio = FALSE;
832 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
834 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
835 if (pAd->StaCfg.bRadio == TRUE)
838 // Update extra information
839 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
844 // Update extra information
845 pAd->ExtraInfo = HW_RADIO_OFF;
850 #endif // CONFIG_STA_SUPPORT //
852 // Do nothing if the driver is starting halt state.
853 // This might happen when timer already been fired before cancel timer with mlmehalt
854 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
855 fRTMP_ADAPTER_RADIO_OFF |
856 fRTMP_ADAPTER_RADIO_MEASUREMENT |
857 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
860 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
862 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
864 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
865 pAd->SameRxByteCount++;
868 pAd->SameRxByteCount = 0;
870 // If after BBP, still not work...need to check to reset PBF&MAC.
871 if (pAd->SameRxByteCount == 702)
873 pAd->SameRxByteCount = 0;
878 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
879 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
881 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
883 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
884 pAd->SameRxByteCount = 700;
889 // Update lastReceiveByteCount.
890 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
892 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
894 pAd->CheckDmaBusyCount = 0;
895 AsicResetFromDMABusy(pAd);
899 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
901 #ifdef CONFIG_STA_SUPPORT
902 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
904 // Do nothing if monitor mode is on
908 if (pAd->Mlme.PeriodicRound & 0x1)
910 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
911 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
912 (STA_TGN_WIFI_ON(pAd)) &&
913 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
916 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
917 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
919 else if ((STA_TGN_WIFI_ON(pAd)) &&
920 ((pAd->MACVersion & 0xffff) == 0x0101))
922 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
923 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
927 #endif // CONFIG_STA_SUPPORT //
929 pAd->bUpdateBcnCntDone = FALSE;
931 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
932 pAd->Mlme.PeriodicRound ++;
934 // execute every 500ms
935 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
937 #ifdef CONFIG_STA_SUPPORT
938 // perform dynamic tx rate switching based on past TX history
939 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
941 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
943 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
944 MlmeDynamicTxRateSwitching(pAd);
946 #endif // CONFIG_STA_SUPPORT //
949 // Normal 1 second Mlme PeriodicExec.
950 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
952 pAd->Mlme.OneSecPeriodicRound ++;
962 // Media status changed, report to NDIS
963 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
965 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
966 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
968 pAd->IndicateMediaState = NdisMediaStateConnected;
969 RTMP_IndicateMediaState(pAd);
974 pAd->IndicateMediaState = NdisMediaStateDisconnected;
975 RTMP_IndicateMediaState(pAd);
979 NdisGetSystemUpTime(&pAd->Mlme.Now32);
981 // add the most up-to-date h/w raw counters into software variable, so that
982 // the dynamic tuning mechanism below are based on most up-to-date information
983 NICUpdateRawCounters(pAd);
986 #ifdef DOT11_N_SUPPORT
987 // Need statistics after read counter. So put after NICUpdateRawCounters
988 ORIBATimerTimeout(pAd);
989 #endif // DOT11_N_SUPPORT //
992 // The time period for checking antenna is according to traffic
993 if (pAd->Mlme.bEnableAutoAntennaCheck)
995 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
996 pAd->RalinkCounters.OneSecTxRetryOkCount +
997 pAd->RalinkCounters.OneSecTxFailCount;
1001 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
1003 AsicEvaluateRxAnt(pAd);
1008 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
1010 AsicEvaluateRxAnt(pAd);
1015 #ifdef CONFIG_STA_SUPPORT
1016 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1017 STAMlmePeriodicExec(pAd);
1018 #endif // CONFIG_STA_SUPPORT //
1020 MlmeResetRalinkCounters(pAd);
1022 #ifdef CONFIG_STA_SUPPORT
1023 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1025 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
1027 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1028 // and sending CTS-to-self over and over.
1029 // Software Patch Solution:
1030 // 1. Polling debug state register 0x10F4 every one second.
1031 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1032 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1036 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1037 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1039 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1041 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1043 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1047 #endif // CONFIG_STA_SUPPORT //
1049 RT28XX_MLME_HANDLER(pAd);
1053 pAd->bUpdateBcnCntDone = FALSE;
1056 #ifdef CONFIG_STA_SUPPORT
1057 VOID STAMlmePeriodicExec(
1062 #ifdef WPA_SUPPLICANT_SUPPORT
1063 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1064 #endif // WPA_SUPPLICANT_SUPPORT //
1066 // WPA MIC error should block association attempt for 60 seconds
1067 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1068 pAd->StaCfg.bBlockAssoc = FALSE;
1072 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1073 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1074 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1075 if(pAd->StaCfg.WepStatus<2)
1077 pAd->StaCfg.WpaSupplicantUP = 0;
1081 pAd->StaCfg.WpaSupplicantUP = 1;
1084 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1086 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1088 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1090 pAd->PreMediaState = pAd->IndicateMediaState;
1093 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1094 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1095 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1096 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1097 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1098 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1100 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1105 AsicStaBbpTuning(pAd);
1107 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1108 pAd->RalinkCounters.OneSecTxRetryOkCount +
1109 pAd->RalinkCounters.OneSecTxFailCount;
1111 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1113 // update channel quality for Roaming and UI LinkQuality display
1114 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1117 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1118 // Radio is currently in noisy environment
1119 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1120 AsicAdjustTxPower(pAd);
1124 #ifdef QOS_DLS_SUPPORT
1125 // Check DLS time out, then tear down those session
1126 RTMPCheckDLSTimeOut(pAd);
1127 #endif // QOS_DLS_SUPPORT //
1129 // Is PSM bit consistent with user power management policy?
1130 // This is the only place that will set PSM bit ON.
1131 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1132 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1134 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1136 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1137 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1138 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1140 RTMPSetAGCInitValue(pAd, BW_20);
1141 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1145 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1147 // When APSD is enabled, the period changes as 20 sec
1148 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1149 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1153 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1154 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1156 if (pAd->CommonCfg.bWmmCapable)
1157 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1159 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1164 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1166 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1167 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1168 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1170 // Lost AP, send disconnect & link down event
1171 LinkDown(pAd, FALSE);
1173 #ifdef WPA_SUPPLICANT_SUPPORT
1174 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1175 if (pAd->StaCfg.WpaSupplicantUP)
1177 union iwreq_data wrqu;
1178 //send disassociate event to wpa_supplicant
1179 memset(&wrqu, 0, sizeof(wrqu));
1180 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1181 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1183 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1184 #endif // WPA_SUPPLICANT_SUPPORT //
1186 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1188 union iwreq_data wrqu;
1189 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1190 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1192 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1194 MlmeAutoReconnectLastSSID(pAd);
1196 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1198 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1199 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1200 MlmeAutoReconnectLastSSID(pAd);
1203 // Add auto seamless roaming
1204 if (pAd->StaCfg.bFastRoaming)
1206 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1208 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));
1210 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1212 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1216 else if (ADHOC_ON(pAd))
1218 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1219 // the "TX BEACON competition" for the entire past 1 sec.
1220 // So that even when ASIC's BEACONgen engine been blocked
1221 // by peer's BEACON due to slower system clock, this STA still can send out
1222 // minimum BEACON to tell the peer I'm alive.
1223 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1224 // EnqueueBeaconFrame(pAd); // software send BEACON
1226 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1227 // restore outgoing BEACON to support B/G-mixed mode
1228 if ((pAd->CommonCfg.Channel <= 14) &&
1229 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1230 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1231 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1233 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1234 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1235 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1236 MlmeUpdateTxRates(pAd, FALSE, 0);
1237 MakeIbssBeacon(pAd); // re-build BEACON frame
1238 AsicEnableIbssSync(pAd); // copy to on-chip memory
1239 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1242 #ifdef DOT11_N_SUPPORT
1243 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1245 if ((pAd->StaCfg.AdhocBGJoined) &&
1246 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1248 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1249 pAd->StaCfg.AdhocBGJoined = FALSE;
1252 if ((pAd->StaCfg.Adhoc20NJoined) &&
1253 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1255 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1256 pAd->StaCfg.Adhoc20NJoined = FALSE;
1259 #endif // DOT11_N_SUPPORT //
1262 if ((pAd->CommonCfg.Channel > 14)
1263 && (pAd->CommonCfg.bIEEE80211H == 1)
1264 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1266 RadarDetectPeriodic(pAd);
1269 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1270 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1272 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1273 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1275 MLME_START_REQ_STRUCT StartReq;
1277 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1278 LinkDown(pAd, FALSE);
1280 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1281 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1282 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1285 else // no INFRA nor ADHOC connection
1288 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1289 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1290 goto SKIP_AUTO_SCAN_CONN;
1292 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1294 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1295 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1296 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1298 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1300 MLME_SCAN_REQ_STRUCT ScanReq;
1302 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1304 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1305 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1306 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1307 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1308 // Reset Missed scan number
1309 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1311 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1312 MlmeAutoReconnectLastSSID(pAd);
1314 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1316 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1319 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1323 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1324 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1326 if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1)
1327 MlmeAutoReconnectLastSSID(pAd);
1330 #endif // CARRIER_DETECTION_SUPPORT //
1331 MlmeAutoReconnectLastSSID(pAd);
1337 SKIP_AUTO_SCAN_CONN:
1339 #ifdef DOT11_N_SUPPORT
1340 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1342 pAd->MacTab.fAnyBASession = TRUE;
1343 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1345 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1347 pAd->MacTab.fAnyBASession = FALSE;
1348 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1350 #endif // DOT11_N_SUPPORT //
1353 #ifdef DOT11_N_SUPPORT
1354 #ifdef DOT11N_DRAFT3
1355 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1356 TriEventCounterMaintenance(pAd);
1357 #endif // DOT11N_DRAFT3 //
1358 #endif // DOT11_N_SUPPORT //
1365 IN PVOID SystemSpecific1,
1366 IN PVOID FunctionContext,
1367 IN PVOID SystemSpecific2,
1368 IN PVOID SystemSpecific3)
1371 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1373 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1374 RTMP_IndicateMediaState(pAd);
1375 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1378 // IRQL = DISPATCH_LEVEL
1380 IN PRTMP_ADAPTER pAd)
1382 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1383 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1385 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1387 MLME_CNTL_STATE_MACHINE,
1388 OID_802_11_BSSID_LIST_SCAN,
1391 RT28XX_MLME_HANDLER(pAd);
1395 // IRQL = DISPATCH_LEVEL
1396 VOID MlmeAutoReconnectLastSSID(
1397 IN PRTMP_ADAPTER pAd)
1401 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1402 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1403 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1405 NDIS_802_11_SSID OidSsid;
1406 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1407 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1409 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1411 MLME_CNTL_STATE_MACHINE,
1413 sizeof(NDIS_802_11_SSID),
1415 RT28XX_MLME_HANDLER(pAd);
1418 #endif // CONFIG_STA_SUPPORT //
1421 ==========================================================================
1422 Validate SSID for connection try and rescan purpose
1423 Valid SSID will have visible chars only.
1424 The valid length is from 0 to 32.
1425 IRQL = DISPATCH_LEVEL
1426 ==========================================================================
1428 BOOLEAN MlmeValidateSSID(
1434 if (SsidLen > MAX_LEN_OF_SSID)
1437 // Check each character value
1438 for (index = 0; index < SsidLen; index++)
1440 if (pSsid[index] < 0x20)
1448 VOID MlmeSelectTxRateTable(
1449 IN PRTMP_ADAPTER pAd,
1450 IN PMAC_TABLE_ENTRY pEntry,
1452 IN PUCHAR pTableSize,
1453 IN PUCHAR pInitTxRateIdx)
1457 // decide the rate table for tuning
1458 if (pAd->CommonCfg.TxRateTableSize > 0)
1460 *ppTable = RateSwitchTable;
1461 *pTableSize = RateSwitchTable[0];
1462 *pInitTxRateIdx = RateSwitchTable[1];
1467 #ifdef CONFIG_STA_SUPPORT
1468 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1470 #ifdef DOT11_N_SUPPORT
1471 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1472 !pAd->StaCfg.AdhocBOnlyJoined &&
1473 !pAd->StaCfg.AdhocBGJoined &&
1474 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1475 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1477 *ppTable = RateSwitchTable11N1S;
1478 *pTableSize = RateSwitchTable11N1S[0];
1479 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1482 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1483 !pAd->StaCfg.AdhocBOnlyJoined &&
1484 !pAd->StaCfg.AdhocBGJoined &&
1485 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1486 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1487 (pAd->Antenna.field.TxPath == 2))
1489 if (pAd->LatchRfRegs.Channel <= 14)
1491 *ppTable = RateSwitchTable11N2S;
1492 *pTableSize = RateSwitchTable11N2S[0];
1493 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1497 *ppTable = RateSwitchTable11N2SForABand;
1498 *pTableSize = RateSwitchTable11N2SForABand[0];
1499 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1504 #endif // DOT11_N_SUPPORT //
1505 if (pAd->CommonCfg.PhyMode == PHY_11B)
1507 *ppTable = RateSwitchTable11B;
1508 *pTableSize = RateSwitchTable11B[0];
1509 *pInitTxRateIdx = RateSwitchTable11B[1];
1512 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1514 // USe B Table when Only b-only Station in my IBSS .
1515 *ppTable = RateSwitchTable11B;
1516 *pTableSize = RateSwitchTable11B[0];
1517 *pInitTxRateIdx = RateSwitchTable11B[1];
1520 else if (pAd->LatchRfRegs.Channel <= 14)
1522 *ppTable = RateSwitchTable11BG;
1523 *pTableSize = RateSwitchTable11BG[0];
1524 *pInitTxRateIdx = RateSwitchTable11BG[1];
1529 *ppTable = RateSwitchTable11G;
1530 *pTableSize = RateSwitchTable11G[0];
1531 *pInitTxRateIdx = RateSwitchTable11G[1];
1536 #endif // CONFIG_STA_SUPPORT //
1538 #ifdef DOT11_N_SUPPORT
1539 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1540 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1542 *ppTable = RateSwitchTable11BGN1S;
1543 *pTableSize = RateSwitchTable11BGN1S[0];
1544 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1549 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1550 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1552 if (pAd->LatchRfRegs.Channel <= 14)
1554 *ppTable = RateSwitchTable11BGN2S;
1555 *pTableSize = RateSwitchTable11BGN2S[0];
1556 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1561 *ppTable = RateSwitchTable11BGN2SForABand;
1562 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1563 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1569 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1571 *ppTable = RateSwitchTable11N1S;
1572 *pTableSize = RateSwitchTable11N1S[0];
1573 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1578 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1580 if (pAd->LatchRfRegs.Channel <= 14)
1582 *ppTable = RateSwitchTable11N2S;
1583 *pTableSize = RateSwitchTable11N2S[0];
1584 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1588 *ppTable = RateSwitchTable11N2SForABand;
1589 *pTableSize = RateSwitchTable11N2SForABand[0];
1590 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1595 #endif // DOT11_N_SUPPORT //
1596 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1597 if ((pEntry->RateLen == 4)
1598 #ifdef DOT11_N_SUPPORT
1599 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1600 #endif // DOT11_N_SUPPORT //
1603 *ppTable = RateSwitchTable11B;
1604 *pTableSize = RateSwitchTable11B[0];
1605 *pInitTxRateIdx = RateSwitchTable11B[1];
1610 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1611 if ((pEntry->RateLen > 8)
1612 #ifdef DOT11_N_SUPPORT
1613 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1614 #endif // DOT11_N_SUPPORT //
1617 *ppTable = RateSwitchTable11BG;
1618 *pTableSize = RateSwitchTable11BG[0];
1619 *pInitTxRateIdx = RateSwitchTable11BG[1];
1624 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1625 if ((pEntry->RateLen == 8)
1626 #ifdef DOT11_N_SUPPORT
1627 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1628 #endif // DOT11_N_SUPPORT //
1631 *ppTable = RateSwitchTable11G;
1632 *pTableSize = RateSwitchTable11G[0];
1633 *pInitTxRateIdx = RateSwitchTable11G[1];
1637 #ifdef DOT11_N_SUPPORT
1638 #endif // DOT11_N_SUPPORT //
1640 #ifdef CONFIG_STA_SUPPORT
1641 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1643 #ifdef DOT11_N_SUPPORT
1644 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1645 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1646 #endif // DOT11_N_SUPPORT //
1648 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1650 *ppTable = RateSwitchTable11B;
1651 *pTableSize = RateSwitchTable11B[0];
1652 *pInitTxRateIdx = RateSwitchTable11B[1];
1654 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1656 *ppTable = RateSwitchTable11G;
1657 *pTableSize = RateSwitchTable11G[0];
1658 *pInitTxRateIdx = RateSwitchTable11G[1];
1663 *ppTable = RateSwitchTable11BG;
1664 *pTableSize = RateSwitchTable11BG[0];
1665 *pInitTxRateIdx = RateSwitchTable11BG[1];
1669 #ifdef DOT11_N_SUPPORT
1670 if (pAd->LatchRfRegs.Channel <= 14)
1672 if (pAd->CommonCfg.TxStream == 1)
1674 *ppTable = RateSwitchTable11N1S;
1675 *pTableSize = RateSwitchTable11N1S[0];
1676 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1677 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1681 *ppTable = RateSwitchTable11N2S;
1682 *pTableSize = RateSwitchTable11N2S[0];
1683 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1684 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1689 if (pAd->CommonCfg.TxStream == 1)
1691 *ppTable = RateSwitchTable11N1S;
1692 *pTableSize = RateSwitchTable11N1S[0];
1693 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1694 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1698 *ppTable = RateSwitchTable11N2SForABand;
1699 *pTableSize = RateSwitchTable11N2SForABand[0];
1700 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1701 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1704 #endif // DOT11_N_SUPPORT //
1705 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1706 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1708 #endif // CONFIG_STA_SUPPORT //
1712 #ifdef CONFIG_STA_SUPPORT
1714 ==========================================================================
1716 This routine checks if there're other APs out there capable for
1717 roaming. Caller should call this routine only when Link up in INFRA mode
1718 and channel quality is below CQI_GOOD_THRESHOLD.
1720 IRQL = DISPATCH_LEVEL
1723 ==========================================================================
1725 VOID MlmeCheckForRoaming(
1726 IN PRTMP_ADAPTER pAd,
1730 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1733 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1734 // put all roaming candidates into RoamTab, and sort in RSSI order
1735 BssTableInit(pRoamTab);
1736 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1738 pBss = &pAd->ScanTab.BssEntry[i];
1740 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1741 continue; // AP disappear
1742 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1743 continue; // RSSI too weak. forget it.
1744 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1745 continue; // skip current AP
1746 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1747 continue; // only AP with stronger RSSI is eligible for roaming
1749 // AP passing all above rules is put into roaming candidate table
1750 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1751 pRoamTab->BssNr += 1;
1754 if (pRoamTab->BssNr > 0)
1756 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1757 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1759 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1760 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1761 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1762 RT28XX_MLME_HANDLER(pAd);
1765 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1769 ==========================================================================
1771 This routine checks if there're other APs out there capable for
1772 roaming. Caller should call this routine only when link up in INFRA mode
1773 and channel quality is below CQI_GOOD_THRESHOLD.
1775 IRQL = DISPATCH_LEVEL
1778 ==========================================================================
1780 VOID MlmeCheckForFastRoaming(
1781 IN PRTMP_ADAPTER pAd,
1785 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1788 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1789 // put all roaming candidates into RoamTab, and sort in RSSI order
1790 BssTableInit(pRoamTab);
1791 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1793 pBss = &pAd->ScanTab.BssEntry[i];
1795 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1796 continue; // RSSI too weak. forget it.
1797 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1798 continue; // skip current AP
1799 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1800 continue; // skip different SSID
1801 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1802 continue; // skip AP without better RSSI
1804 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));
1805 // AP passing all above rules is put into roaming candidate table
1806 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1807 pRoamTab->BssNr += 1;
1810 if (pRoamTab->BssNr > 0)
1812 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1813 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1815 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1816 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1817 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1818 RT28XX_MLME_HANDLER(pAd);
1821 // Maybe site survey required
1824 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1826 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1827 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1828 pAd->StaCfg.ScanCnt = 2;
1829 pAd->StaCfg.LastScanTime = Now;
1834 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1838 ==========================================================================
1840 This routine calculates TxPER, RxPER of the past N-sec period. And
1841 according to the calculation result, ChannelQuality is calculated here
1842 to decide if current AP is still doing the job.
1844 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1846 StaCfg.ChannelQuality - 0..100
1848 IRQL = DISPATCH_LEVEL
1850 NOTE: This routine decide channle quality based on RX CRC error ratio.
1851 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1852 is performed right before this routine, so that this routine can decide
1853 channel quality based on the most up-to-date information
1854 ==========================================================================
1856 VOID MlmeCalculateChannelQuality(
1857 IN PRTMP_ADAPTER pAd,
1860 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1864 ULONG BeaconLostTime = BEACON_LOST_TIME;
1866 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1867 // longer beacon lost time when carrier detection enabled
1868 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1870 BeaconLostTime = BEACON_LOST_TIME + BEACON_LOST_TIME/2;
1872 #endif // CARRIER_DETECTION_SUPPORT //
1874 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1877 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1879 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1880 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1888 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1889 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1893 // calculate RX PER - don't take RxPER into consideration if too few sample
1895 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1899 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1902 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1904 if (INFRA_ON(pAd) &&
1905 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1906 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1908 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1909 pAd->Mlme.ChannelQuality = 0;
1916 else if (MaxRssi < -90)
1919 NorRssi = (MaxRssi + 90) * 2;
1921 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1922 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1923 TX_WEIGHTING * (100 - TxPRR) +
1924 RX_WEIGHTING* (100 - RxPER)) / 100;
1925 if (pAd->Mlme.ChannelQuality >= 100)
1926 pAd->Mlme.ChannelQuality = 100;
1932 IN PRTMP_ADAPTER pAd,
1933 IN PMAC_TABLE_ENTRY pEntry,
1934 IN PRTMP_TX_RATE_SWITCH pTxRate)
1936 UCHAR MaxMode = MODE_OFDM;
1938 #ifdef DOT11_N_SUPPORT
1939 MaxMode = MODE_HTGREENFIELD;
1941 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1942 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1944 #endif // DOT11_N_SUPPORT //
1945 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1947 if (pTxRate->CurrMCS < MCS_AUTO)
1948 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1950 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1951 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1955 // If peer adhoc is b-only mode, we can't send 11g rate.
1956 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1957 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1960 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1962 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1963 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1964 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1966 // Patch speed error in status page
1967 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1971 if (pTxRate->Mode <= MaxMode)
1972 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1974 #ifdef DOT11_N_SUPPORT
1975 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1976 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1978 #endif // DOT11_N_SUPPORT //
1979 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1981 #ifdef DOT11_N_SUPPORT
1982 // Reexam each bandwidth's SGI support.
1983 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1985 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1986 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1987 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1988 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1991 // Turn RTS/CTS rate to 6Mbps.
1992 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1994 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1995 if (pAd->MacTab.fAnyBASession)
1997 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2001 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2004 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
2006 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
2007 if (pAd->MacTab.fAnyBASession)
2009 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2013 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2016 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
2018 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2021 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
2023 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2025 #endif // DOT11_N_SUPPORT //
2027 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
2028 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
2029 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
2030 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
2031 #ifdef DOT11_N_SUPPORT
2032 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
2033 pAd->WIFItestbed.bGreenField)
2034 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
2035 #endif // DOT11_N_SUPPORT //
2038 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
2042 ==========================================================================
2044 This routine calculates the acumulated TxPER of eaxh TxRate. And
2045 according to the calculation result, change CommonCfg.TxRate which
2046 is the stable TX Rate we expect the Radio situation could sustained.
2048 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
2052 IRQL = DISPATCH_LEVEL
2055 call this routine every second
2056 ==========================================================================
2058 VOID MlmeDynamicTxRateSwitching(
2059 IN PRTMP_ADAPTER pAd)
2061 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2062 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2063 ULONG TxErrorRatio = 0;
2064 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2065 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2067 UCHAR TableSize = 0;
2068 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2069 CHAR Rssi, RssiOffset = 0;
2070 TX_STA_CNT1_STRUC StaTx1;
2071 TX_STA_CNT0_STRUC TxStaCnt0;
2072 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2073 MAC_TABLE_ENTRY *pEntry;
2075 /*if (pAd->Antenna.field.RxPath > 1)
2076 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2078 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
2081 // walk through MAC table, see if need to change AP's TX rate toward each entry
2083 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2085 pEntry = &pAd->MacTab.Content[i];
2087 // check if this entry need to switch rate automatically
2088 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2091 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2093 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2095 // Update statistic counter
2096 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2097 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2098 pAd->bUpdateBcnCntDone = TRUE;
2099 TxRetransmit = StaTx1.field.TxRetransmit;
2100 TxSuccess = StaTx1.field.TxSuccess;
2101 TxFailCount = TxStaCnt0.field.TxFailCount;
2102 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2104 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2105 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2106 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2107 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2108 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2109 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2111 // if no traffic in the past 1-sec period, don't change TX rate,
2112 // but clear all bad history. because the bad history may affect the next
2113 // Chariot throughput test
2114 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2115 pAd->RalinkCounters.OneSecTxRetryOkCount +
2116 pAd->RalinkCounters.OneSecTxFailCount;
2119 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2123 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2125 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2126 pEntry->OneSecTxRetryOkCount +
2127 pEntry->OneSecTxFailCount;
2130 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2133 CurrRateIdx = pEntry->CurrTxRateIndex;
2135 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2137 if (CurrRateIdx >= TableSize)
2139 CurrRateIdx = TableSize - 1;
2142 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2143 // So need to sync here.
2144 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2145 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2146 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2150 // Need to sync Real Tx rate and our record.
2151 // Then return for next DRS.
2152 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2153 pEntry->CurrTxRateIndex = InitTxRateIdx;
2154 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2156 // reset all OneSecTx counters
2157 RESET_ONE_SEC_TX_CNT(pEntry);
2161 // decide the next upgrade rate and downgrade rate, if any
2162 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2164 UpRateIdx = CurrRateIdx + 1;
2165 DownRateIdx = CurrRateIdx -1;
2167 else if (CurrRateIdx == 0)
2169 UpRateIdx = CurrRateIdx + 1;
2170 DownRateIdx = CurrRateIdx;
2172 else if (CurrRateIdx == (TableSize - 1))
2174 UpRateIdx = CurrRateIdx;
2175 DownRateIdx = CurrRateIdx - 1;
2178 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2180 #ifdef DOT11_N_SUPPORT
2181 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2183 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2184 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2187 #endif // DOT11_N_SUPPORT //
2189 TrainUp = pCurrTxRate->TrainUp;
2190 TrainDown = pCurrTxRate->TrainDown;
2193 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2196 // Keep the last time TxRateChangeAction status.
2198 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2203 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2204 // (criteria copied from RT2500 for Netopia case)
2206 if (TxTotalCnt <= 15)
2210 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2211 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2212 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2213 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2215 // check the existence and index of each needed MCS
2216 while (idx < pTable[0])
2218 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2220 if (pCurrTxRate->CurrMCS == MCS_0)
2224 else if (pCurrTxRate->CurrMCS == MCS_1)
2228 else if (pCurrTxRate->CurrMCS == MCS_2)
2232 else if (pCurrTxRate->CurrMCS == MCS_3)
2236 else if (pCurrTxRate->CurrMCS == MCS_4)
2240 else if (pCurrTxRate->CurrMCS == MCS_5)
2244 else if (pCurrTxRate->CurrMCS == MCS_6)
2248 //else if (pCurrTxRate->CurrMCS == MCS_7)
2249 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2253 else if (pCurrTxRate->CurrMCS == MCS_12)
2257 else if (pCurrTxRate->CurrMCS == MCS_13)
2261 else if (pCurrTxRate->CurrMCS == MCS_14)
2265 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2266 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
2270 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2274 else if (pCurrTxRate->CurrMCS == MCS_21)
2278 else if (pCurrTxRate->CurrMCS == MCS_22)
2282 else if (pCurrTxRate->CurrMCS == MCS_23)
2289 if (pAd->LatchRfRegs.Channel <= 14)
2291 if (pAd->NicConfig2.field.ExternalLNAForG)
2302 if (pAd->NicConfig2.field.ExternalLNAForA)
2311 #ifdef DOT11_N_SUPPORT
2313 if ((pTable == RateSwitchTable11BGN3S) ||
2314 (pTable == RateSwitchTable11N3S) ||
2315 (pTable == RateSwitchTable))
2316 {// N mode with 3 stream // 3*3
2317 if (MCS23 && (Rssi >= -70))
2319 else if (MCS22 && (Rssi >= -72))
2321 else if (MCS21 && (Rssi >= -76))
2323 else if (MCS20 && (Rssi >= -78))
2325 else if (MCS4 && (Rssi >= -82))
2327 else if (MCS3 && (Rssi >= -84))
2329 else if (MCS2 && (Rssi >= -86))
2331 else if (MCS1 && (Rssi >= -88))
2336 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2337 {// N mode with 2 stream
2338 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2340 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2342 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2344 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2346 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2348 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2350 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2352 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2357 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2358 {// N mode with 1 stream
2359 if (MCS7 && (Rssi > (-72+RssiOffset)))
2361 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2363 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2365 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2367 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2369 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2371 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2377 #endif // DOT11_N_SUPPORT //
2379 if (MCS7 && (Rssi > -70))
2381 else if (MCS6 && (Rssi > -74))
2383 else if (MCS5 && (Rssi > -78))
2385 else if (MCS4 && (Rssi > -82))
2387 else if (MCS4 == 0) // for B-only mode
2389 else if (MCS3 && (Rssi > -85))
2391 else if (MCS2 && (Rssi > -87))
2393 else if (MCS1 && (Rssi > -90))
2400 pEntry->CurrTxRateIndex = TxRateIdx;
2401 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2402 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2405 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2406 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2407 pEntry->fLastSecAccordingRSSI = TRUE;
2408 // reset all OneSecTx counters
2409 RESET_ONE_SEC_TX_CNT(pEntry);
2414 if (pEntry->fLastSecAccordingRSSI == TRUE)
2416 pEntry->fLastSecAccordingRSSI = FALSE;
2417 pEntry->LastSecTxRateChangeAction = 0;
2418 // reset all OneSecTx counters
2419 RESET_ONE_SEC_TX_CNT(pEntry);
2426 BOOLEAN bTrainUpDown = FALSE;
2428 pEntry->CurrTxRateStableTime ++;
2430 // downgrade TX quality if PER >= Rate-Down threshold
2431 if (TxErrorRatio >= TrainDown)
2433 bTrainUpDown = TRUE;
2434 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2436 // upgrade TX quality if PER <= Rate-Up threshold
2437 else if (TxErrorRatio <= TrainUp)
2439 bTrainUpDown = TRUE;
2440 bUpgradeQuality = TRUE;
2441 if (pEntry->TxQuality[CurrRateIdx])
2442 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2444 if (pEntry->TxRateUpPenalty)
2445 pEntry->TxRateUpPenalty --;
2446 else if (pEntry->TxQuality[UpRateIdx])
2447 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2450 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2454 // perform DRS - consider TxRate Down first, then rate up.
2455 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2457 pEntry->CurrTxRateIndex = DownRateIdx;
2459 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2461 pEntry->CurrTxRateIndex = UpRateIdx;
2466 // if rate-up happen, clear all bad history of all TX rates
2467 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2469 pEntry->CurrTxRateStableTime = 0;
2470 pEntry->TxRateUpPenalty = 0;
2471 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2472 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2473 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2476 // For TxRate fast train up
2478 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2480 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2482 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2484 bTxRateChanged = TRUE;
2486 // if rate-down happen, only clear DownRate's bad history
2487 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2489 pEntry->CurrTxRateStableTime = 0;
2490 pEntry->TxRateUpPenalty = 0; // no penalty
2491 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2492 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2493 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2496 // For TxRate fast train down
2498 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2500 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2502 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2504 bTxRateChanged = TRUE;
2508 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2509 bTxRateChanged = FALSE;
2512 pEntry->LastTxOkCount = TxSuccess;
2514 // reset all OneSecTx counters
2515 RESET_ONE_SEC_TX_CNT(pEntry);
2517 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2518 if (bTxRateChanged && pNextTxRate)
2520 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2526 ========================================================================
2527 Routine Description:
2528 Station side, Auto TxRate faster train up timer call back function.
2531 SystemSpecific1 - Not used.
2532 FunctionContext - Pointer to our Adapter context.
2533 SystemSpecific2 - Not used.
2534 SystemSpecific3 - Not used.
2539 ========================================================================
2541 VOID StaQuickResponeForRateUpExec(
2542 IN PVOID SystemSpecific1,
2543 IN PVOID FunctionContext,
2544 IN PVOID SystemSpecific2,
2545 IN PVOID SystemSpecific3)
2547 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2548 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2550 ULONG TxErrorRatio = 0;
2551 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2552 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2554 UCHAR TableSize = 0;
2555 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2556 TX_STA_CNT1_STRUC StaTx1;
2557 TX_STA_CNT0_STRUC TxStaCnt0;
2559 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2560 MAC_TABLE_ENTRY *pEntry;
2563 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2566 // walk through MAC table, see if need to change AP's TX rate toward each entry
2568 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2570 pEntry = &pAd->MacTab.Content[i];
2572 // check if this entry need to switch rate automatically
2573 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2576 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2577 if (pAd->Antenna.field.TxPath > 1)
2578 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2580 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2582 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2584 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2586 // decide the next upgrade rate and downgrade rate, if any
2587 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2589 UpRateIdx = CurrRateIdx + 1;
2590 DownRateIdx = CurrRateIdx -1;
2592 else if (CurrRateIdx == 0)
2594 UpRateIdx = CurrRateIdx + 1;
2595 DownRateIdx = CurrRateIdx;
2597 else if (CurrRateIdx == (TableSize - 1))
2599 UpRateIdx = CurrRateIdx;
2600 DownRateIdx = CurrRateIdx - 1;
2603 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2605 #ifdef DOT11_N_SUPPORT
2606 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2608 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2609 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2612 #endif // DOT11_N_SUPPORT //
2614 TrainUp = pCurrTxRate->TrainUp;
2615 TrainDown = pCurrTxRate->TrainDown;
2618 if (pAd->MacTab.Size == 1)
2620 // Update statistic counter
2621 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2622 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2624 TxRetransmit = StaTx1.field.TxRetransmit;
2625 TxSuccess = StaTx1.field.TxSuccess;
2626 TxFailCount = TxStaCnt0.field.TxFailCount;
2627 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2629 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2630 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2631 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2632 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2633 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2634 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2637 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2641 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2642 pEntry->OneSecTxRetryOkCount +
2643 pEntry->OneSecTxFailCount;
2646 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2651 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2652 // (criteria copied from RT2500 for Netopia case)
2654 if (TxTotalCnt <= 12)
2656 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2657 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2659 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2661 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2662 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2664 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2666 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2669 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2675 ULONG OneSecTxNoRetryOKRationCount;
2677 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2682 // downgrade TX quality if PER >= Rate-Down threshold
2683 if (TxErrorRatio >= TrainDown)
2685 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2688 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2690 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2692 // perform DRS - consider TxRate Down first, then rate up.
2693 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2695 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2697 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2698 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2703 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2705 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2709 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2711 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2716 // if rate-up happen, clear all bad history of all TX rates
2717 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2719 pAd->DrsCounters.TxRateUpPenalty = 0;
2720 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2721 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2723 // if rate-down happen, only clear DownRate's bad history
2724 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2726 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2728 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2729 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2730 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2734 bTxRateChanged = FALSE;
2737 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2738 if (bTxRateChanged && pNextTxRate)
2740 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2746 ==========================================================================
2748 This routine is executed periodically inside MlmePeriodicExec() after
2749 association with an AP.
2750 It checks if StaCfg.Psm is consistent with user policy (recorded in
2751 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2752 there're some conditions to consider:
2753 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2754 the time when Mibss==TRUE
2755 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2756 if outgoing traffic available in TxRing or MgmtRing.
2758 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2760 IRQL = DISPATCH_LEVEL
2762 ==========================================================================
2764 VOID MlmeCheckPsmChange(
2765 IN PRTMP_ADAPTER pAd,
2771 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2772 // 2. user wants either MAX_PSP or FAST_PSP
2773 // 3. but current psm is not in PWR_SAVE
2774 // 4. CNTL state machine is not doing SCANning
2775 // 5. no TX SUCCESS event for the past 1-sec period
2776 #ifdef NDIS51_MINIPORT
2777 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2778 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2781 PowerMode = pAd->StaCfg.WindowsPowerMode;
2783 if (INFRA_ON(pAd) &&
2784 (PowerMode != Ndis802_11PowerModeCAM) &&
2785 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2786 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2788 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2789 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2790 MlmeSetPsmBit(pAd, PWR_SAVE);
2791 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2793 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2797 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2802 // IRQL = PASSIVE_LEVEL
2803 // IRQL = DISPATCH_LEVEL
2805 IN PRTMP_ADAPTER pAd,
2808 AUTO_RSP_CFG_STRUC csr4;
2810 pAd->StaCfg.Psm = psm;
2811 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2812 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2813 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2814 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2816 #endif // CONFIG_STA_SUPPORT //
2819 // IRQL = DISPATCH_LEVEL
2820 VOID MlmeSetTxPreamble(
2821 IN PRTMP_ADAPTER pAd,
2822 IN USHORT TxPreamble)
2824 AUTO_RSP_CFG_STRUC csr4;
2827 // Always use Long preamble before verifiation short preamble functionality works well.
2828 // Todo: remove the following line if short preamble functionality works
2830 //TxPreamble = Rt802_11PreambleLong;
2832 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2833 if (TxPreamble == Rt802_11PreambleLong)
2835 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2836 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2837 csr4.field.AutoResponderPreamble = 0;
2841 // NOTE: 1Mbps should always use long preamble
2842 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2843 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2844 csr4.field.AutoResponderPreamble = 1;
2847 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2851 ==========================================================================
2853 Update basic rate bitmap
2854 ==========================================================================
2857 VOID UpdateBasicRateBitmap(
2858 IN PRTMP_ADAPTER pAdapter)
2861 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2862 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2863 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2864 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2865 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2868 /* if A mode, always use fix BasicRateBitMap */
2869 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2870 if (pAdapter->CommonCfg.Channel > 14)
2871 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2874 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2876 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2880 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2886 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2888 if (bitmap & (1 << i))
2890 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2892 if (sup_p[j] == rate[i])
2897 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2899 if (ext_p[j] == rate[i])
2905 } /* End of UpdateBasicRateBitmap */
2907 // IRQL = PASSIVE_LEVEL
2908 // IRQL = DISPATCH_LEVEL
2909 // bLinkUp is to identify the inital link speed.
2910 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2911 VOID MlmeUpdateTxRates(
2912 IN PRTMP_ADAPTER pAd,
2917 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2918 UCHAR MinSupport = RATE_54;
2919 ULONG BasicRateBitmap = 0;
2920 UCHAR CurrBasicRate = RATE_1;
2921 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2922 PHTTRANSMIT_SETTING pHtPhy = NULL;
2923 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2924 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2925 BOOLEAN *auto_rate_cur_p;
2926 UCHAR HtMcs = MCS_AUTO;
2928 // find max desired rate
2929 UpdateBasicRateBitmap(pAd);
2932 auto_rate_cur_p = NULL;
2933 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2935 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2937 case 2: Rate = RATE_1; num++; break;
2938 case 4: Rate = RATE_2; num++; break;
2939 case 11: Rate = RATE_5_5; num++; break;
2940 case 22: Rate = RATE_11; num++; break;
2941 case 12: Rate = RATE_6; num++; break;
2942 case 18: Rate = RATE_9; num++; break;
2943 case 24: Rate = RATE_12; num++; break;
2944 case 36: Rate = RATE_18; num++; break;
2945 case 48: Rate = RATE_24; num++; break;
2946 case 72: Rate = RATE_36; num++; break;
2947 case 96: Rate = RATE_48; num++; break;
2948 case 108: Rate = RATE_54; num++; break;
2949 //default: Rate = RATE_1; break;
2951 if (MaxDesire < Rate) MaxDesire = Rate;
2954 //===========================================================================
2955 //===========================================================================
2957 #ifdef CONFIG_STA_SUPPORT
2958 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2960 pHtPhy = &pAd->StaCfg.HTPhyMode;
2961 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2962 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2964 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2965 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2967 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2968 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2969 (MaxDesire > RATE_11))
2971 MaxDesire = RATE_11;
2974 #endif // CONFIG_STA_SUPPORT //
2976 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2977 pMinHtPhy->word = 0;
2978 pMaxHtPhy->word = 0;
2981 // Auto rate switching is enabled only if more than one DESIRED RATES are
2982 // specified; otherwise disabled
2985 *auto_rate_cur_p = FALSE;
2989 *auto_rate_cur_p = TRUE;
2993 if (HtMcs != MCS_AUTO)
2995 *auto_rate_cur_p = FALSE;
2999 *auto_rate_cur_p = TRUE;
3003 #ifdef CONFIG_STA_SUPPORT
3004 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3006 pSupRate = &pAd->StaActive.SupRate[0];
3007 pExtRate = &pAd->StaActive.ExtRate[0];
3008 SupRateLen = pAd->StaActive.SupRateLen;
3009 ExtRateLen = pAd->StaActive.ExtRateLen;
3012 #endif // CONFIG_STA_SUPPORT //
3014 pSupRate = &pAd->CommonCfg.SupRate[0];
3015 pExtRate = &pAd->CommonCfg.ExtRate[0];
3016 SupRateLen = pAd->CommonCfg.SupRateLen;
3017 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3020 // find max supported rate
3021 for (i=0; i<SupRateLen; i++)
3023 switch (pSupRate[i] & 0x7f)
3025 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3026 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3027 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3028 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3029 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3030 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3031 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3032 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3033 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3034 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3035 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3036 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3037 default: Rate = RATE_1; break;
3039 if (MaxSupport < Rate) MaxSupport = Rate;
3041 if (MinSupport > Rate) MinSupport = Rate;
3044 for (i=0; i<ExtRateLen; i++)
3046 switch (pExtRate[i] & 0x7f)
3048 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3049 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3050 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3051 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3052 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3053 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3054 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3055 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3056 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3057 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3058 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3059 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3060 default: Rate = RATE_1; break;
3062 if (MaxSupport < Rate) MaxSupport = Rate;
3064 if (MinSupport > Rate) MinSupport = Rate;
3067 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3069 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3070 // the DURATION field of outgoing uniicast DATA/MGMT frame
3071 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3073 if (BasicRateBitmap & (0x01 << i))
3074 CurrBasicRate = (UCHAR)i;
3075 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3078 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3079 // max tx rate = min {max desire rate, max supported rate}
3080 if (MaxSupport < MaxDesire)
3081 pAd->CommonCfg.MaxTxRate = MaxSupport;
3083 pAd->CommonCfg.MaxTxRate = MaxDesire;
3085 pAd->CommonCfg.MinTxRate = MinSupport;
3086 if (*auto_rate_cur_p)
3089 #ifdef CONFIG_STA_SUPPORT
3090 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3091 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3092 #endif // CONFIG_STA_SUPPORT //
3093 if (bLinkUp == TRUE)
3094 pAd->CommonCfg.TxRate = RATE_24;
3096 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3099 pAd->CommonCfg.TxRate = RATE_11;
3101 pAd->CommonCfg.TxRate = RATE_24;
3103 // should never exceed MaxTxRate (consider 11B-only mode)
3104 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3105 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3107 pAd->CommonCfg.TxRateIndex = 0;
3111 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3112 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3113 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3115 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3116 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3117 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3118 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3121 if (pAd->CommonCfg.TxRate <= RATE_11)
3123 pMaxHtPhy->field.MODE = MODE_CCK;
3124 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3125 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3129 pMaxHtPhy->field.MODE = MODE_OFDM;
3130 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3131 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3132 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3134 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3137 pHtPhy->word = (pMaxHtPhy->word);
3138 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3140 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3141 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3142 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3146 switch (pAd->CommonCfg.PhyMode)
3148 case PHY_11BG_MIXED:
3150 #ifdef DOT11_N_SUPPORT
3151 case PHY_11BGN_MIXED:
3152 #endif // DOT11_N_SUPPORT //
3153 pAd->CommonCfg.MlmeRate = RATE_1;
3154 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3155 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3156 pAd->CommonCfg.RtsRate = RATE_11;
3160 #ifdef DOT11_N_SUPPORT
3161 case PHY_11AGN_MIXED:
3162 case PHY_11GN_MIXED:
3164 case PHY_11AN_MIXED:
3166 #endif // DOT11_N_SUPPORT //
3167 pAd->CommonCfg.MlmeRate = RATE_6;
3168 pAd->CommonCfg.RtsRate = RATE_6;
3169 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3170 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3172 case PHY_11ABG_MIXED:
3173 #ifdef DOT11_N_SUPPORT
3174 case PHY_11ABGN_MIXED:
3175 #endif // DOT11_N_SUPPORT //
3176 if (pAd->CommonCfg.Channel <= 14)
3178 pAd->CommonCfg.MlmeRate = RATE_1;
3179 pAd->CommonCfg.RtsRate = RATE_1;
3180 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3181 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3185 pAd->CommonCfg.MlmeRate = RATE_6;
3186 pAd->CommonCfg.RtsRate = RATE_6;
3187 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3188 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3192 pAd->CommonCfg.MlmeRate = RATE_6;
3193 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3194 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3195 pAd->CommonCfg.RtsRate = RATE_1;
3199 // Keep Basic Mlme Rate.
3201 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3202 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3203 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3205 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3206 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3209 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3210 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3211 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3212 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3213 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3214 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3215 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 ));
3218 #ifdef DOT11_N_SUPPORT
3220 ==========================================================================
3222 This function update HT Rate setting.
3223 Input Wcid value is valid for 2 case :
3224 1. it's used for Station in infra mode that copy AP rate to Mactable.
3225 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3227 IRQL = DISPATCH_LEVEL
3229 ==========================================================================
3231 VOID MlmeUpdateHtTxRates(
3232 IN PRTMP_ADAPTER pAd,
3235 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3237 RT_HT_CAPABILITY *pRtHtCap = NULL;
3238 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3241 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3242 PHTTRANSMIT_SETTING pHtPhy = NULL;
3243 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3244 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3245 BOOLEAN *auto_rate_cur_p;
3247 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3249 auto_rate_cur_p = NULL;
3251 #ifdef CONFIG_STA_SUPPORT
3252 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3254 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3255 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3256 pHtPhy = &pAd->StaCfg.HTPhyMode;
3257 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3258 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3260 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3262 #endif // CONFIG_STA_SUPPORT //
3264 #ifdef CONFIG_STA_SUPPORT
3265 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3267 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3270 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3271 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3272 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3273 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3274 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3275 pMaxHtPhy->field.STBC = STBC_USE;
3277 pMaxHtPhy->field.STBC = STBC_NONE;
3280 #endif // CONFIG_STA_SUPPORT //
3282 if (pDesireHtPhy->bHtEnable == FALSE)
3285 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3286 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3287 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3288 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3289 pMaxHtPhy->field.STBC = STBC_USE;
3291 pMaxHtPhy->field.STBC = STBC_NONE;
3294 // Decide MAX ht rate.
3295 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3296 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3298 pMaxHtPhy->field.MODE = MODE_HTMIX;
3300 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3301 pMaxHtPhy->field.BW = BW_40;
3303 pMaxHtPhy->field.BW = BW_20;
3305 if (pMaxHtPhy->field.BW == BW_20)
3306 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3308 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3310 for (i=23; i>=0; i--) // 3*3
3313 bitmask = (1<<(i-(j*8)));
3315 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3317 pMaxHtPhy->field.MCS = i;
3325 // Copy MIN ht rate. rt2860???
3326 pMinHtPhy->field.BW = BW_20;
3327 pMinHtPhy->field.MCS = 0;
3328 pMinHtPhy->field.STBC = 0;
3329 pMinHtPhy->field.ShortGI = 0;
3330 //If STA assigns fixed rate. update to fixed here.
3331 #ifdef CONFIG_STA_SUPPORT
3332 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3334 if (pDesireHtPhy->MCSSet[4] != 0)
3336 pMaxHtPhy->field.MCS = 32;
3337 pMinHtPhy->field.MCS = 32;
3338 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3341 for (i=23; (CHAR)i >= 0; i--) // 3*3
3344 bitmask = (1<<(i-(j*8)));
3345 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3347 pMaxHtPhy->field.MCS = i;
3348 pMinHtPhy->field.MCS = i;
3355 #endif // CONFIG_STA_SUPPORT //
3359 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3360 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3361 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3362 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3363 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3365 // use default now. rt2860
3366 if (pDesireHtPhy->MCSSet[0] != 0xff)
3367 *auto_rate_cur_p = FALSE;
3369 *auto_rate_cur_p = TRUE;
3371 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3372 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3373 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3374 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3376 #endif // DOT11_N_SUPPORT //
3378 // IRQL = DISPATCH_LEVEL
3380 IN PRTMP_ADAPTER pAd)
3382 RT28XX_MLME_RADIO_OFF(pAd);
3385 // IRQL = DISPATCH_LEVEL
3387 IN PRTMP_ADAPTER pAd)
3389 RT28XX_MLME_RADIO_ON(pAd);
3392 // ===========================================================================================
3394 // ===========================================================================================
3397 /*! \brief initialize BSS table
3398 * \param p_tab pointer to the table
3403 IRQL = PASSIVE_LEVEL
3404 IRQL = DISPATCH_LEVEL
3413 Tab->BssOverlapNr = 0;
3414 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3416 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3417 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3421 #ifdef DOT11_N_SUPPORT
3423 IN PRTMP_ADAPTER pAd,
3428 Tab->numAsOriginator = 0;
3429 Tab->numAsRecipient = 0;
3430 NdisAllocateSpinLock(&pAd->BATabLock);
3431 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3433 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3434 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3436 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3438 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3441 #endif // DOT11_N_SUPPORT //
3443 /*! \brief search the BSS table by SSID
3444 * \param p_tab pointer to the bss table
3445 * \param ssid SSID string
3446 * \return index of the table, BSS_NOT_FOUND if not in the table
3449 * \note search by sequential search
3451 IRQL = DISPATCH_LEVEL
3454 ULONG BssTableSearch(
3461 for (i = 0; i < Tab->BssNr; i++)
3464 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3465 // We should distinguish this case.
3467 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3468 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3469 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3474 return (ULONG)BSS_NOT_FOUND;
3477 ULONG BssSsidTableSearch(
3486 for (i = 0; i < Tab->BssNr; i++)
3489 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3490 // We should distinguish this case.
3492 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3493 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3494 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3495 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3500 return (ULONG)BSS_NOT_FOUND;
3503 ULONG BssTableSearchWithSSID(
3512 for (i = 0; i < Tab->BssNr; i++)
3514 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3515 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3516 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3517 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3518 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3519 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3524 return (ULONG)BSS_NOT_FOUND;
3527 // IRQL = DISPATCH_LEVEL
3528 VOID BssTableDeleteEntry(
3529 IN OUT BSS_TABLE *Tab,
3535 for (i = 0; i < Tab->BssNr; i++)
3537 if ((Tab->BssEntry[i].Channel == Channel) &&
3538 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3540 for (j = i; j < Tab->BssNr - 1; j++)
3542 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3544 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3551 #ifdef DOT11_N_SUPPORT
3553 ========================================================================
3554 Routine Description:
3555 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3558 // IRQL = DISPATCH_LEVEL
3559 ========================================================================
3561 VOID BATableDeleteORIEntry(
3562 IN OUT PRTMP_ADAPTER pAd,
3563 IN BA_ORI_ENTRY *pBAORIEntry)
3566 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3568 NdisAcquireSpinLock(&pAd->BATabLock);
3569 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3571 pAd->BATable.numAsOriginator -= 1;
3572 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3573 // Erase Bitmap flag.
3575 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3576 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3577 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3578 pBAORIEntry->Token = 1;
3579 // Not clear Sequence here.
3580 NdisReleaseSpinLock(&pAd->BATabLock);
3583 #endif // DOT11_N_SUPPORT //
3591 IRQL = DISPATCH_LEVEL
3595 IN PRTMP_ADAPTER pAd,
3596 OUT BSS_ENTRY *pBss,
3601 IN USHORT BeaconPeriod,
3602 IN PCF_PARM pCfParm,
3604 IN USHORT CapabilityInfo,
3606 IN UCHAR SupRateLen,
3608 IN UCHAR ExtRateLen,
3609 IN HT_CAPABILITY_IE *pHtCapability,
3610 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3611 IN UCHAR HtCapabilityLen,
3612 IN UCHAR AddHtInfoLen,
3613 IN UCHAR NewExtChanOffset,
3616 IN LARGE_INTEGER TimeStamp,
3618 IN PEDCA_PARM pEdcaParm,
3619 IN PQOS_CAPABILITY_PARM pQosCapability,
3620 IN PQBSS_LOAD_PARM pQbssLoad,
3621 IN USHORT LengthVIE,
3622 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3624 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3625 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3629 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3630 // Or send beacon /probe response with SSID len matching real SSID length,
3631 // but SSID is all zero. such as "00-00-00-00" with length 4.
3632 // We have to prevent this case overwrite correct table
3633 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3635 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3636 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3637 pBss->SsidLen = SsidLen;
3643 pBss->BssType = BssType;
3644 pBss->BeaconPeriod = BeaconPeriod;
3645 if (BssType == BSS_INFRA)
3647 if (pCfParm->bValid)
3649 pBss->CfpCount = pCfParm->CfpCount;
3650 pBss->CfpPeriod = pCfParm->CfpPeriod;
3651 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3652 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3657 pBss->AtimWin = AtimWin;
3660 pBss->CapabilityInfo = CapabilityInfo;
3661 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3662 // Combine with AuthMode, they will decide the connection methods.
3663 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3664 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3665 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3666 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3668 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3669 pBss->SupRateLen = SupRateLen;
3670 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3671 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3672 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3673 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3674 pBss->NewExtChanOffset = NewExtChanOffset;
3675 pBss->ExtRateLen = ExtRateLen;
3676 pBss->Channel = Channel;
3677 pBss->CentralChannel = Channel;
3679 // Update CkipFlag. if not exists, the value is 0x0
3680 pBss->CkipFlag = CkipFlag;
3682 // New for microsoft Fixed IEs
3683 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3684 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3685 pBss->FixIEs.Capabilities = CapabilityInfo;
3687 // New for microsoft Variable IEs
3690 pBss->VarIELen = LengthVIE;
3691 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3698 pBss->AddHtInfoLen = 0;
3699 pBss->HtCapabilityLen = 0;
3700 #ifdef DOT11_N_SUPPORT
3701 if (HtCapabilityLen> 0)
3703 pBss->HtCapabilityLen = HtCapabilityLen;
3704 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3705 if (AddHtInfoLen > 0)
3707 pBss->AddHtInfoLen = AddHtInfoLen;
3708 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3710 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3712 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3714 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3716 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3720 #endif // DOT11_N_SUPPORT //
3722 BssCipherParse(pBss);
3726 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3728 pBss->EdcaParm.bValid = FALSE;
3730 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3732 pBss->QosCapability.bValid = FALSE;
3734 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3736 pBss->QbssLoad.bValid = FALSE;
3738 #ifdef CONFIG_STA_SUPPORT
3739 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3745 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3746 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3747 #ifdef EXT_BUILD_CHANNEL_LIST
3748 NdisZeroMemory(&pBss->CountryString[0], 3);
3749 pBss->bHasCountryIE = FALSE;
3750 #endif // EXT_BUILD_CHANNEL_LIST //
3751 pEid = (PEID_STRUCT) pVIE;
3752 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3757 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3759 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3761 pBss->WpaIE.IELen = 0;
3764 pBss->WpaIE.IELen = pEid->Len + 2;
3765 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3769 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3771 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3773 pBss->RsnIE.IELen = 0;
3776 pBss->RsnIE.IELen = pEid->Len + 2;
3777 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3780 #ifdef EXT_BUILD_CHANNEL_LIST
3782 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3783 pBss->bHasCountryIE = TRUE;
3785 #endif // EXT_BUILD_CHANNEL_LIST //
3787 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3788 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3791 #endif // CONFIG_STA_SUPPORT //
3795 * \brief insert an entry into the bss table
3796 * \param p_tab The BSS table
3797 * \param Bssid BSSID
3799 * \param ssid_len Length of SSID
3801 * \param beacon_period
3808 * \param channel_idx
3812 * \note If SSID is identical, the old entry will be replaced by the new one
3814 IRQL = DISPATCH_LEVEL
3817 ULONG BssTableSetEntry(
3818 IN PRTMP_ADAPTER pAd,
3824 IN USHORT BeaconPeriod,
3827 IN USHORT CapabilityInfo,
3829 IN UCHAR SupRateLen,
3831 IN UCHAR ExtRateLen,
3832 IN HT_CAPABILITY_IE *pHtCapability,
3833 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3834 IN UCHAR HtCapabilityLen,
3835 IN UCHAR AddHtInfoLen,
3836 IN UCHAR NewExtChanOffset,
3839 IN LARGE_INTEGER TimeStamp,
3841 IN PEDCA_PARM pEdcaParm,
3842 IN PQOS_CAPABILITY_PARM pQosCapability,
3843 IN PQBSS_LOAD_PARM pQbssLoad,
3844 IN USHORT LengthVIE,
3845 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3849 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3850 if (Idx == BSS_NOT_FOUND)
3852 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3855 // It may happen when BSS Table was full.
3856 // The desired AP will not be added into BSS Table
3857 // In this case, if we found the desired AP then overwrite BSS Table.
3859 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3861 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3862 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3864 Idx = Tab->BssOverlapNr;
3865 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3866 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3867 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3868 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3874 return BSS_NOT_FOUND;
3878 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3879 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3880 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3885 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3886 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3887 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3893 #ifdef CONFIG_STA_SUPPORT
3894 #ifdef DOT11_N_SUPPORT
3895 #ifdef DOT11N_DRAFT3
3897 IN PRTMP_ADAPTER pAd)
3901 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3902 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3904 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3905 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3908 ULONG TriEventTableSetEntry(
3909 IN PRTMP_ADAPTER pAd,
3910 OUT TRIGGER_EVENT_TAB *Tab,
3912 IN HT_CAPABILITY_IE *pHtCapability,
3913 IN UCHAR HtCapabilityLen,
3918 if (HtCapabilityLen == 0)
3920 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3922 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3923 Tab->EventA[Tab->EventANo].bValid = TRUE;
3924 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3925 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3928 // Beacon has Regulatory class IE. So use beacon's
3929 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3933 // Use Station's Regulatory class instead.
3934 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3936 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3938 Tab->EventA[Tab->EventANo].RegClass = 32;
3940 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3941 Tab->EventA[Tab->EventANo].RegClass = 33;
3944 Tab->EventA[Tab->EventANo].RegClass = ??;
3951 else if (pHtCapability->HtCapInfo.Intolerant40)
3953 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3959 ========================================================================
3960 Routine Description:
3961 Trigger Event table Maintainence called once every second.
3964 // IRQL = DISPATCH_LEVEL
3965 ========================================================================
3967 VOID TriEventCounterMaintenance(
3968 IN PRTMP_ADAPTER pAd)
3971 BOOLEAN bNotify = FALSE;
3972 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3974 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3976 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3977 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3979 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3980 pAd->CommonCfg.TriggerEventTab.EventANo --;
3981 // Need to send 20/40 Coexistence Notify frame if has status change.
3986 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
3988 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
3989 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
3993 if (bNotify == TRUE)
3994 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
3996 #endif // DOT11N_DRAFT3 //
3997 #endif // DOT11_N_SUPPORT //
3999 // IRQL = DISPATCH_LEVEL
4000 VOID BssTableSsidSort(
4001 IN PRTMP_ADAPTER pAd,
4002 OUT BSS_TABLE *OutTab,
4007 BssTableInit(OutTab);
4009 for (i = 0; i < pAd->ScanTab.BssNr; i++)
4011 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
4012 BOOLEAN bIsHiddenApIncluded = FALSE;
4014 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
4015 (pAd->MlmeAux.Channel > 14) &&
4016 RadarChannelCheck(pAd, pInBss->Channel))
4017 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
4018 || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
4019 #endif // CARRIER_DETECTION_SUPPORT //
4023 bIsHiddenApIncluded = TRUE;
4026 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
4027 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
4029 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4032 #ifdef EXT_BUILD_CHANNEL_LIST
4033 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
4034 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
4035 (pInBss->bHasCountryIE == FALSE))
4037 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
4040 #endif // EXT_BUILD_CHANNEL_LIST //
4042 #ifdef DOT11_N_SUPPORT
4043 // 2.4G/5G N only mode
4044 if ((pInBss->HtCapabilityLen == 0) &&
4045 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4047 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4050 #endif // DOT11_N_SUPPORT //
4053 // Check the Authmode first
4054 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4056 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4057 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4061 // Check cipher suite, AP must have more secured cipher than station setting
4062 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4064 // If it's not mixed mode, we should only let BSS pass with the same encryption
4065 if (pInBss->WPA.bMixMode == FALSE)
4066 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4069 // check group cipher
4070 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4071 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4072 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
4075 // check pairwise cipher, skip if none matched
4076 // If profile set to AES, let it pass without question.
4077 // If profile set to TKIP, we must find one mateched
4078 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4079 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4080 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4083 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4085 // If it's not mixed mode, we should only let BSS pass with the same encryption
4086 if (pInBss->WPA2.bMixMode == FALSE)
4087 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4090 // check group cipher
4091 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4092 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4093 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
4096 // check pairwise cipher, skip if none matched
4097 // If profile set to AES, let it pass without question.
4098 // If profile set to TKIP, we must find one mateched
4099 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4100 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4101 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4105 // Bss Type matched, SSID matched.
4106 // We will check wepstatus for qualification Bss
4107 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4109 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4111 // For the SESv2 case, we will not qualify WepStatus.
4117 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4118 // It definitely will fail. So, skip it.
4119 // CCX also require not even try to connect it!!
4123 #ifdef DOT11_N_SUPPORT
4124 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4125 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4126 if ((pInBss->CentralChannel != pInBss->Channel) &&
4127 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4129 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4131 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4133 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4137 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4143 #endif // DOT11_N_SUPPORT //
4145 // copy matching BSS from InTab to OutTab
4146 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4150 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4152 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4155 #ifdef DOT11_N_SUPPORT
4156 // 2.4G/5G N only mode
4157 if ((pInBss->HtCapabilityLen == 0) &&
4158 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4160 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4163 #endif // DOT11_N_SUPPORT //
4166 // Check the Authmode first
4167 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4169 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4170 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4174 // Check cipher suite, AP must have more secured cipher than station setting
4175 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4177 // If it's not mixed mode, we should only let BSS pass with the same encryption
4178 if (pInBss->WPA.bMixMode == FALSE)
4179 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4182 // check group cipher
4183 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4186 // check pairwise cipher, skip if none matched
4187 // If profile set to AES, let it pass without question.
4188 // If profile set to TKIP, we must find one mateched
4189 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4190 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4191 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4194 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4196 // If it's not mixed mode, we should only let BSS pass with the same encryption
4197 if (pInBss->WPA2.bMixMode == FALSE)
4198 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4201 // check group cipher
4202 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4205 // check pairwise cipher, skip if none matched
4206 // If profile set to AES, let it pass without question.
4207 // If profile set to TKIP, we must find one mateched
4208 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4209 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4210 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4214 // Bss Type matched, SSID matched.
4215 // We will check wepstatus for qualification Bss
4216 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4219 #ifdef DOT11_N_SUPPORT
4220 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4221 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4222 if ((pInBss->CentralChannel != pInBss->Channel) &&
4223 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4225 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4227 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4229 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4232 #endif // DOT11_N_SUPPORT //
4234 // copy matching BSS from InTab to OutTab
4235 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4240 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4244 BssTableSortByRssi(OutTab);
4248 // IRQL = DISPATCH_LEVEL
4249 VOID BssTableSortByRssi(
4250 IN OUT BSS_TABLE *OutTab)
4255 for (i = 0; i < OutTab->BssNr - 1; i++)
4257 for (j = i+1; j < OutTab->BssNr; j++)
4259 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4261 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4262 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4263 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4268 #endif // CONFIG_STA_SUPPORT //
4271 VOID BssCipherParse(
4272 IN OUT PBSS_ENTRY pBss)
4276 PRSN_IE_HEADER_STRUCT pRsnHeader;
4277 PCIPHER_SUITE_STRUCT pCipher;
4278 PAKM_SUITE_STRUCT pAKM;
4281 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4284 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4288 pBss->WepStatus = Ndis802_11WEPEnabled;
4292 pBss->WepStatus = Ndis802_11WEPDisabled;
4294 // Set default to disable & open authentication before parsing variable IE
4295 pBss->AuthMode = Ndis802_11AuthModeOpen;
4296 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4299 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4300 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4301 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4302 pBss->WPA.RsnCapability = 0;
4303 pBss->WPA.bMixMode = FALSE;
4305 // Init WPA2 setting
4306 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4307 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4308 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4309 pBss->WPA2.RsnCapability = 0;
4310 pBss->WPA2.bMixMode = FALSE;
4313 Length = (INT) pBss->VarIELen;
4317 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4318 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4319 pEid = (PEID_STRUCT) pTmp;
4323 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4324 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4330 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4331 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4332 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4333 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4336 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4337 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4338 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4341 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4342 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4343 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4349 // if Cisco IE_WPA, break
4352 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4357 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4359 // if unsupported vendor specific IE
4362 // Skip OUI, version, and multicast suite
4363 // This part should be improved in the future when AP supported multiple cipher suite.
4364 // For now, it's OK since almost all APs have fixed cipher suite supported.
4365 // pTmp = (PUCHAR) pEid->Octet;
4368 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4376 // Parse group cipher
4380 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4383 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4386 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4389 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4394 // number of unicast suite
4397 // skip all unicast cipher suites
4398 //Count = *(PUSHORT) pTmp;
4399 Count = (pTmp[1]<<8) + pTmp[0];
4400 pTmp += sizeof(USHORT);
4402 // Parsing all unicast cipher suite
4407 TmpCipher = Ndis802_11WEPDisabled;
4411 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4412 TmpCipher = Ndis802_11Encryption1Enabled;
4415 TmpCipher = Ndis802_11Encryption2Enabled;
4418 TmpCipher = Ndis802_11Encryption3Enabled;
4423 if (TmpCipher > pBss->WPA.PairCipher)
4425 // Move the lower cipher suite to PairCipherAux
4426 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4427 pBss->WPA.PairCipher = TmpCipher;
4431 pBss->WPA.PairCipherAux = TmpCipher;
4437 // 4. get AKM suite counts
4438 //Count = *(PUSHORT) pTmp;
4439 Count = (pTmp[1]<<8) + pTmp[0];
4440 pTmp += sizeof(USHORT);
4446 // Set AP support WPA mode
4447 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4448 pBss->AuthMode = Ndis802_11AuthModeWPA;
4450 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4453 // Set AP support WPA mode
4454 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4455 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4457 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4464 // Fixed for WPA-None
4465 if (pBss->BssType == BSS_ADHOC)
4467 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4468 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4469 pBss->WepStatus = pBss->WPA.GroupCipher;
4470 // Patched bugs for old driver
4471 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4472 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4475 pBss->WepStatus = pBss->WPA.PairCipher;
4477 // Check the Pair & Group, if different, turn on mixed mode flag
4478 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4479 pBss->WPA.bMixMode = TRUE;
4484 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4486 // 0. Version must be 1
4487 if (le2cpu16(pRsnHeader->Version) != 1)
4489 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4491 // 1. Check group cipher
4492 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4493 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4496 // Parse group cipher
4497 switch (pCipher->Type)
4500 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4503 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4506 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4509 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4514 // set to correct offset for next parsing
4515 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4517 // 2. Get pairwise cipher counts
4518 //Count = *(PUSHORT) pTmp;
4519 Count = (pTmp[1]<<8) + pTmp[0];
4520 pTmp += sizeof(USHORT);
4522 // 3. Get pairwise cipher
4523 // Parsing all unicast cipher suite
4527 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4528 TmpCipher = Ndis802_11WEPDisabled;
4529 switch (pCipher->Type)
4532 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4533 TmpCipher = Ndis802_11Encryption1Enabled;
4536 TmpCipher = Ndis802_11Encryption2Enabled;
4539 TmpCipher = Ndis802_11Encryption3Enabled;
4544 if (TmpCipher > pBss->WPA2.PairCipher)
4546 // Move the lower cipher suite to PairCipherAux
4547 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4548 pBss->WPA2.PairCipher = TmpCipher;
4552 pBss->WPA2.PairCipherAux = TmpCipher;
4554 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4558 // 4. get AKM suite counts
4559 //Count = *(PUSHORT) pTmp;
4560 Count = (pTmp[1]<<8) + pTmp[0];
4561 pTmp += sizeof(USHORT);
4563 // 5. Get AKM ciphers
4564 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4565 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4571 // Set AP support WPA mode
4572 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4573 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4575 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4578 // Set AP support WPA mode
4579 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4580 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4582 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4587 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4589 // Fixed for WPA-None
4590 if (pBss->BssType == BSS_ADHOC)
4592 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4593 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4594 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4595 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4596 pBss->WepStatus = pBss->WPA.GroupCipher;
4597 // Patched bugs for old driver
4598 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4599 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4601 pBss->WepStatus = pBss->WPA2.PairCipher;
4603 // 6. Get RSN capability
4604 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4605 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4606 pTmp += sizeof(USHORT);
4608 // Check the Pair & Group, if different, turn on mixed mode flag
4609 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4610 pBss->WPA2.bMixMode = TRUE;
4616 Length -= (pEid->Len + 2);
4620 // ===========================================================================================
4622 // ===========================================================================================
4624 /*! \brief generates a random mac address value for IBSS BSSID
4625 * \param Addr the bssid location
4630 VOID MacAddrRandomBssid(
4631 IN PRTMP_ADAPTER pAd,
4636 for (i = 0; i < MAC_ADDR_LEN; i++)
4638 pAddr[i] = RandomByte(pAd);
4641 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4644 /*! \brief init the management mac frame header
4645 * \param p_hdr mac header
4646 * \param subtype subtype of the frame
4647 * \param p_ds destination address, don't care if it is a broadcast address
4649 * \pre the station has the following information in the pAd->StaCfg
4653 * \note this function initializes the following field
4655 IRQL = PASSIVE_LEVEL
4656 IRQL = DISPATCH_LEVEL
4659 VOID MgtMacHeaderInit(
4660 IN PRTMP_ADAPTER pAd,
4661 IN OUT PHEADER_802_11 pHdr80211,
4667 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4669 pHdr80211->FC.Type = BTYPE_MGMT;
4670 pHdr80211->FC.SubType = SubType;
4671 pHdr80211->FC.ToDs = ToDs;
4672 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4673 #ifdef CONFIG_STA_SUPPORT
4674 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4675 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4676 #endif // CONFIG_STA_SUPPORT //
4677 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4680 // ===========================================================================================
4682 // ===========================================================================================
4684 /*!***************************************************************************
4685 * This routine build an outgoing frame, and fill all information specified
4686 * in argument list to the frame body. The actual frame size is the summation
4689 * Buffer - pointer to a pre-allocated memory segment
4690 * args - a list of <int arg_size, arg> pairs.
4691 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4692 * function will FAIL!!!
4694 * Size of the buffer
4696 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4698 IRQL = PASSIVE_LEVEL
4699 IRQL = DISPATCH_LEVEL
4701 ****************************************************************************/
4702 ULONG MakeOutgoingFrame(
4704 OUT ULONG *FrameLen, ...)
4711 // calculates the total length
4713 va_start(Args, FrameLen);
4716 leng = va_arg(Args, int);
4717 if (leng == END_OF_ARGS)
4721 p = va_arg(Args, PVOID);
4722 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4723 TotLeng = TotLeng + leng;
4726 va_end(Args); /* clean up */
4727 *FrameLen = TotLeng;
4731 // ===========================================================================================
4733 // ===========================================================================================
4735 /*! \brief Initialize The MLME Queue, used by MLME Functions
4736 * \param *Queue The MLME Queue
4737 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4740 * \note Because this is done only once (at the init stage), no need to be locked
4742 IRQL = PASSIVE_LEVEL
4745 NDIS_STATUS MlmeQueueInit(
4746 IN MLME_QUEUE *Queue)
4750 NdisAllocateSpinLock(&Queue->Lock);
4756 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4758 Queue->Entry[i].Occupied = FALSE;
4759 Queue->Entry[i].MsgLen = 0;
4760 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4763 return NDIS_STATUS_SUCCESS;
4766 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4767 * \param *Queue The MLME Queue
4768 * \param Machine The State Machine Id
4769 * \param MsgType The Message Type
4770 * \param MsgLen The Message length
4771 * \param *Msg The message pointer
4772 * \return TRUE if enqueue is successful, FALSE if the queue is full
4775 * \note The message has to be initialized
4777 IRQL = PASSIVE_LEVEL
4778 IRQL = DISPATCH_LEVEL
4781 BOOLEAN MlmeEnqueue(
4782 IN PRTMP_ADAPTER pAd,
4789 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4791 // Do nothing if the driver is starting halt state.
4792 // This might happen when timer already been fired before cancel timer with mlmehalt
4793 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4796 // First check the size, it MUST not exceed the mlme queue size
4797 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4799 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4803 if (MlmeQueueFull(Queue))
4808 NdisAcquireSpinLock(&(Queue->Lock));
4812 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4817 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4818 Queue->Entry[Tail].Occupied = TRUE;
4819 Queue->Entry[Tail].Machine = Machine;
4820 Queue->Entry[Tail].MsgType = MsgType;
4821 Queue->Entry[Tail].MsgLen = MsgLen;
4825 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4828 NdisReleaseSpinLock(&(Queue->Lock));
4832 /*! \brief This function is used when Recv gets a MLME message
4833 * \param *Queue The MLME Queue
4834 * \param TimeStampHigh The upper 32 bit of timestamp
4835 * \param TimeStampLow The lower 32 bit of timestamp
4836 * \param Rssi The receiving RSSI strength
4837 * \param MsgLen The length of the message
4838 * \param *Msg The message pointer
4839 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4843 IRQL = DISPATCH_LEVEL
4846 BOOLEAN MlmeEnqueueForRecv(
4847 IN PRTMP_ADAPTER pAd,
4849 IN ULONG TimeStampHigh,
4850 IN ULONG TimeStampLow,
4859 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4861 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
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 MLME_QUEUE_ELEM *Elem = NULL;
4961 #ifdef CONFIG_STA_SUPPORT
4963 #endif // CONFIG_STA_SUPPORT //
4965 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4967 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4968 if(pAd->Mlme.bRunning)
4970 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4975 pAd->Mlme.bRunning = TRUE;
4977 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4979 // Remove all Mlme queues elements
4980 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4982 //From message type, determine which state machine I should drive
4983 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4985 // free MLME element
4986 Elem->Occupied = FALSE;
4991 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4995 #ifdef CONFIG_STA_SUPPORT
4996 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4998 #ifdef QOS_DLS_SUPPORT
5000 #endif // QOS_DLS_SUPPORT //
5001 // Cancel all timer events
5002 // Be careful to cancel new added timer
5003 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
5004 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
5005 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
5006 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
5007 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
5008 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
5010 #ifdef QOS_DLS_SUPPORT
5011 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
5013 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
5015 #endif // QOS_DLS_SUPPORT //
5017 #endif // CONFIG_STA_SUPPORT //
5019 // Change back to original channel in case of doing scan
5020 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
5021 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
5023 // Resume MSDU which is turned off durning scan
5024 RTMPResumeMsduTransmission(pAd);
5026 #ifdef CONFIG_STA_SUPPORT
5027 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5029 // Set all state machines back IDLE
5030 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
5031 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
5032 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
5033 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
5034 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
5035 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
5036 #ifdef QOS_DLS_SUPPORT
5037 pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
5038 #endif // QOS_DLS_SUPPORT //
5040 #endif // CONFIG_STA_SUPPORT //
5042 // Remove running state
5043 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
5044 pAd->Mlme.bRunning = FALSE;
5045 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
5048 /*! \brief test if the MLME Queue is empty
5049 * \param *Queue The MLME Queue
5050 * \return TRUE if the Queue is empty, FALSE otherwise
5054 IRQL = DISPATCH_LEVEL
5057 BOOLEAN MlmeQueueEmpty(
5058 IN MLME_QUEUE *Queue)
5062 NdisAcquireSpinLock(&(Queue->Lock));
5063 Ans = (Queue->Num == 0);
5064 NdisReleaseSpinLock(&(Queue->Lock));
5069 /*! \brief test if the MLME Queue is full
5070 * \param *Queue The MLME Queue
5071 * \return TRUE if the Queue is empty, FALSE otherwise
5075 IRQL = PASSIVE_LEVEL
5076 IRQL = DISPATCH_LEVEL
5079 BOOLEAN MlmeQueueFull(
5080 IN MLME_QUEUE *Queue)
5084 NdisAcquireSpinLock(&(Queue->Lock));
5085 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5086 NdisReleaseSpinLock(&(Queue->Lock));
5091 /*! \brief The destructor of MLME Queue
5096 * \note Clear Mlme Queue, Set Queue->Num to Zero.
5098 IRQL = PASSIVE_LEVEL
5101 VOID MlmeQueueDestroy(
5102 IN MLME_QUEUE *pQueue)
5104 NdisAcquireSpinLock(&(pQueue->Lock));
5108 NdisReleaseSpinLock(&(pQueue->Lock));
5109 NdisFreeSpinLock(&(pQueue->Lock));
5112 /*! \brief To substitute the message type if the message is coming from external
5113 * \param pFrame The frame received
5114 * \param *Machine The state machine
5115 * \param *MsgType the message type for the state machine
5116 * \return TRUE if the substitution is successful, FALSE otherwise
5120 IRQL = DISPATCH_LEVEL
5123 #ifdef CONFIG_STA_SUPPORT
5124 BOOLEAN MsgTypeSubst(
5125 IN PRTMP_ADAPTER pAd,
5126 IN PFRAME_802_11 pFrame,
5134 // Pointer to start of data frames including SNAP header
5135 pData = (PUCHAR) pFrame + LENGTH_802_11;
5137 // The only data type will pass to this function is EAPOL frame
5138 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5140 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5142 // Cisco Aironet SNAP header
5143 *Machine = AIRONET_STATE_MACHINE;
5144 *MsgType = MT2_AIRONET_MSG;
5148 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5151 *Machine = LEAP_STATE_MACHINE;
5152 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5153 return (LeapMsgTypeSubst(EAPType, MsgType));
5156 #endif // LEAP_SUPPORT //
5158 *Machine = WPA_PSK_STATE_MACHINE;
5159 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5160 return(WpaMsgTypeSubst(EAPType, MsgType));
5164 switch (pFrame->Hdr.FC.SubType)
5166 case SUBTYPE_ASSOC_REQ:
5167 *Machine = ASSOC_STATE_MACHINE;
5168 *MsgType = MT2_PEER_ASSOC_REQ;
5170 case SUBTYPE_ASSOC_RSP:
5171 *Machine = ASSOC_STATE_MACHINE;
5172 *MsgType = MT2_PEER_ASSOC_RSP;
5174 case SUBTYPE_REASSOC_REQ:
5175 *Machine = ASSOC_STATE_MACHINE;
5176 *MsgType = MT2_PEER_REASSOC_REQ;
5178 case SUBTYPE_REASSOC_RSP:
5179 *Machine = ASSOC_STATE_MACHINE;
5180 *MsgType = MT2_PEER_REASSOC_RSP;
5182 case SUBTYPE_PROBE_REQ:
5183 *Machine = SYNC_STATE_MACHINE;
5184 *MsgType = MT2_PEER_PROBE_REQ;
5186 case SUBTYPE_PROBE_RSP:
5187 *Machine = SYNC_STATE_MACHINE;
5188 *MsgType = MT2_PEER_PROBE_RSP;
5190 case SUBTYPE_BEACON:
5191 *Machine = SYNC_STATE_MACHINE;
5192 *MsgType = MT2_PEER_BEACON;
5195 *Machine = SYNC_STATE_MACHINE;
5196 *MsgType = MT2_PEER_ATIM;
5198 case SUBTYPE_DISASSOC:
5199 *Machine = ASSOC_STATE_MACHINE;
5200 *MsgType = MT2_PEER_DISASSOC_REQ;
5203 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5204 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5205 if (Seq == 1 || Seq == 3)
5207 *Machine = AUTH_RSP_STATE_MACHINE;
5208 *MsgType = MT2_PEER_AUTH_ODD;
5210 else if (Seq == 2 || Seq == 4)
5212 *Machine = AUTH_STATE_MACHINE;
5213 *MsgType = MT2_PEER_AUTH_EVEN;
5220 case SUBTYPE_DEAUTH:
5221 *Machine = AUTH_RSP_STATE_MACHINE;
5222 *MsgType = MT2_PEER_DEAUTH;
5224 case SUBTYPE_ACTION:
5225 *Machine = ACTION_STATE_MACHINE;
5226 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5227 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5229 *MsgType = MT2_ACT_INVALID;
5233 *MsgType = (pFrame->Octet[0]&0x7F);
5243 #endif // CONFIG_STA_SUPPORT //
5245 // ===========================================================================================
5247 // ===========================================================================================
5249 /*! \brief Initialize the state machine.
5250 * \param *S pointer to the state machine
5251 * \param Trans State machine transition function
5252 * \param StNr number of states
5253 * \param MsgNr number of messages
5254 * \param DefFunc default function, when there is invalid state/message combination
5255 * \param InitState initial state of the state machine
5256 * \param Base StateMachine base, internal use only
5257 * \pre p_sm should be a legal pointer
5260 IRQL = PASSIVE_LEVEL
5263 VOID StateMachineInit(
5264 IN STATE_MACHINE *S,
5265 IN STATE_MACHINE_FUNC Trans[],
5268 IN STATE_MACHINE_FUNC DefFunc,
5274 // set number of states and messages
5279 S->TransFunc = Trans;
5281 // init all state transition to default function
5282 for (i = 0; i < StNr; i++)
5284 for (j = 0; j < MsgNr; j++)
5286 S->TransFunc[i * MsgNr + j] = DefFunc;
5290 // set the starting state
5291 S->CurrState = InitState;
5294 /*! \brief This function fills in the function pointer into the cell in the state machine
5295 * \param *S pointer to the state machine
5297 * \param Msg incoming message
5298 * \param f the function to be executed when (state, message) combination occurs at the state machine
5299 * \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
5302 IRQL = PASSIVE_LEVEL
5305 VOID StateMachineSetAction(
5306 IN STATE_MACHINE *S,
5309 IN STATE_MACHINE_FUNC Func)
5313 MsgIdx = Msg - S->Base;
5315 if (St < S->NrState && MsgIdx < S->NrMsg)
5317 // boundary checking before setting the action
5318 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5322 /*! \brief This function does the state transition
5323 * \param *Adapter the NIC adapter pointer
5324 * \param *S the state machine
5325 * \param *Elem the message to be executed
5328 IRQL = DISPATCH_LEVEL
5331 VOID StateMachinePerformAction(
5332 IN PRTMP_ADAPTER pAd,
5333 IN STATE_MACHINE *S,
5334 IN MLME_QUEUE_ELEM *Elem)
5336 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5340 ==========================================================================
5342 The drop function, when machine executes this, the message is simply
5343 ignored. This function does nothing, the message is freed in
5344 StateMachinePerformAction()
5345 ==========================================================================
5348 IN PRTMP_ADAPTER pAd,
5349 IN MLME_QUEUE_ELEM *Elem)
5353 // ===========================================================================================
5355 // ===========================================================================================
5358 ==========================================================================
5361 IRQL = PASSIVE_LEVEL
5363 ==========================================================================
5366 IN PRTMP_ADAPTER pAd,
5370 pAd->Mlme.ShiftReg = 1;
5372 pAd->Mlme.ShiftReg = Seed;
5376 ==========================================================================
5378 ==========================================================================
5381 IN PRTMP_ADAPTER pAd)
5388 if (pAd->Mlme.ShiftReg == 0)
5389 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5391 for (i = 0; i < 8; i++)
5393 if (pAd->Mlme.ShiftReg & 0x00000001)
5395 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5400 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5403 R = (R << 1) | Result;
5409 VOID AsicUpdateAutoFallBackTable(
5410 IN PRTMP_ADAPTER pAd,
5411 IN PUCHAR pRateTable)
5414 HT_FBK_CFG0_STRUC HtCfg0;
5415 HT_FBK_CFG1_STRUC HtCfg1;
5416 LG_FBK_CFG0_STRUC LgCfg0;
5417 LG_FBK_CFG1_STRUC LgCfg1;
5418 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5420 // set to initial value
5421 HtCfg0.word = 0x65432100;
5422 HtCfg1.word = 0xedcba988;
5423 LgCfg0.word = 0xedcba988;
5424 LgCfg1.word = 0x00002100;
5426 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5427 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5429 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5430 switch (pCurrTxRate->Mode)
5436 switch(pCurrTxRate->CurrMCS)
5439 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5442 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5445 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5448 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5451 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5454 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5457 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5460 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5465 #ifdef DOT11_N_SUPPORT
5469 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5471 switch(pCurrTxRate->CurrMCS)
5474 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5477 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5480 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5483 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5486 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5489 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5492 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5495 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5498 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5501 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5504 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5507 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5510 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5513 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5516 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5519 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5522 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5527 #endif // DOT11_N_SUPPORT //
5530 pNextTxRate = pCurrTxRate;
5533 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5534 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5535 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5536 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5540 ========================================================================
5542 Routine Description:
5543 Set MAC register value according operation mode.
5544 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5545 If MM or GF mask is not set, those passing argument doesn't not take effect.
5547 Operation mode meaning:
5548 = 0 : Pure HT, no preotection.
5549 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5550 = 0x10: No Transmission in 40M is protected.
5551 = 0x11: Transmission in both 40M and 20M shall be protected
5553 we should choose not to use GF. But still set correct ASIC registers.
5554 ========================================================================
5556 VOID AsicUpdateProtect(
5557 IN PRTMP_ADAPTER pAd,
5558 IN USHORT OperationMode,
5560 IN BOOLEAN bDisableBGProtect,
5561 IN BOOLEAN bNonGFExist)
5563 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5569 #ifdef DOT11_N_SUPPORT
5570 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5575 if (pAd->BATable.numAsOriginator)
5578 // enable the RTS/CTS to avoid channel collision
5580 SetMask = ALLN_SETPROTECT;
5583 #endif // DOT11_N_SUPPORT //
5585 // Config ASIC RTS threshold register
5586 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5587 MacReg &= 0xFF0000FF;
5589 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5591 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5593 #ifdef DOT11_N_SUPPORT
5594 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5595 #endif // DOT11_N_SUPPORT //
5596 (pAd->CommonCfg.bAggregationCapable == TRUE))
5597 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5599 MacReg |= (0x1000 << 8);
5603 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5607 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5609 // Initial common protection settings
5610 RTMPZeroMemory(Protect, sizeof(Protect));
5613 ProtCfg.field.TxopAllowGF40 = 1;
5614 ProtCfg.field.TxopAllowGF20 = 1;
5615 ProtCfg.field.TxopAllowMM40 = 1;
5616 ProtCfg.field.TxopAllowMM20 = 1;
5617 ProtCfg.field.TxopAllowOfdm = 1;
5618 ProtCfg.field.TxopAllowCck = 1;
5619 ProtCfg.field.RTSThEn = 1;
5620 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5622 // update PHY mode and rate
5623 if (pAd->CommonCfg.Channel > 14)
5624 ProtCfg.field.ProtectRate = 0x4000;
5625 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5627 // Handle legacy(B/G) protection
5628 if (bDisableBGProtect)
5630 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5631 ProtCfg.field.ProtectCtrl = 0;
5632 Protect[0] = ProtCfg.word;
5633 Protect[1] = ProtCfg.word;
5637 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5638 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5639 Protect[0] = ProtCfg.word;
5640 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5641 Protect[1] = ProtCfg.word;
5644 #ifdef DOT11_N_SUPPORT
5645 // Decide HT frame protection.
5646 if ((SetMask & ALLN_SETPROTECT) != 0)
5648 switch(OperationMode)
5652 // 1.All STAs in the BSS are 20/40 MHz HT
5653 // 2. in ai 20/40MHz BSS
5654 // 3. all STAs are 20MHz in a 20MHz BSS
5655 // Pure HT. no protection.
5659 // PROT_TXOP(25:20) -- 010111
5660 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5661 // PROT_CTRL(17:16) -- 00 (None)
5662 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5663 Protect[2] = 0x01744004;
5667 // PROT_TXOP(25:20) -- 111111
5668 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5669 // PROT_CTRL(17:16) -- 00 (None)
5670 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5671 Protect[3] = 0x03f44084;
5675 // PROT_TXOP(25:20) -- 010111
5676 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5677 // PROT_CTRL(17:16) -- 00 (None)
5678 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5679 Protect[4] = 0x01744004;
5683 // PROT_TXOP(25:20) -- 111111
5684 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5685 // PROT_CTRL(17:16) -- 00 (None)
5686 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5687 Protect[5] = 0x03f44084;
5691 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5692 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5693 Protect[4] = 0x01754004;
5694 Protect[5] = 0x03f54084;
5696 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5700 // This is "HT non-member protection mode."
5701 // If there may be non-HT STAs my BSS
5702 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5703 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5704 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5706 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5707 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5709 //Assign Protection method for 20&40 MHz packets
5710 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5711 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5712 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5713 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5714 Protect[2] = ProtCfg.word;
5715 Protect[3] = ProtCfg4.word;
5716 Protect[4] = ProtCfg.word;
5717 Protect[5] = ProtCfg4.word;
5718 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5722 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5723 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5724 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5726 //Assign Protection method for 40MHz packets
5727 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5728 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5729 Protect[2] = ProtCfg.word;
5730 Protect[3] = ProtCfg4.word;
5733 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5734 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5736 Protect[4] = ProtCfg.word;
5737 Protect[5] = ProtCfg4.word;
5739 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5743 // HT mixed mode. PROTECT ALL!
5745 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5746 ProtCfg4.word = 0x03f44084;
5747 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5748 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5750 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5751 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5753 //Assign Protection method for 20&40 MHz packets
5754 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5755 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5756 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5757 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5758 Protect[2] = ProtCfg.word;
5759 Protect[3] = ProtCfg4.word;
5760 Protect[4] = ProtCfg.word;
5761 Protect[5] = ProtCfg4.word;
5762 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5766 // Special on for Atheros problem n chip.
5767 Protect[2] = 0x01754004;
5768 Protect[3] = 0x03f54084;
5769 Protect[4] = 0x01754004;
5770 Protect[5] = 0x03f54084;
5771 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5775 #endif // DOT11_N_SUPPORT //
5777 offset = CCK_PROT_CFG;
5778 for (i = 0;i < 6;i++)
5780 if ((SetMask & (1<< i)))
5782 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5788 ==========================================================================
5791 IRQL = PASSIVE_LEVEL
5792 IRQL = DISPATCH_LEVEL
5794 ==========================================================================
5796 VOID AsicSwitchChannel(
5797 IN PRTMP_ADAPTER pAd,
5801 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5802 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5804 UINT32 Value = 0; //BbpReg, Value;
5805 RTMP_RF_REGS *RFRegTable;
5807 // Search Tx power value
5808 for (index = 0; index < pAd->ChannelListNum; index++)
5810 if (Channel == pAd->ChannelList[index].Channel)
5812 TxPwer = pAd->ChannelList[index].Power;
5813 TxPwer2 = pAd->ChannelList[index].Power2;
5818 if (index == MAX_NUM_OF_CHANNELS)
5820 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5824 RFRegTable = RF2850RegTable;
5826 switch (pAd->RfIcType)
5833 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5835 if (Channel == RFRegTable[index].Channel)
5837 R2 = RFRegTable[index].R2;
5838 if (pAd->Antenna.field.TxPath == 1)
5840 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5843 if (pAd->Antenna.field.RxPath == 2)
5845 R2 |= 0x40; // write 1 to off Rxpath.
5847 else if (pAd->Antenna.field.RxPath == 1)
5849 R2 |= 0x20040; // write 1 to off RxPath
5854 // initialize R3, R4
5855 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5856 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5858 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5860 if ((TxPwer >= -7) && (TxPwer < 0))
5862 TxPwer = (7+TxPwer);
5863 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5864 R3 |= (TxPwer << 10);
5865 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5869 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5870 R3 |= (TxPwer << 10) | (1 << 9);
5874 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5876 TxPwer2 = (7+TxPwer2);
5877 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5878 R4 |= (TxPwer2 << 7);
5879 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5883 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5884 R4 |= (TxPwer2 << 7) | (1 << 6);
5889 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5890 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5893 // Based on BBP current mode before changing RF channel.
5894 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5900 pAd->LatchRfRegs.Channel = Channel;
5901 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5902 pAd->LatchRfRegs.R2 = R2;
5903 pAd->LatchRfRegs.R3 = R3;
5904 pAd->LatchRfRegs.R4 = R4;
5906 // Set RF value 1's set R3[bit2] = [0]
5907 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5908 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5909 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5910 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5914 // Set RF value 2's set R3[bit2] = [1]
5915 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5916 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5917 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5918 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5922 // Set RF value 3's set R3[bit2] = [0]
5923 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5924 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5925 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5926 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5938 // Change BBP setting during siwtch from a->g, g->a
5941 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5943 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5944 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5945 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5946 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.
5947 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5949 // Rx High power VGA offset for LNA select
5950 if (pAd->NicConfig2.field.ExternalLNAForG)
5952 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5953 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5957 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5958 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5961 // 5G band selection PIN, bit1 and bit2 are complement
5962 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5965 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5967 // Turn off unused PA or LNA when only 1T or 1R
5968 if (pAd->Antenna.field.TxPath == 1)
5970 TxPinCfg &= 0xFFFFFFF3;
5972 if (pAd->Antenna.field.RxPath == 1)
5974 TxPinCfg &= 0xFFFFF3FF;
5977 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5981 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5983 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5984 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5985 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5986 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.
5987 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5989 // Rx High power VGA offset for LNA select
5990 if (pAd->NicConfig2.field.ExternalLNAForA)
5992 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
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);
6018 // R66 should be set according to Channel and use 20MHz when scanning
6019 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6021 RTMPSetAGCInitValue(pAd, BW_20);
6023 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6026 // On 11A, We should delay and wait RF/BBP to be stable
6027 // and the appropriate time should be 1000 micro seconds
6028 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6030 RTMPusecDelay(1000);
6032 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",
6035 (R3 & 0x00003e00) >> 9,
6036 (R4 & 0x000007c0) >> 6,
6037 pAd->Antenna.field.TxPath,
6038 pAd->LatchRfRegs.R1,
6039 pAd->LatchRfRegs.R2,
6040 pAd->LatchRfRegs.R3,
6041 pAd->LatchRfRegs.R4));
6045 ==========================================================================
6047 This function is required for 2421 only, and should not be used during
6048 site survey. It's only required after NIC decided to stay at a channel
6049 for a longer period.
6050 When this function is called, it's always after AsicSwitchChannel().
6052 IRQL = PASSIVE_LEVEL
6053 IRQL = DISPATCH_LEVEL
6055 ==========================================================================
6057 VOID AsicLockChannel(
6058 IN PRTMP_ADAPTER pAd,
6064 ==========================================================================
6067 IRQL = PASSIVE_LEVEL
6068 IRQL = DISPATCH_LEVEL
6070 ==========================================================================
6072 VOID AsicAntennaSelect(
6073 IN PRTMP_ADAPTER pAd,
6079 ========================================================================
6081 Routine Description:
6082 Antenna miscellaneous setting.
6085 pAd Pointer to our adapter
6086 BandState Indicate current Band State.
6091 IRQL <= DISPATCH_LEVEL
6094 1.) Frame End type control
6095 only valid for G only (RF_2527 & RF_2529)
6096 0: means DPDT, set BBP R4 bit 5 to 1
6097 1: means SPDT, set BBP R4 bit 5 to 0
6100 ========================================================================
6102 VOID AsicAntennaSetting(
6103 IN PRTMP_ADAPTER pAd,
6104 IN ABGBAND_STATE BandState)
6108 VOID AsicRfTuningExec(
6109 IN PVOID SystemSpecific1,
6110 IN PVOID FunctionContext,
6111 IN PVOID SystemSpecific2,
6112 IN PVOID SystemSpecific3)
6117 ==========================================================================
6119 Gives CCK TX rate 2 more dB TX power.
6120 This routine works only in LINK UP in INFRASTRUCTURE mode.
6122 calculate desired Tx power in RF R3.Tx0~5, should consider -
6123 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6124 1. TxPowerPercentage
6125 2. auto calibration based on TSSI feedback
6126 3. extra 2 db for CCK
6127 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6129 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6130 it should be called AFTER MlmeDynamicTxRatSwitching()
6131 ==========================================================================
6133 VOID AsicAdjustTxPower(
6134 IN PRTMP_ADAPTER pAd)
6138 BOOLEAN bAutoTxAgc = FALSE;
6139 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6140 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6141 PCHAR pTxAgcCompensate;
6145 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6146 || (pAd->bPCIclkOff == TRUE)
6147 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6148 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6151 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6153 if (pAd->CommonCfg.CentralChannel > 14)
6155 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6156 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6157 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6158 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6159 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6163 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6164 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6165 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6166 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6167 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6172 if (pAd->CommonCfg.Channel > 14)
6174 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6175 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6176 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6177 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6178 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6182 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6183 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6184 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6185 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6186 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6190 // TX power compensation for temperature variation based on TSSI. try every 4 second
6191 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6193 if (pAd->CommonCfg.Channel <= 14)
6196 bAutoTxAgc = pAd->bAutoTxAgcG;
6197 TssiRef = pAd->TssiRefG;
6198 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6199 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6200 TxAgcStep = pAd->TxAgcStepG;
6201 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6206 bAutoTxAgc = pAd->bAutoTxAgcA;
6207 TssiRef = pAd->TssiRefA;
6208 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6209 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6210 TxAgcStep = pAd->TxAgcStepA;
6211 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6216 /* BbpR1 is unsigned char */
6217 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6219 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6220 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6221 /* step value is defined in pAd->TxAgcStepG for tx power value */
6223 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6224 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6225 above value are examined in mass factory production */
6226 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6228 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6229 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6230 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6232 if (BbpR49 > pTssiMinusBoundary[1])
6234 // Reading is larger than the reference value
6235 // check for how large we need to decrease the Tx power
6236 for (idx = 1; idx < 5; idx++)
6238 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6241 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6242 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6244 DeltaPwr += (*pTxAgcCompensate);
6245 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6246 BbpR49, TssiRef, TxAgcStep, idx-1));
6248 else if (BbpR49 < pTssiPlusBoundary[1])
6250 // Reading is smaller than the reference value
6251 // check for how large we need to increase the Tx power
6252 for (idx = 1; idx < 5; idx++)
6254 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6257 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6258 *pTxAgcCompensate = TxAgcStep * (idx-1);
6259 DeltaPwr += (*pTxAgcCompensate);
6260 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6261 BbpR49, TssiRef, TxAgcStep, idx-1));
6265 *pTxAgcCompensate = 0;
6266 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6267 BbpR49, TssiRef, TxAgcStep, 0));
6273 if (pAd->CommonCfg.Channel <= 14)
6275 bAutoTxAgc = pAd->bAutoTxAgcG;
6276 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6280 bAutoTxAgc = pAd->bAutoTxAgcA;
6281 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6285 DeltaPwr += (*pTxAgcCompensate);
6288 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6292 // Handle regulatory max tx power constrain
6295 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6296 UCHAR AdjustMaxTxPwr[40];
6298 if (pAd->CommonCfg.Channel > 14) // 5G band
6299 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6301 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6302 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6304 // error handling, range check
6305 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6307 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6311 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6313 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6315 // Adjust max tx power according to the relationship of tx power in E2PROM
6318 // CCK will have 4dBm larger than OFDM
6319 // Therefore, we should separate to parse the tx power field
6324 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6328 // CCK will have 4dBm larger than OFDM
6329 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6333 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6335 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6342 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6344 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6345 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6350 // Adjust tx power according to the relationship
6353 if (TxPwr[i] != 0xffffffff)
6357 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6359 // The system tx power is larger than the regulatory, the power should be restrain
6360 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6362 // decrease to zero and don't need to take care BBPR1
6363 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6364 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6368 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6371 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6373 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6378 #endif // SINGLE_SKU //
6380 /* calculate delta power based on the percentage specified from UI */
6381 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6382 // We lower TX power here according to the percentage specified from UI
6383 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6385 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6387 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6391 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6395 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6399 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6404 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6409 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6411 /* reset different new tx power for different TX rate */
6414 if (TxPwr[i] != 0xffffffff)
6418 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6420 if ((Value + DeltaPwr) < 0)
6422 Value = 0; /* min */
6424 else if ((Value + DeltaPwr) > 0xF)
6426 Value = 0xF; /* max */
6430 Value += DeltaPwr; /* temperature compensation */
6433 /* fill new value to CSR offset */
6434 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6437 /* write tx power value to CSR */
6438 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6439 TX power for OFDM 6M/9M
6440 TX power for CCK5.5M/11M
6441 TX power for CCK1M/2M */
6442 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6443 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6449 #ifdef CONFIG_STA_SUPPORT
6451 ==========================================================================
6453 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6454 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6455 the wakeup timer timeout. Driver has to issue a separate command to wake
6458 IRQL = DISPATCH_LEVEL
6460 ==========================================================================
6462 VOID AsicSleepThenAutoWakeup(
6463 IN PRTMP_ADAPTER pAd,
6464 IN USHORT TbttNumToNextWakeUp)
6466 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6470 ==========================================================================
6472 AsicForceWakeup() is used whenever manual wakeup is required
6473 AsicForceSleep() should only be used when not in INFRA BSS. When
6474 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6475 ==========================================================================
6477 VOID AsicForceSleep(
6478 IN PRTMP_ADAPTER pAd)
6484 ==========================================================================
6486 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6489 IRQL = PASSIVE_LEVEL
6490 IRQL = DISPATCH_LEVEL
6491 ==========================================================================
6493 VOID AsicForceWakeup(
6494 IN PRTMP_ADAPTER pAd,
6497 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6498 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6500 #endif // CONFIG_STA_SUPPORT //
6502 ==========================================================================
6506 IRQL = DISPATCH_LEVEL
6508 ==========================================================================
6511 IN PRTMP_ADAPTER pAd,
6515 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6516 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6518 Addr4 = (ULONG)(pBssid[0]) |
6519 (ULONG)(pBssid[1] << 8) |
6520 (ULONG)(pBssid[2] << 16) |
6521 (ULONG)(pBssid[3] << 24);
6522 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6525 // always one BSSID in STA mode
6526 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6528 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6531 VOID AsicSetMcastWC(
6532 IN PRTMP_ADAPTER pAd)
6534 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6537 pEntry->Sst = SST_ASSOC;
6538 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6539 pEntry->PsMode = PWR_ACTIVE;
6540 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6541 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6545 ==========================================================================
6548 IRQL = DISPATCH_LEVEL
6550 ==========================================================================
6552 VOID AsicDelWcidTab(
6553 IN PRTMP_ADAPTER pAd,
6556 ULONG Addr0 = 0x0, Addr1 = 0x0;
6559 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6560 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6561 RTMP_IO_WRITE32(pAd, offset, Addr0);
6563 RTMP_IO_WRITE32(pAd, offset, Addr1);
6567 ==========================================================================
6570 IRQL = DISPATCH_LEVEL
6572 ==========================================================================
6575 IN PRTMP_ADAPTER pAd)
6577 TX_LINK_CFG_STRUC TxLinkCfg;
6580 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6581 TxLinkCfg.field.TxRDGEn = 1;
6582 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6584 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6587 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6589 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6593 ==========================================================================
6596 IRQL = DISPATCH_LEVEL
6598 ==========================================================================
6600 VOID AsicDisableRDG(
6601 IN PRTMP_ADAPTER pAd)
6603 TX_LINK_CFG_STRUC TxLinkCfg;
6607 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6608 TxLinkCfg.field.TxRDGEn = 0;
6609 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6611 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6614 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6615 #ifdef DOT11_N_SUPPORT
6616 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6617 #endif // DOT11_N_SUPPORT //
6620 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6621 if (pAd->CommonCfg.bEnableTxBurst)
6624 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6628 ==========================================================================
6631 IRQL = PASSIVE_LEVEL
6632 IRQL = DISPATCH_LEVEL
6634 ==========================================================================
6636 VOID AsicDisableSync(
6637 IN PRTMP_ADAPTER pAd)
6639 BCN_TIME_CFG_STRUC csr;
6641 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6643 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6644 // that NIC will never wakes up because TSF stops and no more
6646 pAd->TbttTickCount = 0;
6647 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6648 csr.field.bBeaconGen = 0;
6649 csr.field.bTBTTEnable = 0;
6650 csr.field.TsfSyncMode = 0;
6651 csr.field.bTsfTicking = 0;
6652 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6657 ==========================================================================
6660 IRQL = DISPATCH_LEVEL
6662 ==========================================================================
6664 VOID AsicEnableBssSync(
6665 IN PRTMP_ADAPTER pAd)
6667 BCN_TIME_CFG_STRUC csr;
6669 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6671 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6672 #ifdef CONFIG_STA_SUPPORT
6673 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6675 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6676 csr.field.bTsfTicking = 1;
6677 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6678 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6679 csr.field.bTBTTEnable = 1;
6681 #endif // CONFIG_STA_SUPPORT //
6682 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6686 ==========================================================================
6689 BEACON frame in shared memory should be built ok before this routine
6690 can be called. Otherwise, a garbage frame maybe transmitted out every
6693 IRQL = DISPATCH_LEVEL
6695 ==========================================================================
6697 VOID AsicEnableIbssSync(
6698 IN PRTMP_ADAPTER pAd)
6700 BCN_TIME_CFG_STRUC csr9;
6704 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6706 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6707 csr9.field.bBeaconGen = 0;
6708 csr9.field.bTBTTEnable = 0;
6709 csr9.field.bTsfTicking = 0;
6710 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6712 // move BEACON TXD and frame content to on-chip memory
6713 ptr = (PUCHAR)&pAd->BeaconTxWI;
6714 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6716 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6717 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6721 // start right after the 16-byte TXWI field
6722 ptr = pAd->BeaconBuf;
6723 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6725 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6726 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6730 // start sending BEACON
6731 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6732 csr9.field.bTsfTicking = 1;
6733 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6734 csr9.field.bTBTTEnable = 1;
6735 csr9.field.bBeaconGen = 1;
6736 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6740 ==========================================================================
6743 IRQL = PASSIVE_LEVEL
6744 IRQL = DISPATCH_LEVEL
6746 ==========================================================================
6748 VOID AsicSetEdcaParm(
6749 IN PRTMP_ADAPTER pAd,
6750 IN PEDCA_PARM pEdcaParm)
6752 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6753 AC_TXOP_CSR0_STRUC csr0;
6754 AC_TXOP_CSR1_STRUC csr1;
6755 AIFSN_CSR_STRUC AifsnCsr;
6756 CWMIN_CSR_STRUC CwminCsr;
6757 CWMAX_CSR_STRUC CwmaxCsr;
6764 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6766 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6767 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6768 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6770 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6771 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6774 //========================================================
6775 // MAC Register has a copy .
6776 //========================================================
6777 if( pAd->CommonCfg.bEnableTxBurst )
6779 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6780 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6783 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6784 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6785 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6786 Ac0Cfg.field.Aifsn = 2;
6787 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6789 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6790 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6791 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6792 Ac1Cfg.field.Aifsn = 2;
6793 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6795 if (pAd->CommonCfg.PhyMode == PHY_11B)
6797 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6798 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6802 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6803 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6805 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6806 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6807 Ac2Cfg.field.Aifsn = 2;
6808 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6809 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6810 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6811 Ac3Cfg.field.Aifsn = 2;
6812 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6814 //========================================================
6815 // DMA Register has a copy too.
6816 //========================================================
6817 csr0.field.Ac0Txop = 0; // QID_AC_BE
6818 csr0.field.Ac1Txop = 0; // QID_AC_BK
6819 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6820 if (pAd->CommonCfg.PhyMode == PHY_11B)
6822 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6823 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6827 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6828 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6830 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6833 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6834 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6835 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6836 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6837 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6840 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6841 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6842 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6843 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6844 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6846 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6848 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6852 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6853 //========================================================
6854 // MAC Register has a copy.
6855 //========================================================
6857 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6858 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6860 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6862 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6863 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6864 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6865 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6867 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6868 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6869 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6870 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6872 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6873 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6874 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6875 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6876 #ifdef CONFIG_STA_SUPPORT
6877 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6879 // Tuning for Wi-Fi WMM S06
6880 if (pAd->CommonCfg.bWiFiTest &&
6881 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6882 Ac2Cfg.field.Aifsn -= 1;
6884 // Tuning for TGn Wi-Fi 5.2.32
6885 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6886 if (STA_TGN_WIFI_ON(pAd) &&
6887 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6889 Ac0Cfg.field.Aifsn = 3;
6890 Ac2Cfg.field.AcTxop = 5;
6893 #endif // CONFIG_STA_SUPPORT //
6895 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6896 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6897 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6898 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6901 if (pAd->CommonCfg.bWiFiTest)
6903 if (Ac3Cfg.field.AcTxop == 102)
6905 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6906 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6907 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6908 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6909 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6912 //#endif // WIFI_TEST //
6914 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6915 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6916 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6917 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6920 //========================================================
6921 // DMA Register has a copy too.
6922 //========================================================
6923 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6924 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6925 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6927 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6928 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6929 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6932 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6933 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6934 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6935 #ifdef CONFIG_STA_SUPPORT
6936 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6937 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6938 #endif // CONFIG_STA_SUPPORT //
6939 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6942 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6943 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6944 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6945 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6946 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6949 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6950 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6951 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6952 #ifdef CONFIG_STA_SUPPORT
6953 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6955 // Tuning for Wi-Fi WMM S06
6956 if (pAd->CommonCfg.bWiFiTest &&
6957 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6958 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6960 // Tuning for TGn Wi-Fi 5.2.32
6961 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6962 if (STA_TGN_WIFI_ON(pAd) &&
6963 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6965 AifsnCsr.field.Aifsn0 = 3;
6966 AifsnCsr.field.Aifsn2 = 7;
6969 #endif // CONFIG_STA_SUPPORT //
6971 #ifdef CONFIG_STA_SUPPORT
6972 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6973 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6974 #endif // CONFIG_STA_SUPPORT //
6975 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6977 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6980 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6981 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6982 pEdcaParm->Aifsn[0],
6983 pEdcaParm->Cwmin[0],
6984 pEdcaParm->Cwmax[0],
6985 pEdcaParm->Txop[0]<<5,
6986 pEdcaParm->bACM[0]));
6987 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6988 pEdcaParm->Aifsn[1],
6989 pEdcaParm->Cwmin[1],
6990 pEdcaParm->Cwmax[1],
6991 pEdcaParm->Txop[1]<<5,
6992 pEdcaParm->bACM[1]));
6993 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6994 pEdcaParm->Aifsn[2],
6995 pEdcaParm->Cwmin[2],
6996 pEdcaParm->Cwmax[2],
6997 pEdcaParm->Txop[2]<<5,
6998 pEdcaParm->bACM[2]));
6999 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7000 pEdcaParm->Aifsn[3],
7001 pEdcaParm->Cwmin[3],
7002 pEdcaParm->Cwmax[3],
7003 pEdcaParm->Txop[3]<<5,
7004 pEdcaParm->bACM[3]));
7010 ==========================================================================
7013 IRQL = PASSIVE_LEVEL
7014 IRQL = DISPATCH_LEVEL
7016 ==========================================================================
7018 VOID AsicSetSlotTime(
7019 IN PRTMP_ADAPTER pAd,
7020 IN BOOLEAN bUseShortSlotTime)
7023 UINT32 RegValue = 0;
7025 #ifdef CONFIG_STA_SUPPORT
7026 if (pAd->CommonCfg.Channel > 14)
7027 bUseShortSlotTime = TRUE;
7028 #endif // CONFIG_STA_SUPPORT //
7030 if (bUseShortSlotTime)
7031 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7033 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7035 SlotTime = (bUseShortSlotTime)? 9 : 20;
7037 #ifdef CONFIG_STA_SUPPORT
7038 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7040 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7041 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7042 #ifdef DOT11_N_SUPPORT
7043 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7044 #endif // DOT11_N_SUPPORT //
7047 // In this case, we will think it is doing Wi-Fi test
7048 // And we will not set to short slot when bEnableTxBurst is TRUE.
7050 else if (pAd->CommonCfg.bEnableTxBurst)
7053 #endif // CONFIG_STA_SUPPORT //
7056 // For some reasons, always set it to short slot time.
7058 // ToDo: Should consider capability with 11B
7060 #ifdef CONFIG_STA_SUPPORT
7061 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7063 if (pAd->StaCfg.BssType == BSS_ADHOC)
7066 #endif // CONFIG_STA_SUPPORT //
7068 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7069 RegValue = RegValue & 0xFFFFFF00;
7071 RegValue |= SlotTime;
7073 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7077 ========================================================================
7079 Add Shared key information into ASIC.
7080 Update shared key, TxMic and RxMic to Asic Shared key table
7081 Update its cipherAlg to Asic Shared key Mode.
7084 ========================================================================
7086 VOID AsicAddSharedKeyEntry(
7087 IN PRTMP_ADAPTER pAd,
7095 ULONG offset; //, csr0;
7096 SHAREDKEY_MODE_STRUC csr1;
7099 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7100 //============================================================================================
7102 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7103 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7104 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]));
7107 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7108 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7112 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7113 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7115 //============================================================================================
7117 // fill key material - key + TX MIC + RX MIC
7119 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7120 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7122 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7125 offset += MAX_LEN_OF_SHARE_KEY;
7130 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7139 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7145 // Update cipher algorithm. WSTA always use BSS0
7147 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7148 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7149 if ((BssIndex%2) == 0)
7152 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7153 else if (KeyIdx == 1)
7154 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7155 else if (KeyIdx == 2)
7156 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7158 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7163 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7164 else if (KeyIdx == 1)
7165 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7166 else if (KeyIdx == 2)
7167 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7169 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7171 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7172 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7176 // IRQL = DISPATCH_LEVEL
7177 VOID AsicRemoveSharedKeyEntry(
7178 IN PRTMP_ADAPTER pAd,
7183 SHAREDKEY_MODE_STRUC csr1;
7185 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7187 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7188 if ((BssIndex%2) == 0)
7191 csr1.field.Bss0Key0CipherAlg = 0;
7192 else if (KeyIdx == 1)
7193 csr1.field.Bss0Key1CipherAlg = 0;
7194 else if (KeyIdx == 2)
7195 csr1.field.Bss0Key2CipherAlg = 0;
7197 csr1.field.Bss0Key3CipherAlg = 0;
7202 csr1.field.Bss1Key0CipherAlg = 0;
7203 else if (KeyIdx == 1)
7204 csr1.field.Bss1Key1CipherAlg = 0;
7205 else if (KeyIdx == 2)
7206 csr1.field.Bss1Key2CipherAlg = 0;
7208 csr1.field.Bss1Key3CipherAlg = 0;
7210 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7211 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7212 ASSERT(BssIndex < 4);
7218 VOID AsicUpdateWCIDAttribute(
7219 IN PRTMP_ADAPTER pAd,
7223 IN BOOLEAN bUsePairewiseKeyTable)
7225 ULONG WCIDAttri = 0, offset;
7228 // Update WCID attribute.
7229 // Only TxKey could update WCID attribute.
7231 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7232 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7233 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7236 VOID AsicUpdateWCIDIVEIV(
7237 IN PRTMP_ADAPTER pAd,
7244 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7246 RTMP_IO_WRITE32(pAd, offset, uIV);
7247 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7250 VOID AsicUpdateRxWCIDTable(
7251 IN PRTMP_ADAPTER pAd,
7258 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7259 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7260 RTMP_IO_WRITE32(pAd, offset, Addr);
7261 Addr = pAddr[4] + (pAddr[5] << 8);
7262 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7267 ========================================================================
7269 Routine Description:
7270 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7273 pAd Pointer to our adapter
7274 WCID WCID Entry number.
7275 BssIndex BSSID index, station or none multiple BSSID support
7276 this value should be 0.
7277 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7278 pCipherKey Pointer to Cipher Key.
7279 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7280 otherwise PairewiseKey table
7281 bTxKey This is the transmit key if enabled.
7287 This routine will set the relative key stuff to Asic including WCID attribute,
7288 Cipher Key, Cipher algorithm and IV/EIV.
7290 IV/EIV will be update if this CipherKey is the transmission key because
7291 ASIC will base on IV's KeyID value to select Cipher Key.
7293 If bTxKey sets to FALSE, this is not the TX key, but it could be
7296 For AP mode bTxKey must be always set to TRUE.
7297 ========================================================================
7299 VOID AsicAddKeyEntry(
7300 IN PRTMP_ADAPTER pAd,
7304 IN PCIPHER_KEY pCipherKey,
7305 IN BOOLEAN bUsePairewiseKeyTable,
7310 PUCHAR pKey = pCipherKey->Key;
7311 PUCHAR pTxMic = pCipherKey->TxMic;
7312 PUCHAR pRxMic = pCipherKey->RxMic;
7313 PUCHAR pTxtsc = pCipherKey->TxTsc;
7314 UCHAR CipherAlg = pCipherKey->CipherAlg;
7315 SHAREDKEY_MODE_STRUC csr1;
7318 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7320 // 1.) decide key table offset
7322 if (bUsePairewiseKeyTable)
7323 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7325 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7328 // 2.) Set Key to Asic
7330 //for (i = 0; i < KeyLen; i++)
7331 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7333 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7335 offset += MAX_LEN_OF_PEER_KEY;
7338 // 3.) Set MIC key if available
7342 for (i = 0; i < 8; i++)
7344 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7347 offset += LEN_TKIP_TXMICK;
7351 for (i = 0; i < 8; i++)
7353 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7359 // 4.) Modify IV/EIV if needs
7360 // This will force Asic to use this key ID by setting IV.
7364 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7368 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7369 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7370 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7372 IV4 = (KeyIdx << 6);
7373 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7374 IV4 |= 0x20; // turn on extension bit means EIV existence
7376 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7382 for (i = 0; i < 4; i++)
7384 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7387 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7390 if (!bUsePairewiseKeyTable)
7393 // Only update the shared key security mode
7395 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7396 if ((BssIndex % 2) == 0)
7399 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7400 else if (KeyIdx == 1)
7401 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7402 else if (KeyIdx == 2)
7403 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7405 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7410 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7411 else if (KeyIdx == 1)
7412 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7413 else if (KeyIdx == 2)
7414 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7416 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7418 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7421 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7426 ========================================================================
7428 Add Pair-wise key material into ASIC.
7429 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7432 ========================================================================
7434 VOID AsicAddPairwiseKeyEntry(
7435 IN PRTMP_ADAPTER pAd,
7438 IN CIPHER_KEY *pCipherKey)
7442 PUCHAR pKey = pCipherKey->Key;
7443 PUCHAR pTxMic = pCipherKey->TxMic;
7444 PUCHAR pRxMic = pCipherKey->RxMic;
7446 UCHAR CipherAlg = pCipherKey->CipherAlg;
7450 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7451 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7453 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7455 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7458 RTMP_IO_READ32(pAd, offset + i, &Value);
7461 offset += MAX_LEN_OF_PEER_KEY;
7468 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7476 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7480 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7481 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7482 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]));
7485 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7486 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7490 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7491 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7495 ========================================================================
7497 Remove Pair-wise key material from ASIC.
7500 ========================================================================
7502 VOID AsicRemovePairwiseKeyEntry(
7503 IN PRTMP_ADAPTER pAd,
7510 // re-set the entry's WCID attribute as OPEN-NONE.
7511 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7512 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7513 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7516 BOOLEAN AsicSendCommandToMcu(
7517 IN PRTMP_ADAPTER pAd,
7523 HOST_CMD_CSR_STRUC H2MCmd;
7524 H2M_MAILBOX_STRUC H2MMailbox;
7529 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7530 if (H2MMailbox.field.Owner == 0)
7542 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7544 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7546 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7547 // Reset DMA/CPU ring index
7548 RTMPRingCleanUp(pAd, QID_AC_BK);
7549 RTMPRingCleanUp(pAd, QID_AC_BE);
7550 RTMPRingCleanUp(pAd, QID_AC_VI);
7551 RTMPRingCleanUp(pAd, QID_AC_VO);
7552 RTMPRingCleanUp(pAd, QID_HCCA);
7553 RTMPRingCleanUp(pAd, QID_MGMT);
7554 RTMPRingCleanUp(pAd, QID_RX);
7557 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7559 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7560 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7565 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7566 H2MMailbox.field.CmdToken = Token;
7567 H2MMailbox.field.HighByte = Arg1;
7568 H2MMailbox.field.LowByte = Arg0;
7569 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7572 H2MCmd.field.HostCommand = Command;
7573 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7575 if (Command != 0x80)
7582 BOOLEAN AsicCheckCommanOk(
7583 IN PRTMP_ADAPTER pAd,
7586 UINT32 CmdStatus = 0, CID = 0, i;
7587 UINT32 ThisCIDMask = 0;
7592 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7593 // Find where the command is. Because this is randomly specified by firmware.
7594 if ((CID & CID0MASK) == Command)
7596 ThisCIDMask = CID0MASK;
7599 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7601 ThisCIDMask = CID1MASK;
7604 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7606 ThisCIDMask = CID2MASK;
7609 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7611 ThisCIDMask = CID3MASK;
7619 // Get CommandStatus Value
7620 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7622 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7625 // If Status is 1, the comamnd is success.
7626 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7627 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7629 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7630 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7631 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7634 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7638 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7640 // Clear Command and Status.
7641 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7642 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7648 ========================================================================
7650 Routine Description:
7651 Verify the support rate for different PHY type
7654 pAd Pointer to our adapter
7659 IRQL = PASSIVE_LEVEL
7661 ========================================================================
7663 VOID RTMPCheckRates(
7664 IN PRTMP_ADAPTER pAd,
7665 IN OUT UCHAR SupRate[],
7666 IN OUT UCHAR *SupRateLen)
7668 UCHAR RateIdx, i, j;
7669 UCHAR NewRate[12], NewRateLen;
7673 if (pAd->CommonCfg.PhyMode == PHY_11B)
7678 // Check for support rates exclude basic rate bit
7679 for (i = 0; i < *SupRateLen; i++)
7680 for (j = 0; j < RateIdx; j++)
7681 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7682 NewRate[NewRateLen++] = SupRate[i];
7684 *SupRateLen = NewRateLen;
7685 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7688 #ifdef CONFIG_STA_SUPPORT
7689 #ifdef DOT11_N_SUPPORT
7690 BOOLEAN RTMPCheckChannel(
7691 IN PRTMP_ADAPTER pAd,
7692 IN UCHAR CentralChannel,
7696 UCHAR UpperChannel = 0, LowerChannel = 0;
7697 UCHAR NoEffectChannelinList = 0;
7699 // Find upper and lower channel according to 40MHz current operation.
7700 if (CentralChannel < Channel)
7702 UpperChannel = Channel;
7703 if (CentralChannel > 2)
7704 LowerChannel = CentralChannel - 2;
7708 else if (CentralChannel > Channel)
7710 UpperChannel = CentralChannel + 2;
7711 LowerChannel = Channel;
7714 for (k = 0;k < pAd->ChannelListNum;k++)
7716 if (pAd->ChannelList[k].Channel == UpperChannel)
7718 NoEffectChannelinList ++;
7720 if (pAd->ChannelList[k].Channel == LowerChannel)
7722 NoEffectChannelinList ++;
7726 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7727 if (NoEffectChannelinList == 2)
7734 ========================================================================
7736 Routine Description:
7737 Verify the support rate for HT phy type
7740 pAd Pointer to our adapter
7743 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7745 IRQL = PASSIVE_LEVEL
7747 ========================================================================
7749 BOOLEAN RTMPCheckHt(
7750 IN PRTMP_ADAPTER pAd,
7752 IN HT_CAPABILITY_IE *pHtCapability,
7753 IN ADD_HT_INFO_IE *pAddHtInfo)
7755 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7758 // If use AMSDU, set flag.
7759 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7760 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7761 // Save Peer Capability
7762 if (pHtCapability->HtCapInfo.ShortGIfor20)
7763 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7764 if (pHtCapability->HtCapInfo.ShortGIfor40)
7765 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7766 if (pHtCapability->HtCapInfo.TxSTBC)
7767 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7768 if (pHtCapability->HtCapInfo.RxSTBC)
7769 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7770 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7772 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7775 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7777 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7780 // Will check ChannelWidth for MCSSet[4] below
7781 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7782 switch (pAd->CommonCfg.RxStream)
7785 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7786 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7787 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7788 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7791 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7792 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7793 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7794 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7797 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7798 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7799 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7800 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7804 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7806 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7807 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7808 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7810 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7812 // Send Assoc Req with my HT capability.
7813 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7814 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7815 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7816 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7817 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7818 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7819 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7820 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7821 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7822 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7823 if (pAd->CommonCfg.bRdg)
7825 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7826 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7829 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7830 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7832 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7835 #endif // DOT11_N_SUPPORT //
7836 #endif // CONFIG_STA_SUPPORT //
7839 ========================================================================
7841 Routine Description:
7842 Verify the support rate for different PHY type
7845 pAd Pointer to our adapter
7850 IRQL = PASSIVE_LEVEL
7852 ========================================================================
7854 VOID RTMPUpdateMlmeRate(
7855 IN PRTMP_ADAPTER pAd)
7858 UCHAR ProperMlmeRate; //= RATE_54;
7859 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7860 BOOLEAN bMatch = FALSE;
7862 switch (pAd->CommonCfg.PhyMode)
7865 ProperMlmeRate = RATE_11;
7866 MinimumRate = RATE_1;
7868 case PHY_11BG_MIXED:
7869 #ifdef DOT11_N_SUPPORT
7870 case PHY_11ABGN_MIXED:
7871 case PHY_11BGN_MIXED:
7872 #endif // DOT11_N_SUPPORT //
7873 if ((pAd->MlmeAux.SupRateLen == 4) &&
7874 (pAd->MlmeAux.ExtRateLen == 0))
7876 ProperMlmeRate = RATE_11;
7878 ProperMlmeRate = RATE_24;
7880 if (pAd->MlmeAux.Channel <= 14)
7881 MinimumRate = RATE_1;
7883 MinimumRate = RATE_6;
7886 #ifdef DOT11_N_SUPPORT
7887 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7888 case PHY_11GN_MIXED:
7889 case PHY_11AGN_MIXED:
7890 case PHY_11AN_MIXED:
7892 #endif // DOT11_N_SUPPORT //
7893 ProperMlmeRate = RATE_24;
7894 MinimumRate = RATE_6;
7896 case PHY_11ABG_MIXED:
7897 ProperMlmeRate = RATE_24;
7898 if (pAd->MlmeAux.Channel <= 14)
7899 MinimumRate = RATE_1;
7901 MinimumRate = RATE_6;
7904 ProperMlmeRate = RATE_1;
7905 MinimumRate = RATE_1;
7909 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7911 for (j = 0; j < RateIdx; j++)
7913 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7915 if (j == ProperMlmeRate)
7927 if (bMatch == FALSE)
7929 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7931 for (j = 0; j < RateIdx; j++)
7933 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7935 if (j == ProperMlmeRate)
7948 if (bMatch == FALSE)
7950 ProperMlmeRate = MinimumRate;
7953 pAd->CommonCfg.MlmeRate = MinimumRate;
7954 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7955 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7957 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7958 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7959 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7960 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7964 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7965 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7966 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7967 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7970 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7974 IN PRTMP_ADAPTER pAd,
7981 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7986 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7988 larger = max(Rssi0, Rssi1);
7991 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7993 larger = max(larger, Rssi2);
8003 ========================================================================
8004 Routine Description:
8005 Periodic evaluate antenna link status
8008 pAd - Adapter pointer
8013 ========================================================================
8015 VOID AsicEvaluateRxAnt(
8016 IN PRTMP_ADAPTER pAd)
8020 #ifdef CONFIG_STA_SUPPORT
8021 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8023 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8024 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8025 fRTMP_ADAPTER_RADIO_OFF |
8026 fRTMP_ADAPTER_NIC_NOT_EXIST |
8027 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
8030 if (pAd->StaCfg.Psm == PWR_SAVE)
8033 #endif // CONFIG_STA_SUPPORT //
8035 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8037 if(pAd->Antenna.field.RxPath == 3)
8041 else if(pAd->Antenna.field.RxPath == 2)
8045 else if(pAd->Antenna.field.RxPath == 1)
8049 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8050 #ifdef CONFIG_STA_SUPPORT
8051 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8052 pAd->StaCfg.BBPR3 = BBPR3;
8053 #endif // CONFIG_STA_SUPPORT //
8054 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8057 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8058 pAd->RalinkCounters.OneSecTxRetryOkCount +
8059 pAd->RalinkCounters.OneSecTxFailCount;
8061 if (TxTotalCnt > 50)
8063 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8064 pAd->Mlme.bLowThroughput = FALSE;
8068 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8069 pAd->Mlme.bLowThroughput = TRUE;
8075 ========================================================================
8076 Routine Description:
8077 After evaluation, check antenna link status
8080 pAd - Adapter pointer
8085 ========================================================================
8087 VOID AsicRxAntEvalTimeout(
8088 IN PVOID SystemSpecific1,
8089 IN PVOID FunctionContext,
8090 IN PVOID SystemSpecific2,
8091 IN PVOID SystemSpecific3)
8093 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8094 #ifdef CONFIG_STA_SUPPORT
8096 CHAR larger = -127, rssi0, rssi1, rssi2;
8097 #endif // CONFIG_STA_SUPPORT //
8099 #ifdef CONFIG_STA_SUPPORT
8100 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8102 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8103 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8104 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8105 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8108 if (pAd->StaCfg.Psm == PWR_SAVE)
8112 // if the traffic is low, use average rssi as the criteria
8113 if (pAd->Mlme.bLowThroughput == TRUE)
8115 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8116 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8117 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8121 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8122 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8123 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8126 if(pAd->Antenna.field.RxPath == 3)
8128 larger = max(rssi0, rssi1);
8130 if (larger > (rssi2 + 20))
8131 pAd->Mlme.RealRxPath = 2;
8133 pAd->Mlme.RealRxPath = 3;
8135 else if(pAd->Antenna.field.RxPath == 2)
8137 if (rssi0 > (rssi1 + 20))
8138 pAd->Mlme.RealRxPath = 1;
8140 pAd->Mlme.RealRxPath = 2;
8143 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8145 if(pAd->Mlme.RealRxPath == 3)
8149 else if(pAd->Mlme.RealRxPath == 2)
8153 else if(pAd->Mlme.RealRxPath == 1)
8157 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8158 pAd->StaCfg.BBPR3 = BBPR3;
8161 #endif // CONFIG_STA_SUPPORT //
8167 VOID APSDPeriodicExec(
8168 IN PVOID SystemSpecific1,
8169 IN PVOID FunctionContext,
8170 IN PVOID SystemSpecific2,
8171 IN PVOID SystemSpecific3)
8173 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8175 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8178 pAd->CommonCfg.TriggerTimerCount++;
8183 ========================================================================
8184 Routine Description:
8185 Set/reset MAC registers according to bPiggyBack parameter
8188 pAd - Adapter pointer
8189 bPiggyBack - Enable / Disable Piggy-Back
8194 ========================================================================
8196 VOID RTMPSetPiggyBack(
8197 IN PRTMP_ADAPTER pAd,
8198 IN BOOLEAN bPiggyBack)
8200 TX_LINK_CFG_STRUC TxLinkCfg;
8202 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8204 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8205 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8209 ========================================================================
8210 Routine Description:
8211 check if this entry need to switch rate automatically
8221 ========================================================================
8223 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8224 IN PRTMP_ADAPTER pAd,
8225 IN PMAC_TABLE_ENTRY pEntry)
8227 BOOLEAN result = TRUE;
8230 #ifdef CONFIG_STA_SUPPORT
8231 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8233 // only associated STA counts
8234 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8236 result = pAd->StaCfg.bAutoTxRateSwitch;
8241 #ifdef QOS_DLS_SUPPORT
8242 if (pEntry && (pEntry->ValidAsDls))
8243 result = pAd->StaCfg.bAutoTxRateSwitch;
8244 #endif // QOS_DLS_SUPPORT //
8246 #endif // CONFIG_STA_SUPPORT //
8254 BOOLEAN RTMPAutoRateSwitchCheck(
8255 IN PRTMP_ADAPTER pAd)
8258 #ifdef CONFIG_STA_SUPPORT
8259 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8261 if (pAd->StaCfg.bAutoTxRateSwitch)
8264 #endif // CONFIG_STA_SUPPORT //
8270 ========================================================================
8271 Routine Description:
8272 check if this entry need to fix tx legacy rate
8282 ========================================================================
8284 UCHAR RTMPStaFixedTxMode(
8285 IN PRTMP_ADAPTER pAd,
8286 IN PMAC_TABLE_ENTRY pEntry)
8288 UCHAR tx_mode = FIXED_TXMODE_HT;
8291 #ifdef CONFIG_STA_SUPPORT
8292 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8294 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8296 #endif // CONFIG_STA_SUPPORT //
8302 ========================================================================
8303 Routine Description:
8304 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8314 ========================================================================
8316 VOID RTMPUpdateLegacyTxSetting(
8317 UCHAR fixed_tx_mode,
8318 PMAC_TABLE_ENTRY pEntry)
8320 HTTRANSMIT_SETTING TransmitSetting;
8322 if (fixed_tx_mode == FIXED_TXMODE_HT)
8325 TransmitSetting.word = 0;
8327 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8328 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8330 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8332 TransmitSetting.field.MODE = MODE_CCK;
8333 // CCK mode allow MCS 0~3
8334 if (TransmitSetting.field.MCS > MCS_3)
8335 TransmitSetting.field.MCS = MCS_3;
8339 TransmitSetting.field.MODE = MODE_OFDM;
8340 // OFDM mode allow MCS 0~7
8341 if (TransmitSetting.field.MCS > MCS_7)
8342 TransmitSetting.field.MCS = MCS_7;
8345 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8347 pEntry->HTPhyMode.word = TransmitSetting.word;
8348 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8349 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8353 #ifdef CONFIG_STA_SUPPORT
8355 ==========================================================================
8357 dynamic tune BBP R66 to find a balance between sensibility and
8360 IRQL = DISPATCH_LEVEL
8362 ==========================================================================
8364 VOID AsicStaBbpTuning(
8365 IN PRTMP_ADAPTER pAd)
8367 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8370 // 2860C did not support Fase CCA, therefore can't tune
8371 if (pAd->MACVersion == 0x28600100)
8377 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8380 if ((pAd->OpMode == OPMODE_STA)
8381 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8383 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8384 && (pAd->bPCIclkOff == FALSE))
8386 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8389 if (pAd->Antenna.field.RxPath > 1)
8390 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8392 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8394 if (pAd->LatchRfRegs.Channel <= 14)
8397 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8399 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8400 if (OrigR66Value != R66)
8402 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8407 R66 = 0x2E + GET_LNA_GAIN(pAd);
8408 if (OrigR66Value != R66)
8410 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8417 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8419 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8421 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8422 if (OrigR66Value != R66)
8424 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8429 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8430 if (OrigR66Value != R66)
8432 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8438 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8440 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8441 if (OrigR66Value != R66)
8443 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8448 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8449 if (OrigR66Value != R66)
8451 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8461 VOID AsicResetFromDMABusy(
8462 IN PRTMP_ADAPTER pAd)
8465 BOOLEAN bCtrl = FALSE;
8467 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8469 // Be sure restore link control value so we can write register.
8470 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8471 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8473 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8474 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8475 RTMPusecDelay(6000);
8476 pAd->bPCIclkOff = FALSE;
8480 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8482 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8484 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8485 // Reset DMA/CPU ring index
8486 RTMPRingCleanUp(pAd, QID_AC_BK);
8487 RTMPRingCleanUp(pAd, QID_AC_BE);
8488 RTMPRingCleanUp(pAd, QID_AC_VI);
8489 RTMPRingCleanUp(pAd, QID_AC_VO);
8490 RTMPRingCleanUp(pAd, QID_HCCA);
8491 RTMPRingCleanUp(pAd, QID_MGMT);
8492 RTMPRingCleanUp(pAd, QID_RX);
8495 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8497 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8499 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8500 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8501 RTMPPCIeLinkCtrlSetting(pAd, 3);
8503 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8504 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8505 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8509 IN PRTMP_ADAPTER pAd)
8511 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8513 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8514 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8515 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8517 // After hard-reset BBP, initialize all BBP values.
8518 NICRestoreBBPValue(pAd);
8519 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8523 IN PRTMP_ADAPTER pAd)
8527 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8528 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8530 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8532 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8534 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8538 IN PRTMP_ADAPTER pAd)
8540 ULONG Value1, Value2;
8543 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8544 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8547 // sum should be equals to 0xff, which is the total buffer size.
8548 if ((Value1 + Value2) < 0xff)
8550 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8551 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8553 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8555 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8557 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8560 #endif // CONFIG_STA_SUPPORT //
8562 VOID RTMPSetAGCInitValue(
8563 IN PRTMP_ADAPTER pAd,
8568 if (pAd->LatchRfRegs.Channel <= 14)
8570 R66 = 0x2E + GET_LNA_GAIN(pAd);
8571 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8575 if (BandWidth == BW_20)
8577 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8578 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8580 #ifdef DOT11_N_SUPPORT
8583 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8584 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8586 #endif // DOT11_N_SUPPORT //
8591 VOID AsicTurnOffRFClk(
8592 IN PRTMP_ADAPTER pAd,
8597 UINT32 R1 = 0, R2 = 0, R3 = 0;
8599 RTMP_RF_REGS *RFRegTable;
8601 RFRegTable = RF2850RegTable;
8603 switch (pAd->RfIcType)
8610 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8612 if (Channel == RFRegTable[index].Channel)
8614 R1 = RFRegTable[index].R1 & 0xffffdfff;
8615 R2 = RFRegTable[index].R2 & 0xfffbffff;
8616 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8618 RTMP_RF_IO_WRITE32(pAd, R1);
8619 RTMP_RF_IO_WRITE32(pAd, R2);
8621 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8622 // Set RF R2 bit18=0, R3 bit[18:19]=0
8623 //if (pAd->StaCfg.bRadio == FALSE)
8626 RTMP_RF_IO_WRITE32(pAd, R3);
8628 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8629 Channel, pAd->RfIcType, R2, R3));
8632 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8633 Channel, pAd->RfIcType, R2));
8645 VOID AsicTurnOnRFClk(
8646 IN PRTMP_ADAPTER pAd,
8651 UINT32 R1 = 0, R2 = 0, R3 = 0;
8653 RTMP_RF_REGS *RFRegTable;
8655 RFRegTable = RF2850RegTable;
8657 switch (pAd->RfIcType)
8664 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8666 if (Channel == RFRegTable[index].Channel)
8668 R3 = pAd->LatchRfRegs.R3;
8671 RTMP_RF_IO_WRITE32(pAd, R3);
8673 R1 = RFRegTable[index].R1;
8674 RTMP_RF_IO_WRITE32(pAd, R1);
8676 R2 = RFRegTable[index].R2;
8677 if (pAd->Antenna.field.TxPath == 1)
8679 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8682 if (pAd->Antenna.field.RxPath == 2)
8684 R2 |= 0x40; // write 1 to off Rxpath.
8686 else if (pAd->Antenna.field.RxPath == 1)
8688 R2 |= 0x20040; // write 1 to off RxPath
8690 RTMP_RF_IO_WRITE32(pAd, R2);
8701 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",