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 MlmeAutoReconnectLastSSID(pAd);
1329 SKIP_AUTO_SCAN_CONN:
1331 #ifdef DOT11_N_SUPPORT
1332 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1334 pAd->MacTab.fAnyBASession = TRUE;
1335 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1337 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1339 pAd->MacTab.fAnyBASession = FALSE;
1340 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1342 #endif // DOT11_N_SUPPORT //
1345 #ifdef DOT11_N_SUPPORT
1346 #ifdef DOT11N_DRAFT3
1347 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1348 TriEventCounterMaintenance(pAd);
1349 #endif // DOT11N_DRAFT3 //
1350 #endif // DOT11_N_SUPPORT //
1357 IN PVOID SystemSpecific1,
1358 IN PVOID FunctionContext,
1359 IN PVOID SystemSpecific2,
1360 IN PVOID SystemSpecific3)
1363 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1365 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1366 RTMP_IndicateMediaState(pAd);
1367 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1370 // IRQL = DISPATCH_LEVEL
1372 IN PRTMP_ADAPTER pAd)
1374 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1375 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1377 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1379 MLME_CNTL_STATE_MACHINE,
1380 OID_802_11_BSSID_LIST_SCAN,
1383 RT28XX_MLME_HANDLER(pAd);
1387 // IRQL = DISPATCH_LEVEL
1388 VOID MlmeAutoReconnectLastSSID(
1389 IN PRTMP_ADAPTER pAd)
1393 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1394 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1395 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1397 NDIS_802_11_SSID OidSsid;
1398 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1399 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1401 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1403 MLME_CNTL_STATE_MACHINE,
1405 sizeof(NDIS_802_11_SSID),
1407 RT28XX_MLME_HANDLER(pAd);
1410 #endif // CONFIG_STA_SUPPORT //
1413 ==========================================================================
1414 Validate SSID for connection try and rescan purpose
1415 Valid SSID will have visible chars only.
1416 The valid length is from 0 to 32.
1417 IRQL = DISPATCH_LEVEL
1418 ==========================================================================
1420 BOOLEAN MlmeValidateSSID(
1426 if (SsidLen > MAX_LEN_OF_SSID)
1429 // Check each character value
1430 for (index = 0; index < SsidLen; index++)
1432 if (pSsid[index] < 0x20)
1440 VOID MlmeSelectTxRateTable(
1441 IN PRTMP_ADAPTER pAd,
1442 IN PMAC_TABLE_ENTRY pEntry,
1444 IN PUCHAR pTableSize,
1445 IN PUCHAR pInitTxRateIdx)
1449 // decide the rate table for tuning
1450 if (pAd->CommonCfg.TxRateTableSize > 0)
1452 *ppTable = RateSwitchTable;
1453 *pTableSize = RateSwitchTable[0];
1454 *pInitTxRateIdx = RateSwitchTable[1];
1459 #ifdef CONFIG_STA_SUPPORT
1460 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1462 #ifdef DOT11_N_SUPPORT
1463 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1464 !pAd->StaCfg.AdhocBOnlyJoined &&
1465 !pAd->StaCfg.AdhocBGJoined &&
1466 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1467 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1469 *ppTable = RateSwitchTable11N1S;
1470 *pTableSize = RateSwitchTable11N1S[0];
1471 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1474 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1475 !pAd->StaCfg.AdhocBOnlyJoined &&
1476 !pAd->StaCfg.AdhocBGJoined &&
1477 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1478 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1479 (pAd->Antenna.field.TxPath == 2))
1481 if (pAd->LatchRfRegs.Channel <= 14)
1483 *ppTable = RateSwitchTable11N2S;
1484 *pTableSize = RateSwitchTable11N2S[0];
1485 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1489 *ppTable = RateSwitchTable11N2SForABand;
1490 *pTableSize = RateSwitchTable11N2SForABand[0];
1491 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1496 #endif // DOT11_N_SUPPORT //
1497 if (pAd->CommonCfg.PhyMode == PHY_11B)
1499 *ppTable = RateSwitchTable11B;
1500 *pTableSize = RateSwitchTable11B[0];
1501 *pInitTxRateIdx = RateSwitchTable11B[1];
1504 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1506 // USe B Table when Only b-only Station in my IBSS .
1507 *ppTable = RateSwitchTable11B;
1508 *pTableSize = RateSwitchTable11B[0];
1509 *pInitTxRateIdx = RateSwitchTable11B[1];
1512 else if (pAd->LatchRfRegs.Channel <= 14)
1514 *ppTable = RateSwitchTable11BG;
1515 *pTableSize = RateSwitchTable11BG[0];
1516 *pInitTxRateIdx = RateSwitchTable11BG[1];
1521 *ppTable = RateSwitchTable11G;
1522 *pTableSize = RateSwitchTable11G[0];
1523 *pInitTxRateIdx = RateSwitchTable11G[1];
1528 #endif // CONFIG_STA_SUPPORT //
1530 #ifdef DOT11_N_SUPPORT
1531 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1532 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1534 *ppTable = RateSwitchTable11BGN1S;
1535 *pTableSize = RateSwitchTable11BGN1S[0];
1536 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1541 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1542 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1544 if (pAd->LatchRfRegs.Channel <= 14)
1546 *ppTable = RateSwitchTable11BGN2S;
1547 *pTableSize = RateSwitchTable11BGN2S[0];
1548 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1553 *ppTable = RateSwitchTable11BGN2SForABand;
1554 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1555 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1561 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1563 *ppTable = RateSwitchTable11N1S;
1564 *pTableSize = RateSwitchTable11N1S[0];
1565 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1570 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1572 if (pAd->LatchRfRegs.Channel <= 14)
1574 *ppTable = RateSwitchTable11N2S;
1575 *pTableSize = RateSwitchTable11N2S[0];
1576 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1580 *ppTable = RateSwitchTable11N2SForABand;
1581 *pTableSize = RateSwitchTable11N2SForABand[0];
1582 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1587 #endif // DOT11_N_SUPPORT //
1588 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1589 if ((pEntry->RateLen == 4)
1590 #ifdef DOT11_N_SUPPORT
1591 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1592 #endif // DOT11_N_SUPPORT //
1595 *ppTable = RateSwitchTable11B;
1596 *pTableSize = RateSwitchTable11B[0];
1597 *pInitTxRateIdx = RateSwitchTable11B[1];
1602 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1603 if ((pEntry->RateLen > 8)
1604 #ifdef DOT11_N_SUPPORT
1605 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1606 #endif // DOT11_N_SUPPORT //
1609 *ppTable = RateSwitchTable11BG;
1610 *pTableSize = RateSwitchTable11BG[0];
1611 *pInitTxRateIdx = RateSwitchTable11BG[1];
1616 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1617 if ((pEntry->RateLen == 8)
1618 #ifdef DOT11_N_SUPPORT
1619 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1620 #endif // DOT11_N_SUPPORT //
1623 *ppTable = RateSwitchTable11G;
1624 *pTableSize = RateSwitchTable11G[0];
1625 *pInitTxRateIdx = RateSwitchTable11G[1];
1629 #ifdef DOT11_N_SUPPORT
1630 #endif // DOT11_N_SUPPORT //
1632 #ifdef CONFIG_STA_SUPPORT
1633 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1635 #ifdef DOT11_N_SUPPORT
1636 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1637 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1638 #endif // DOT11_N_SUPPORT //
1640 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1642 *ppTable = RateSwitchTable11B;
1643 *pTableSize = RateSwitchTable11B[0];
1644 *pInitTxRateIdx = RateSwitchTable11B[1];
1646 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1648 *ppTable = RateSwitchTable11G;
1649 *pTableSize = RateSwitchTable11G[0];
1650 *pInitTxRateIdx = RateSwitchTable11G[1];
1655 *ppTable = RateSwitchTable11BG;
1656 *pTableSize = RateSwitchTable11BG[0];
1657 *pInitTxRateIdx = RateSwitchTable11BG[1];
1661 #ifdef DOT11_N_SUPPORT
1662 if (pAd->LatchRfRegs.Channel <= 14)
1664 if (pAd->CommonCfg.TxStream == 1)
1666 *ppTable = RateSwitchTable11N1S;
1667 *pTableSize = RateSwitchTable11N1S[0];
1668 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1669 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1673 *ppTable = RateSwitchTable11N2S;
1674 *pTableSize = RateSwitchTable11N2S[0];
1675 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1676 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1681 if (pAd->CommonCfg.TxStream == 1)
1683 *ppTable = RateSwitchTable11N1S;
1684 *pTableSize = RateSwitchTable11N1S[0];
1685 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1686 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1690 *ppTable = RateSwitchTable11N2SForABand;
1691 *pTableSize = RateSwitchTable11N2SForABand[0];
1692 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1693 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1696 #endif // DOT11_N_SUPPORT //
1697 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1698 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1700 #endif // CONFIG_STA_SUPPORT //
1704 #ifdef CONFIG_STA_SUPPORT
1706 ==========================================================================
1708 This routine checks if there're other APs out there capable for
1709 roaming. Caller should call this routine only when Link up in INFRA mode
1710 and channel quality is below CQI_GOOD_THRESHOLD.
1712 IRQL = DISPATCH_LEVEL
1715 ==========================================================================
1717 VOID MlmeCheckForRoaming(
1718 IN PRTMP_ADAPTER pAd,
1722 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1725 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1726 // put all roaming candidates into RoamTab, and sort in RSSI order
1727 BssTableInit(pRoamTab);
1728 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1730 pBss = &pAd->ScanTab.BssEntry[i];
1732 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1733 continue; // AP disappear
1734 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1735 continue; // RSSI too weak. forget it.
1736 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1737 continue; // skip current AP
1738 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1739 continue; // only AP with stronger RSSI is eligible for roaming
1741 // AP passing all above rules is put into roaming candidate table
1742 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1743 pRoamTab->BssNr += 1;
1746 if (pRoamTab->BssNr > 0)
1748 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1749 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1751 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1752 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1753 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1754 RT28XX_MLME_HANDLER(pAd);
1757 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1761 ==========================================================================
1763 This routine checks if there're other APs out there capable for
1764 roaming. Caller should call this routine only when link up in INFRA mode
1765 and channel quality is below CQI_GOOD_THRESHOLD.
1767 IRQL = DISPATCH_LEVEL
1770 ==========================================================================
1772 VOID MlmeCheckForFastRoaming(
1773 IN PRTMP_ADAPTER pAd,
1777 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1780 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1781 // put all roaming candidates into RoamTab, and sort in RSSI order
1782 BssTableInit(pRoamTab);
1783 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1785 pBss = &pAd->ScanTab.BssEntry[i];
1787 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1788 continue; // RSSI too weak. forget it.
1789 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1790 continue; // skip current AP
1791 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1792 continue; // skip different SSID
1793 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1794 continue; // skip AP without better RSSI
1796 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));
1797 // AP passing all above rules is put into roaming candidate table
1798 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1799 pRoamTab->BssNr += 1;
1802 if (pRoamTab->BssNr > 0)
1804 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1805 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1807 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1808 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1809 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1810 RT28XX_MLME_HANDLER(pAd);
1813 // Maybe site survey required
1816 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1818 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1819 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1820 pAd->StaCfg.ScanCnt = 2;
1821 pAd->StaCfg.LastScanTime = Now;
1826 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1830 ==========================================================================
1832 This routine calculates TxPER, RxPER of the past N-sec period. And
1833 according to the calculation result, ChannelQuality is calculated here
1834 to decide if current AP is still doing the job.
1836 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1838 StaCfg.ChannelQuality - 0..100
1840 IRQL = DISPATCH_LEVEL
1842 NOTE: This routine decide channle quality based on RX CRC error ratio.
1843 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1844 is performed right before this routine, so that this routine can decide
1845 channel quality based on the most up-to-date information
1846 ==========================================================================
1848 VOID MlmeCalculateChannelQuality(
1849 IN PRTMP_ADAPTER pAd,
1852 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1856 ULONG BeaconLostTime = BEACON_LOST_TIME;
1858 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1861 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1863 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1864 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1872 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1873 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1877 // calculate RX PER - don't take RxPER into consideration if too few sample
1879 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1883 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1886 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1888 if (INFRA_ON(pAd) &&
1889 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1890 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1892 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1893 pAd->Mlme.ChannelQuality = 0;
1900 else if (MaxRssi < -90)
1903 NorRssi = (MaxRssi + 90) * 2;
1905 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1906 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1907 TX_WEIGHTING * (100 - TxPRR) +
1908 RX_WEIGHTING* (100 - RxPER)) / 100;
1909 if (pAd->Mlme.ChannelQuality >= 100)
1910 pAd->Mlme.ChannelQuality = 100;
1916 IN PRTMP_ADAPTER pAd,
1917 IN PMAC_TABLE_ENTRY pEntry,
1918 IN PRTMP_TX_RATE_SWITCH pTxRate)
1920 UCHAR MaxMode = MODE_OFDM;
1922 #ifdef DOT11_N_SUPPORT
1923 MaxMode = MODE_HTGREENFIELD;
1925 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1926 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1928 #endif // DOT11_N_SUPPORT //
1929 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1931 if (pTxRate->CurrMCS < MCS_AUTO)
1932 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1934 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1935 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1939 // If peer adhoc is b-only mode, we can't send 11g rate.
1940 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1941 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1944 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1946 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1947 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1948 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1950 // Patch speed error in status page
1951 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1955 if (pTxRate->Mode <= MaxMode)
1956 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1958 #ifdef DOT11_N_SUPPORT
1959 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1960 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1962 #endif // DOT11_N_SUPPORT //
1963 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1965 #ifdef DOT11_N_SUPPORT
1966 // Reexam each bandwidth's SGI support.
1967 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1969 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1970 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1971 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1972 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1975 // Turn RTS/CTS rate to 6Mbps.
1976 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1978 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1979 if (pAd->MacTab.fAnyBASession)
1981 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1985 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1988 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1990 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1991 if (pAd->MacTab.fAnyBASession)
1993 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1997 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2000 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
2002 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2005 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
2007 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
2009 #endif // DOT11_N_SUPPORT //
2011 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
2012 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
2013 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
2014 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
2015 #ifdef DOT11_N_SUPPORT
2016 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
2017 pAd->WIFItestbed.bGreenField)
2018 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
2019 #endif // DOT11_N_SUPPORT //
2022 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
2026 ==========================================================================
2028 This routine calculates the acumulated TxPER of eaxh TxRate. And
2029 according to the calculation result, change CommonCfg.TxRate which
2030 is the stable TX Rate we expect the Radio situation could sustained.
2032 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
2036 IRQL = DISPATCH_LEVEL
2039 call this routine every second
2040 ==========================================================================
2042 VOID MlmeDynamicTxRateSwitching(
2043 IN PRTMP_ADAPTER pAd)
2045 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
2046 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
2047 ULONG TxErrorRatio = 0;
2048 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
2049 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2051 UCHAR TableSize = 0;
2052 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2053 CHAR Rssi, RssiOffset = 0;
2054 TX_STA_CNT1_STRUC StaTx1;
2055 TX_STA_CNT0_STRUC TxStaCnt0;
2056 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2057 MAC_TABLE_ENTRY *pEntry;
2059 /*if (pAd->Antenna.field.RxPath > 1)
2060 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2062 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
2065 // walk through MAC table, see if need to change AP's TX rate toward each entry
2067 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2069 pEntry = &pAd->MacTab.Content[i];
2071 // check if this entry need to switch rate automatically
2072 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2075 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2077 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
2079 // Update statistic counter
2080 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2081 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2082 pAd->bUpdateBcnCntDone = TRUE;
2083 TxRetransmit = StaTx1.field.TxRetransmit;
2084 TxSuccess = StaTx1.field.TxSuccess;
2085 TxFailCount = TxStaCnt0.field.TxFailCount;
2086 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2088 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2089 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2090 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2091 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2092 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2093 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2095 // if no traffic in the past 1-sec period, don't change TX rate,
2096 // but clear all bad history. because the bad history may affect the next
2097 // Chariot throughput test
2098 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2099 pAd->RalinkCounters.OneSecTxRetryOkCount +
2100 pAd->RalinkCounters.OneSecTxFailCount;
2103 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2107 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2109 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2110 pEntry->OneSecTxRetryOkCount +
2111 pEntry->OneSecTxFailCount;
2114 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2117 CurrRateIdx = pEntry->CurrTxRateIndex;
2119 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2121 if (CurrRateIdx >= TableSize)
2123 CurrRateIdx = TableSize - 1;
2126 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2127 // So need to sync here.
2128 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2129 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2130 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2134 // Need to sync Real Tx rate and our record.
2135 // Then return for next DRS.
2136 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2137 pEntry->CurrTxRateIndex = InitTxRateIdx;
2138 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2140 // reset all OneSecTx counters
2141 RESET_ONE_SEC_TX_CNT(pEntry);
2145 // decide the next upgrade rate and downgrade rate, if any
2146 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2148 UpRateIdx = CurrRateIdx + 1;
2149 DownRateIdx = CurrRateIdx -1;
2151 else if (CurrRateIdx == 0)
2153 UpRateIdx = CurrRateIdx + 1;
2154 DownRateIdx = CurrRateIdx;
2156 else if (CurrRateIdx == (TableSize - 1))
2158 UpRateIdx = CurrRateIdx;
2159 DownRateIdx = CurrRateIdx - 1;
2162 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2164 #ifdef DOT11_N_SUPPORT
2165 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2167 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2168 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2171 #endif // DOT11_N_SUPPORT //
2173 TrainUp = pCurrTxRate->TrainUp;
2174 TrainDown = pCurrTxRate->TrainDown;
2177 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2180 // Keep the last time TxRateChangeAction status.
2182 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2187 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2188 // (criteria copied from RT2500 for Netopia case)
2190 if (TxTotalCnt <= 15)
2194 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2195 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2196 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2197 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2199 // check the existence and index of each needed MCS
2200 while (idx < pTable[0])
2202 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2204 if (pCurrTxRate->CurrMCS == MCS_0)
2208 else if (pCurrTxRate->CurrMCS == MCS_1)
2212 else if (pCurrTxRate->CurrMCS == MCS_2)
2216 else if (pCurrTxRate->CurrMCS == MCS_3)
2220 else if (pCurrTxRate->CurrMCS == MCS_4)
2224 else if (pCurrTxRate->CurrMCS == MCS_5)
2228 else if (pCurrTxRate->CurrMCS == MCS_6)
2232 //else if (pCurrTxRate->CurrMCS == MCS_7)
2233 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2237 else if (pCurrTxRate->CurrMCS == MCS_12)
2241 else if (pCurrTxRate->CurrMCS == MCS_13)
2245 else if (pCurrTxRate->CurrMCS == MCS_14)
2249 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2250 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
2254 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2258 else if (pCurrTxRate->CurrMCS == MCS_21)
2262 else if (pCurrTxRate->CurrMCS == MCS_22)
2266 else if (pCurrTxRate->CurrMCS == MCS_23)
2273 if (pAd->LatchRfRegs.Channel <= 14)
2275 if (pAd->NicConfig2.field.ExternalLNAForG)
2286 if (pAd->NicConfig2.field.ExternalLNAForA)
2295 #ifdef DOT11_N_SUPPORT
2297 if ((pTable == RateSwitchTable11BGN3S) ||
2298 (pTable == RateSwitchTable11N3S) ||
2299 (pTable == RateSwitchTable))
2300 {// N mode with 3 stream // 3*3
2301 if (MCS23 && (Rssi >= -70))
2303 else if (MCS22 && (Rssi >= -72))
2305 else if (MCS21 && (Rssi >= -76))
2307 else if (MCS20 && (Rssi >= -78))
2309 else if (MCS4 && (Rssi >= -82))
2311 else if (MCS3 && (Rssi >= -84))
2313 else if (MCS2 && (Rssi >= -86))
2315 else if (MCS1 && (Rssi >= -88))
2320 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2321 {// N mode with 2 stream
2322 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2324 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2326 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2328 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2330 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2332 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2334 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2336 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2341 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2342 {// N mode with 1 stream
2343 if (MCS7 && (Rssi > (-72+RssiOffset)))
2345 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2347 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2349 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2351 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2353 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2355 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2361 #endif // DOT11_N_SUPPORT //
2363 if (MCS7 && (Rssi > -70))
2365 else if (MCS6 && (Rssi > -74))
2367 else if (MCS5 && (Rssi > -78))
2369 else if (MCS4 && (Rssi > -82))
2371 else if (MCS4 == 0) // for B-only mode
2373 else if (MCS3 && (Rssi > -85))
2375 else if (MCS2 && (Rssi > -87))
2377 else if (MCS1 && (Rssi > -90))
2384 pEntry->CurrTxRateIndex = TxRateIdx;
2385 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2386 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2389 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2390 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2391 pEntry->fLastSecAccordingRSSI = TRUE;
2392 // reset all OneSecTx counters
2393 RESET_ONE_SEC_TX_CNT(pEntry);
2398 if (pEntry->fLastSecAccordingRSSI == TRUE)
2400 pEntry->fLastSecAccordingRSSI = FALSE;
2401 pEntry->LastSecTxRateChangeAction = 0;
2402 // reset all OneSecTx counters
2403 RESET_ONE_SEC_TX_CNT(pEntry);
2410 BOOLEAN bTrainUpDown = FALSE;
2412 pEntry->CurrTxRateStableTime ++;
2414 // downgrade TX quality if PER >= Rate-Down threshold
2415 if (TxErrorRatio >= TrainDown)
2417 bTrainUpDown = TRUE;
2418 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2420 // upgrade TX quality if PER <= Rate-Up threshold
2421 else if (TxErrorRatio <= TrainUp)
2423 bTrainUpDown = TRUE;
2424 bUpgradeQuality = TRUE;
2425 if (pEntry->TxQuality[CurrRateIdx])
2426 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2428 if (pEntry->TxRateUpPenalty)
2429 pEntry->TxRateUpPenalty --;
2430 else if (pEntry->TxQuality[UpRateIdx])
2431 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2434 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2438 // perform DRS - consider TxRate Down first, then rate up.
2439 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2441 pEntry->CurrTxRateIndex = DownRateIdx;
2443 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2445 pEntry->CurrTxRateIndex = UpRateIdx;
2450 // if rate-up happen, clear all bad history of all TX rates
2451 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2453 pEntry->CurrTxRateStableTime = 0;
2454 pEntry->TxRateUpPenalty = 0;
2455 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2456 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2457 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2460 // For TxRate fast train up
2462 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2464 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2466 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2468 bTxRateChanged = TRUE;
2470 // if rate-down happen, only clear DownRate's bad history
2471 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2473 pEntry->CurrTxRateStableTime = 0;
2474 pEntry->TxRateUpPenalty = 0; // no penalty
2475 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2476 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2477 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2480 // For TxRate fast train down
2482 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2484 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2486 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2488 bTxRateChanged = TRUE;
2492 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2493 bTxRateChanged = FALSE;
2496 pEntry->LastTxOkCount = TxSuccess;
2498 // reset all OneSecTx counters
2499 RESET_ONE_SEC_TX_CNT(pEntry);
2501 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2502 if (bTxRateChanged && pNextTxRate)
2504 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2510 ========================================================================
2511 Routine Description:
2512 Station side, Auto TxRate faster train up timer call back function.
2515 SystemSpecific1 - Not used.
2516 FunctionContext - Pointer to our Adapter context.
2517 SystemSpecific2 - Not used.
2518 SystemSpecific3 - Not used.
2523 ========================================================================
2525 VOID StaQuickResponeForRateUpExec(
2526 IN PVOID SystemSpecific1,
2527 IN PVOID FunctionContext,
2528 IN PVOID SystemSpecific2,
2529 IN PVOID SystemSpecific3)
2531 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2532 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2534 ULONG TxErrorRatio = 0;
2535 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2536 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2538 UCHAR TableSize = 0;
2539 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2540 TX_STA_CNT1_STRUC StaTx1;
2541 TX_STA_CNT0_STRUC TxStaCnt0;
2543 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2544 MAC_TABLE_ENTRY *pEntry;
2547 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2550 // walk through MAC table, see if need to change AP's TX rate toward each entry
2552 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2554 pEntry = &pAd->MacTab.Content[i];
2556 // check if this entry need to switch rate automatically
2557 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2560 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2561 if (pAd->Antenna.field.TxPath > 1)
2562 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2564 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2566 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2568 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2570 // decide the next upgrade rate and downgrade rate, if any
2571 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2573 UpRateIdx = CurrRateIdx + 1;
2574 DownRateIdx = CurrRateIdx -1;
2576 else if (CurrRateIdx == 0)
2578 UpRateIdx = CurrRateIdx + 1;
2579 DownRateIdx = CurrRateIdx;
2581 else if (CurrRateIdx == (TableSize - 1))
2583 UpRateIdx = CurrRateIdx;
2584 DownRateIdx = CurrRateIdx - 1;
2587 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2589 #ifdef DOT11_N_SUPPORT
2590 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2592 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2593 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2596 #endif // DOT11_N_SUPPORT //
2598 TrainUp = pCurrTxRate->TrainUp;
2599 TrainDown = pCurrTxRate->TrainDown;
2602 if (pAd->MacTab.Size == 1)
2604 // Update statistic counter
2605 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2606 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2608 TxRetransmit = StaTx1.field.TxRetransmit;
2609 TxSuccess = StaTx1.field.TxSuccess;
2610 TxFailCount = TxStaCnt0.field.TxFailCount;
2611 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2613 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2614 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2615 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2616 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2617 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2618 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2621 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2625 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2626 pEntry->OneSecTxRetryOkCount +
2627 pEntry->OneSecTxFailCount;
2630 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2635 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2636 // (criteria copied from RT2500 for Netopia case)
2638 if (TxTotalCnt <= 12)
2640 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2641 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2643 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2645 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2646 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2648 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2650 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2653 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2659 ULONG OneSecTxNoRetryOKRationCount;
2661 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2666 // downgrade TX quality if PER >= Rate-Down threshold
2667 if (TxErrorRatio >= TrainDown)
2669 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2672 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2674 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2676 // perform DRS - consider TxRate Down first, then rate up.
2677 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2679 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2681 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2682 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2687 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2689 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2693 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2695 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2700 // if rate-up happen, clear all bad history of all TX rates
2701 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2703 pAd->DrsCounters.TxRateUpPenalty = 0;
2704 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2705 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2707 // if rate-down happen, only clear DownRate's bad history
2708 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2710 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2712 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2713 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2714 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2718 bTxRateChanged = FALSE;
2721 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2722 if (bTxRateChanged && pNextTxRate)
2724 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2730 ==========================================================================
2732 This routine is executed periodically inside MlmePeriodicExec() after
2733 association with an AP.
2734 It checks if StaCfg.Psm is consistent with user policy (recorded in
2735 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2736 there're some conditions to consider:
2737 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2738 the time when Mibss==TRUE
2739 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2740 if outgoing traffic available in TxRing or MgmtRing.
2742 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2744 IRQL = DISPATCH_LEVEL
2746 ==========================================================================
2748 VOID MlmeCheckPsmChange(
2749 IN PRTMP_ADAPTER pAd,
2755 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2756 // 2. user wants either MAX_PSP or FAST_PSP
2757 // 3. but current psm is not in PWR_SAVE
2758 // 4. CNTL state machine is not doing SCANning
2759 // 5. no TX SUCCESS event for the past 1-sec period
2760 #ifdef NDIS51_MINIPORT
2761 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2762 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2765 PowerMode = pAd->StaCfg.WindowsPowerMode;
2767 if (INFRA_ON(pAd) &&
2768 (PowerMode != Ndis802_11PowerModeCAM) &&
2769 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2770 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2772 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2773 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2774 MlmeSetPsmBit(pAd, PWR_SAVE);
2775 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2777 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2781 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2786 // IRQL = PASSIVE_LEVEL
2787 // IRQL = DISPATCH_LEVEL
2789 IN PRTMP_ADAPTER pAd,
2792 AUTO_RSP_CFG_STRUC csr4;
2794 pAd->StaCfg.Psm = psm;
2795 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2796 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2797 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2798 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2800 #endif // CONFIG_STA_SUPPORT //
2803 // IRQL = DISPATCH_LEVEL
2804 VOID MlmeSetTxPreamble(
2805 IN PRTMP_ADAPTER pAd,
2806 IN USHORT TxPreamble)
2808 AUTO_RSP_CFG_STRUC csr4;
2811 // Always use Long preamble before verifiation short preamble functionality works well.
2812 // Todo: remove the following line if short preamble functionality works
2814 //TxPreamble = Rt802_11PreambleLong;
2816 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2817 if (TxPreamble == Rt802_11PreambleLong)
2819 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2820 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2821 csr4.field.AutoResponderPreamble = 0;
2825 // NOTE: 1Mbps should always use long preamble
2826 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2827 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2828 csr4.field.AutoResponderPreamble = 1;
2831 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2835 ==========================================================================
2837 Update basic rate bitmap
2838 ==========================================================================
2841 VOID UpdateBasicRateBitmap(
2842 IN PRTMP_ADAPTER pAdapter)
2845 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2846 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2847 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2848 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2849 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2852 /* if A mode, always use fix BasicRateBitMap */
2853 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2854 if (pAdapter->CommonCfg.Channel > 14)
2855 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2858 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2860 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2864 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2870 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2872 if (bitmap & (1 << i))
2874 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2876 if (sup_p[j] == rate[i])
2881 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2883 if (ext_p[j] == rate[i])
2889 } /* End of UpdateBasicRateBitmap */
2891 // IRQL = PASSIVE_LEVEL
2892 // IRQL = DISPATCH_LEVEL
2893 // bLinkUp is to identify the inital link speed.
2894 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2895 VOID MlmeUpdateTxRates(
2896 IN PRTMP_ADAPTER pAd,
2901 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2902 UCHAR MinSupport = RATE_54;
2903 ULONG BasicRateBitmap = 0;
2904 UCHAR CurrBasicRate = RATE_1;
2905 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2906 PHTTRANSMIT_SETTING pHtPhy = NULL;
2907 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2908 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2909 BOOLEAN *auto_rate_cur_p;
2910 UCHAR HtMcs = MCS_AUTO;
2912 // find max desired rate
2913 UpdateBasicRateBitmap(pAd);
2916 auto_rate_cur_p = NULL;
2917 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2919 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2921 case 2: Rate = RATE_1; num++; break;
2922 case 4: Rate = RATE_2; num++; break;
2923 case 11: Rate = RATE_5_5; num++; break;
2924 case 22: Rate = RATE_11; num++; break;
2925 case 12: Rate = RATE_6; num++; break;
2926 case 18: Rate = RATE_9; num++; break;
2927 case 24: Rate = RATE_12; num++; break;
2928 case 36: Rate = RATE_18; num++; break;
2929 case 48: Rate = RATE_24; num++; break;
2930 case 72: Rate = RATE_36; num++; break;
2931 case 96: Rate = RATE_48; num++; break;
2932 case 108: Rate = RATE_54; num++; break;
2933 //default: Rate = RATE_1; break;
2935 if (MaxDesire < Rate) MaxDesire = Rate;
2938 //===========================================================================
2939 //===========================================================================
2941 #ifdef CONFIG_STA_SUPPORT
2942 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2944 pHtPhy = &pAd->StaCfg.HTPhyMode;
2945 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2946 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2948 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2949 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2951 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2952 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2953 (MaxDesire > RATE_11))
2955 MaxDesire = RATE_11;
2958 #endif // CONFIG_STA_SUPPORT //
2960 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2961 pMinHtPhy->word = 0;
2962 pMaxHtPhy->word = 0;
2965 // Auto rate switching is enabled only if more than one DESIRED RATES are
2966 // specified; otherwise disabled
2969 *auto_rate_cur_p = FALSE;
2973 *auto_rate_cur_p = TRUE;
2977 if (HtMcs != MCS_AUTO)
2979 *auto_rate_cur_p = FALSE;
2983 *auto_rate_cur_p = TRUE;
2987 #ifdef CONFIG_STA_SUPPORT
2988 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2990 pSupRate = &pAd->StaActive.SupRate[0];
2991 pExtRate = &pAd->StaActive.ExtRate[0];
2992 SupRateLen = pAd->StaActive.SupRateLen;
2993 ExtRateLen = pAd->StaActive.ExtRateLen;
2996 #endif // CONFIG_STA_SUPPORT //
2998 pSupRate = &pAd->CommonCfg.SupRate[0];
2999 pExtRate = &pAd->CommonCfg.ExtRate[0];
3000 SupRateLen = pAd->CommonCfg.SupRateLen;
3001 ExtRateLen = pAd->CommonCfg.ExtRateLen;
3004 // find max supported rate
3005 for (i=0; i<SupRateLen; i++)
3007 switch (pSupRate[i] & 0x7f)
3009 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3010 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3011 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3012 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3013 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3014 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3015 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3016 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3017 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3018 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3019 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3020 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3021 default: Rate = RATE_1; break;
3023 if (MaxSupport < Rate) MaxSupport = Rate;
3025 if (MinSupport > Rate) MinSupport = Rate;
3028 for (i=0; i<ExtRateLen; i++)
3030 switch (pExtRate[i] & 0x7f)
3032 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3033 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3034 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3035 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3036 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3037 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3038 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3039 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3040 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3041 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3042 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3043 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3044 default: Rate = RATE_1; break;
3046 if (MaxSupport < Rate) MaxSupport = Rate;
3048 if (MinSupport > Rate) MinSupport = Rate;
3051 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3053 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3054 // the DURATION field of outgoing uniicast DATA/MGMT frame
3055 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3057 if (BasicRateBitmap & (0x01 << i))
3058 CurrBasicRate = (UCHAR)i;
3059 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3062 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3063 // max tx rate = min {max desire rate, max supported rate}
3064 if (MaxSupport < MaxDesire)
3065 pAd->CommonCfg.MaxTxRate = MaxSupport;
3067 pAd->CommonCfg.MaxTxRate = MaxDesire;
3069 pAd->CommonCfg.MinTxRate = MinSupport;
3070 if (*auto_rate_cur_p)
3073 #ifdef CONFIG_STA_SUPPORT
3074 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3075 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3076 #endif // CONFIG_STA_SUPPORT //
3077 if (bLinkUp == TRUE)
3078 pAd->CommonCfg.TxRate = RATE_24;
3080 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3083 pAd->CommonCfg.TxRate = RATE_11;
3085 pAd->CommonCfg.TxRate = RATE_24;
3087 // should never exceed MaxTxRate (consider 11B-only mode)
3088 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3089 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3091 pAd->CommonCfg.TxRateIndex = 0;
3095 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3096 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3097 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3099 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3100 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3101 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3102 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3105 if (pAd->CommonCfg.TxRate <= RATE_11)
3107 pMaxHtPhy->field.MODE = MODE_CCK;
3108 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3109 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3113 pMaxHtPhy->field.MODE = MODE_OFDM;
3114 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3115 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3116 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3118 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3121 pHtPhy->word = (pMaxHtPhy->word);
3122 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3124 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3125 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3126 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3130 switch (pAd->CommonCfg.PhyMode)
3132 case PHY_11BG_MIXED:
3134 #ifdef DOT11_N_SUPPORT
3135 case PHY_11BGN_MIXED:
3136 #endif // DOT11_N_SUPPORT //
3137 pAd->CommonCfg.MlmeRate = RATE_1;
3138 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3139 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3140 pAd->CommonCfg.RtsRate = RATE_11;
3144 #ifdef DOT11_N_SUPPORT
3145 case PHY_11AGN_MIXED:
3146 case PHY_11GN_MIXED:
3148 case PHY_11AN_MIXED:
3150 #endif // DOT11_N_SUPPORT //
3151 pAd->CommonCfg.MlmeRate = RATE_6;
3152 pAd->CommonCfg.RtsRate = RATE_6;
3153 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3154 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3156 case PHY_11ABG_MIXED:
3157 #ifdef DOT11_N_SUPPORT
3158 case PHY_11ABGN_MIXED:
3159 #endif // DOT11_N_SUPPORT //
3160 if (pAd->CommonCfg.Channel <= 14)
3162 pAd->CommonCfg.MlmeRate = RATE_1;
3163 pAd->CommonCfg.RtsRate = RATE_1;
3164 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3165 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3169 pAd->CommonCfg.MlmeRate = RATE_6;
3170 pAd->CommonCfg.RtsRate = RATE_6;
3171 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3172 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3176 pAd->CommonCfg.MlmeRate = RATE_6;
3177 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3178 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3179 pAd->CommonCfg.RtsRate = RATE_1;
3183 // Keep Basic Mlme Rate.
3185 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3186 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3187 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3189 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3190 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3193 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3194 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3195 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3196 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3197 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3198 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3199 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 ));
3202 #ifdef DOT11_N_SUPPORT
3204 ==========================================================================
3206 This function update HT Rate setting.
3207 Input Wcid value is valid for 2 case :
3208 1. it's used for Station in infra mode that copy AP rate to Mactable.
3209 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3211 IRQL = DISPATCH_LEVEL
3213 ==========================================================================
3215 VOID MlmeUpdateHtTxRates(
3216 IN PRTMP_ADAPTER pAd,
3219 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3221 RT_HT_CAPABILITY *pRtHtCap = NULL;
3222 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3225 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3226 PHTTRANSMIT_SETTING pHtPhy = NULL;
3227 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3228 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3229 BOOLEAN *auto_rate_cur_p;
3231 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3233 auto_rate_cur_p = NULL;
3235 #ifdef CONFIG_STA_SUPPORT
3236 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3238 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3239 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3240 pHtPhy = &pAd->StaCfg.HTPhyMode;
3241 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3242 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3244 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3246 #endif // CONFIG_STA_SUPPORT //
3248 #ifdef CONFIG_STA_SUPPORT
3249 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3251 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3254 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3255 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3256 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3257 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3258 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3259 pMaxHtPhy->field.STBC = STBC_USE;
3261 pMaxHtPhy->field.STBC = STBC_NONE;
3264 #endif // CONFIG_STA_SUPPORT //
3266 if (pDesireHtPhy->bHtEnable == FALSE)
3269 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3270 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3271 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3272 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3273 pMaxHtPhy->field.STBC = STBC_USE;
3275 pMaxHtPhy->field.STBC = STBC_NONE;
3278 // Decide MAX ht rate.
3279 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3280 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3282 pMaxHtPhy->field.MODE = MODE_HTMIX;
3284 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3285 pMaxHtPhy->field.BW = BW_40;
3287 pMaxHtPhy->field.BW = BW_20;
3289 if (pMaxHtPhy->field.BW == BW_20)
3290 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3292 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3294 for (i=23; i>=0; i--) // 3*3
3297 bitmask = (1<<(i-(j*8)));
3299 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3301 pMaxHtPhy->field.MCS = i;
3309 // Copy MIN ht rate. rt2860???
3310 pMinHtPhy->field.BW = BW_20;
3311 pMinHtPhy->field.MCS = 0;
3312 pMinHtPhy->field.STBC = 0;
3313 pMinHtPhy->field.ShortGI = 0;
3314 //If STA assigns fixed rate. update to fixed here.
3315 #ifdef CONFIG_STA_SUPPORT
3316 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3318 if (pDesireHtPhy->MCSSet[4] != 0)
3320 pMaxHtPhy->field.MCS = 32;
3321 pMinHtPhy->field.MCS = 32;
3322 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3325 for (i=23; (CHAR)i >= 0; i--) // 3*3
3328 bitmask = (1<<(i-(j*8)));
3329 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3331 pMaxHtPhy->field.MCS = i;
3332 pMinHtPhy->field.MCS = i;
3339 #endif // CONFIG_STA_SUPPORT //
3343 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3344 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3345 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3346 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3347 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3349 // use default now. rt2860
3350 if (pDesireHtPhy->MCSSet[0] != 0xff)
3351 *auto_rate_cur_p = FALSE;
3353 *auto_rate_cur_p = TRUE;
3355 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3356 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3357 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3358 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3360 #endif // DOT11_N_SUPPORT //
3362 // IRQL = DISPATCH_LEVEL
3364 IN PRTMP_ADAPTER pAd)
3366 RT28XX_MLME_RADIO_OFF(pAd);
3369 // IRQL = DISPATCH_LEVEL
3371 IN PRTMP_ADAPTER pAd)
3373 RT28XX_MLME_RADIO_ON(pAd);
3376 // ===========================================================================================
3378 // ===========================================================================================
3381 /*! \brief initialize BSS table
3382 * \param p_tab pointer to the table
3387 IRQL = PASSIVE_LEVEL
3388 IRQL = DISPATCH_LEVEL
3397 Tab->BssOverlapNr = 0;
3398 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3400 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3401 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3405 #ifdef DOT11_N_SUPPORT
3407 IN PRTMP_ADAPTER pAd,
3412 Tab->numAsOriginator = 0;
3413 Tab->numAsRecipient = 0;
3414 NdisAllocateSpinLock(&pAd->BATabLock);
3415 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3417 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3418 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3420 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3422 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3425 #endif // DOT11_N_SUPPORT //
3427 /*! \brief search the BSS table by SSID
3428 * \param p_tab pointer to the bss table
3429 * \param ssid SSID string
3430 * \return index of the table, BSS_NOT_FOUND if not in the table
3433 * \note search by sequential search
3435 IRQL = DISPATCH_LEVEL
3438 ULONG BssTableSearch(
3445 for (i = 0; i < Tab->BssNr; i++)
3448 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3449 // We should distinguish this case.
3451 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3452 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3453 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3458 return (ULONG)BSS_NOT_FOUND;
3461 ULONG BssSsidTableSearch(
3470 for (i = 0; i < Tab->BssNr; i++)
3473 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3474 // We should distinguish this case.
3476 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3477 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3478 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3479 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3484 return (ULONG)BSS_NOT_FOUND;
3487 ULONG BssTableSearchWithSSID(
3496 for (i = 0; i < Tab->BssNr; i++)
3498 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3499 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3500 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3501 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3502 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3503 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3508 return (ULONG)BSS_NOT_FOUND;
3511 // IRQL = DISPATCH_LEVEL
3512 VOID BssTableDeleteEntry(
3513 IN OUT BSS_TABLE *Tab,
3519 for (i = 0; i < Tab->BssNr; i++)
3521 if ((Tab->BssEntry[i].Channel == Channel) &&
3522 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3524 for (j = i; j < Tab->BssNr - 1; j++)
3526 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3528 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3535 #ifdef DOT11_N_SUPPORT
3537 ========================================================================
3538 Routine Description:
3539 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3542 // IRQL = DISPATCH_LEVEL
3543 ========================================================================
3545 VOID BATableDeleteORIEntry(
3546 IN OUT PRTMP_ADAPTER pAd,
3547 IN BA_ORI_ENTRY *pBAORIEntry)
3550 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3552 NdisAcquireSpinLock(&pAd->BATabLock);
3553 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3555 pAd->BATable.numAsOriginator -= 1;
3556 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3557 // Erase Bitmap flag.
3559 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3560 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3561 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3562 pBAORIEntry->Token = 1;
3563 // Not clear Sequence here.
3564 NdisReleaseSpinLock(&pAd->BATabLock);
3567 #endif // DOT11_N_SUPPORT //
3575 IRQL = DISPATCH_LEVEL
3579 IN PRTMP_ADAPTER pAd,
3580 OUT BSS_ENTRY *pBss,
3585 IN USHORT BeaconPeriod,
3586 IN PCF_PARM pCfParm,
3588 IN USHORT CapabilityInfo,
3590 IN UCHAR SupRateLen,
3592 IN UCHAR ExtRateLen,
3593 IN HT_CAPABILITY_IE *pHtCapability,
3594 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3595 IN UCHAR HtCapabilityLen,
3596 IN UCHAR AddHtInfoLen,
3597 IN UCHAR NewExtChanOffset,
3600 IN LARGE_INTEGER TimeStamp,
3602 IN PEDCA_PARM pEdcaParm,
3603 IN PQOS_CAPABILITY_PARM pQosCapability,
3604 IN PQBSS_LOAD_PARM pQbssLoad,
3605 IN USHORT LengthVIE,
3606 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3608 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3609 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3613 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3614 // Or send beacon /probe response with SSID len matching real SSID length,
3615 // but SSID is all zero. such as "00-00-00-00" with length 4.
3616 // We have to prevent this case overwrite correct table
3617 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3619 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3620 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3621 pBss->SsidLen = SsidLen;
3627 pBss->BssType = BssType;
3628 pBss->BeaconPeriod = BeaconPeriod;
3629 if (BssType == BSS_INFRA)
3631 if (pCfParm->bValid)
3633 pBss->CfpCount = pCfParm->CfpCount;
3634 pBss->CfpPeriod = pCfParm->CfpPeriod;
3635 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3636 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3641 pBss->AtimWin = AtimWin;
3644 pBss->CapabilityInfo = CapabilityInfo;
3645 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3646 // Combine with AuthMode, they will decide the connection methods.
3647 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3648 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3649 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3650 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3652 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3653 pBss->SupRateLen = SupRateLen;
3654 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3655 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3656 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3657 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3658 pBss->NewExtChanOffset = NewExtChanOffset;
3659 pBss->ExtRateLen = ExtRateLen;
3660 pBss->Channel = Channel;
3661 pBss->CentralChannel = Channel;
3663 // Update CkipFlag. if not exists, the value is 0x0
3664 pBss->CkipFlag = CkipFlag;
3666 // New for microsoft Fixed IEs
3667 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3668 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3669 pBss->FixIEs.Capabilities = CapabilityInfo;
3671 // New for microsoft Variable IEs
3674 pBss->VarIELen = LengthVIE;
3675 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3682 pBss->AddHtInfoLen = 0;
3683 pBss->HtCapabilityLen = 0;
3684 #ifdef DOT11_N_SUPPORT
3685 if (HtCapabilityLen> 0)
3687 pBss->HtCapabilityLen = HtCapabilityLen;
3688 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3689 if (AddHtInfoLen > 0)
3691 pBss->AddHtInfoLen = AddHtInfoLen;
3692 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3694 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3696 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3698 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3700 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3704 #endif // DOT11_N_SUPPORT //
3706 BssCipherParse(pBss);
3710 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3712 pBss->EdcaParm.bValid = FALSE;
3714 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3716 pBss->QosCapability.bValid = FALSE;
3718 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3720 pBss->QbssLoad.bValid = FALSE;
3722 #ifdef CONFIG_STA_SUPPORT
3723 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3729 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3730 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3731 #ifdef EXT_BUILD_CHANNEL_LIST
3732 NdisZeroMemory(&pBss->CountryString[0], 3);
3733 pBss->bHasCountryIE = FALSE;
3734 #endif // EXT_BUILD_CHANNEL_LIST //
3735 pEid = (PEID_STRUCT) pVIE;
3736 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3741 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3743 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3745 pBss->WpaIE.IELen = 0;
3748 pBss->WpaIE.IELen = pEid->Len + 2;
3749 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3753 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3755 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3757 pBss->RsnIE.IELen = 0;
3760 pBss->RsnIE.IELen = pEid->Len + 2;
3761 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3764 #ifdef EXT_BUILD_CHANNEL_LIST
3766 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3767 pBss->bHasCountryIE = TRUE;
3769 #endif // EXT_BUILD_CHANNEL_LIST //
3771 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3772 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3775 #endif // CONFIG_STA_SUPPORT //
3779 * \brief insert an entry into the bss table
3780 * \param p_tab The BSS table
3781 * \param Bssid BSSID
3783 * \param ssid_len Length of SSID
3785 * \param beacon_period
3792 * \param channel_idx
3796 * \note If SSID is identical, the old entry will be replaced by the new one
3798 IRQL = DISPATCH_LEVEL
3801 ULONG BssTableSetEntry(
3802 IN PRTMP_ADAPTER pAd,
3808 IN USHORT BeaconPeriod,
3811 IN USHORT CapabilityInfo,
3813 IN UCHAR SupRateLen,
3815 IN UCHAR ExtRateLen,
3816 IN HT_CAPABILITY_IE *pHtCapability,
3817 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3818 IN UCHAR HtCapabilityLen,
3819 IN UCHAR AddHtInfoLen,
3820 IN UCHAR NewExtChanOffset,
3823 IN LARGE_INTEGER TimeStamp,
3825 IN PEDCA_PARM pEdcaParm,
3826 IN PQOS_CAPABILITY_PARM pQosCapability,
3827 IN PQBSS_LOAD_PARM pQbssLoad,
3828 IN USHORT LengthVIE,
3829 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3833 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3834 if (Idx == BSS_NOT_FOUND)
3836 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3839 // It may happen when BSS Table was full.
3840 // The desired AP will not be added into BSS Table
3841 // In this case, if we found the desired AP then overwrite BSS Table.
3843 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3845 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3846 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3848 Idx = Tab->BssOverlapNr;
3849 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3850 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3851 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3852 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3858 return BSS_NOT_FOUND;
3862 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3863 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3864 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3869 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3870 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3871 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3877 #ifdef CONFIG_STA_SUPPORT
3878 #ifdef DOT11_N_SUPPORT
3879 #ifdef DOT11N_DRAFT3
3881 IN PRTMP_ADAPTER pAd)
3885 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3886 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3888 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3889 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3892 ULONG TriEventTableSetEntry(
3893 IN PRTMP_ADAPTER pAd,
3894 OUT TRIGGER_EVENT_TAB *Tab,
3896 IN HT_CAPABILITY_IE *pHtCapability,
3897 IN UCHAR HtCapabilityLen,
3902 if (HtCapabilityLen == 0)
3904 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3906 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3907 Tab->EventA[Tab->EventANo].bValid = TRUE;
3908 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3909 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3912 // Beacon has Regulatory class IE. So use beacon's
3913 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3917 // Use Station's Regulatory class instead.
3918 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3920 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3922 Tab->EventA[Tab->EventANo].RegClass = 32;
3924 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3925 Tab->EventA[Tab->EventANo].RegClass = 33;
3928 Tab->EventA[Tab->EventANo].RegClass = ??;
3935 else if (pHtCapability->HtCapInfo.Intolerant40)
3937 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3943 ========================================================================
3944 Routine Description:
3945 Trigger Event table Maintainence called once every second.
3948 // IRQL = DISPATCH_LEVEL
3949 ========================================================================
3951 VOID TriEventCounterMaintenance(
3952 IN PRTMP_ADAPTER pAd)
3955 BOOLEAN bNotify = FALSE;
3956 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3958 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3960 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3961 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3963 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3964 pAd->CommonCfg.TriggerEventTab.EventANo --;
3965 // Need to send 20/40 Coexistence Notify frame if has status change.
3970 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
3972 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
3973 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
3977 if (bNotify == TRUE)
3978 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
3980 #endif // DOT11N_DRAFT3 //
3981 #endif // DOT11_N_SUPPORT //
3983 // IRQL = DISPATCH_LEVEL
3984 VOID BssTableSsidSort(
3985 IN PRTMP_ADAPTER pAd,
3986 OUT BSS_TABLE *OutTab,
3991 BssTableInit(OutTab);
3993 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3995 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3996 BOOLEAN bIsHiddenApIncluded = FALSE;
3998 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3999 (pAd->MlmeAux.Channel > 14) &&
4000 RadarChannelCheck(pAd, pInBss->Channel))
4004 bIsHiddenApIncluded = TRUE;
4007 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
4008 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
4010 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4013 #ifdef EXT_BUILD_CHANNEL_LIST
4014 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
4015 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
4016 (pInBss->bHasCountryIE == FALSE))
4018 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
4021 #endif // EXT_BUILD_CHANNEL_LIST //
4023 #ifdef DOT11_N_SUPPORT
4024 // 2.4G/5G N only mode
4025 if ((pInBss->HtCapabilityLen == 0) &&
4026 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4028 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4031 #endif // DOT11_N_SUPPORT //
4034 // Check the Authmode first
4035 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4037 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4038 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4042 // Check cipher suite, AP must have more secured cipher than station setting
4043 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4045 // If it's not mixed mode, we should only let BSS pass with the same encryption
4046 if (pInBss->WPA.bMixMode == FALSE)
4047 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4050 // check group cipher
4051 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4052 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4053 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
4056 // check pairwise cipher, skip if none matched
4057 // If profile set to AES, let it pass without question.
4058 // If profile set to TKIP, we must find one mateched
4059 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4060 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4061 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4064 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4066 // If it's not mixed mode, we should only let BSS pass with the same encryption
4067 if (pInBss->WPA2.bMixMode == FALSE)
4068 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4071 // check group cipher
4072 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4073 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4074 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
4077 // check pairwise cipher, skip if none matched
4078 // If profile set to AES, let it pass without question.
4079 // If profile set to TKIP, we must find one mateched
4080 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4081 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4082 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4086 // Bss Type matched, SSID matched.
4087 // We will check wepstatus for qualification Bss
4088 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4090 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4092 // For the SESv2 case, we will not qualify WepStatus.
4098 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4099 // It definitely will fail. So, skip it.
4100 // CCX also require not even try to connect it!!
4104 #ifdef DOT11_N_SUPPORT
4105 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4106 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4107 if ((pInBss->CentralChannel != pInBss->Channel) &&
4108 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4110 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4112 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4114 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4118 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4124 #endif // DOT11_N_SUPPORT //
4126 // copy matching BSS from InTab to OutTab
4127 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4131 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4133 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4136 #ifdef DOT11_N_SUPPORT
4137 // 2.4G/5G N only mode
4138 if ((pInBss->HtCapabilityLen == 0) &&
4139 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4141 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4144 #endif // DOT11_N_SUPPORT //
4147 // Check the Authmode first
4148 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4150 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4151 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4155 // Check cipher suite, AP must have more secured cipher than station setting
4156 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4158 // If it's not mixed mode, we should only let BSS pass with the same encryption
4159 if (pInBss->WPA.bMixMode == FALSE)
4160 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4163 // check group cipher
4164 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4167 // check pairwise cipher, skip if none matched
4168 // If profile set to AES, let it pass without question.
4169 // If profile set to TKIP, we must find one mateched
4170 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4171 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4172 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4175 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4177 // If it's not mixed mode, we should only let BSS pass with the same encryption
4178 if (pInBss->WPA2.bMixMode == FALSE)
4179 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4182 // check group cipher
4183 if (pAd->StaCfg.WepStatus < pInBss->WPA2.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->WPA2.PairCipher) &&
4191 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4195 // Bss Type matched, SSID matched.
4196 // We will check wepstatus for qualification Bss
4197 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4200 #ifdef DOT11_N_SUPPORT
4201 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4202 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4203 if ((pInBss->CentralChannel != pInBss->Channel) &&
4204 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4206 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4208 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4210 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4213 #endif // DOT11_N_SUPPORT //
4215 // copy matching BSS from InTab to OutTab
4216 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4221 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4225 BssTableSortByRssi(OutTab);
4229 // IRQL = DISPATCH_LEVEL
4230 VOID BssTableSortByRssi(
4231 IN OUT BSS_TABLE *OutTab)
4236 for (i = 0; i < OutTab->BssNr - 1; i++)
4238 for (j = i+1; j < OutTab->BssNr; j++)
4240 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4242 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4243 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4244 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4249 #endif // CONFIG_STA_SUPPORT //
4252 VOID BssCipherParse(
4253 IN OUT PBSS_ENTRY pBss)
4257 PRSN_IE_HEADER_STRUCT pRsnHeader;
4258 PCIPHER_SUITE_STRUCT pCipher;
4259 PAKM_SUITE_STRUCT pAKM;
4262 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4265 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4269 pBss->WepStatus = Ndis802_11WEPEnabled;
4273 pBss->WepStatus = Ndis802_11WEPDisabled;
4275 // Set default to disable & open authentication before parsing variable IE
4276 pBss->AuthMode = Ndis802_11AuthModeOpen;
4277 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4280 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4281 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4282 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4283 pBss->WPA.RsnCapability = 0;
4284 pBss->WPA.bMixMode = FALSE;
4286 // Init WPA2 setting
4287 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4288 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4289 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4290 pBss->WPA2.RsnCapability = 0;
4291 pBss->WPA2.bMixMode = FALSE;
4294 Length = (INT) pBss->VarIELen;
4298 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4299 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4300 pEid = (PEID_STRUCT) pTmp;
4304 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4305 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4311 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4312 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4313 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4314 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4317 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4318 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4319 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4322 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4323 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4324 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4330 // if Cisco IE_WPA, break
4333 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4338 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4340 // if unsupported vendor specific IE
4343 // Skip OUI, version, and multicast suite
4344 // This part should be improved in the future when AP supported multiple cipher suite.
4345 // For now, it's OK since almost all APs have fixed cipher suite supported.
4346 // pTmp = (PUCHAR) pEid->Octet;
4349 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4357 // Parse group cipher
4361 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4364 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4367 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4370 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4375 // number of unicast suite
4378 // skip all unicast cipher suites
4379 //Count = *(PUSHORT) pTmp;
4380 Count = (pTmp[1]<<8) + pTmp[0];
4381 pTmp += sizeof(USHORT);
4383 // Parsing all unicast cipher suite
4388 TmpCipher = Ndis802_11WEPDisabled;
4392 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4393 TmpCipher = Ndis802_11Encryption1Enabled;
4396 TmpCipher = Ndis802_11Encryption2Enabled;
4399 TmpCipher = Ndis802_11Encryption3Enabled;
4404 if (TmpCipher > pBss->WPA.PairCipher)
4406 // Move the lower cipher suite to PairCipherAux
4407 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4408 pBss->WPA.PairCipher = TmpCipher;
4412 pBss->WPA.PairCipherAux = TmpCipher;
4418 // 4. get AKM suite counts
4419 //Count = *(PUSHORT) pTmp;
4420 Count = (pTmp[1]<<8) + pTmp[0];
4421 pTmp += sizeof(USHORT);
4427 // Set AP support WPA mode
4428 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4429 pBss->AuthMode = Ndis802_11AuthModeWPA;
4431 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4434 // Set AP support WPA mode
4435 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4436 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4438 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4445 // Fixed for WPA-None
4446 if (pBss->BssType == BSS_ADHOC)
4448 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4449 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4450 pBss->WepStatus = pBss->WPA.GroupCipher;
4451 // Patched bugs for old driver
4452 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4453 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4456 pBss->WepStatus = pBss->WPA.PairCipher;
4458 // Check the Pair & Group, if different, turn on mixed mode flag
4459 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4460 pBss->WPA.bMixMode = TRUE;
4465 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4467 // 0. Version must be 1
4468 if (le2cpu16(pRsnHeader->Version) != 1)
4470 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4472 // 1. Check group cipher
4473 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4474 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4477 // Parse group cipher
4478 switch (pCipher->Type)
4481 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4484 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4487 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4490 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4495 // set to correct offset for next parsing
4496 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4498 // 2. Get pairwise cipher counts
4499 //Count = *(PUSHORT) pTmp;
4500 Count = (pTmp[1]<<8) + pTmp[0];
4501 pTmp += sizeof(USHORT);
4503 // 3. Get pairwise cipher
4504 // Parsing all unicast cipher suite
4508 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4509 TmpCipher = Ndis802_11WEPDisabled;
4510 switch (pCipher->Type)
4513 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4514 TmpCipher = Ndis802_11Encryption1Enabled;
4517 TmpCipher = Ndis802_11Encryption2Enabled;
4520 TmpCipher = Ndis802_11Encryption3Enabled;
4525 if (TmpCipher > pBss->WPA2.PairCipher)
4527 // Move the lower cipher suite to PairCipherAux
4528 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4529 pBss->WPA2.PairCipher = TmpCipher;
4533 pBss->WPA2.PairCipherAux = TmpCipher;
4535 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4539 // 4. get AKM suite counts
4540 //Count = *(PUSHORT) pTmp;
4541 Count = (pTmp[1]<<8) + pTmp[0];
4542 pTmp += sizeof(USHORT);
4544 // 5. Get AKM ciphers
4545 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4546 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4552 // Set AP support WPA mode
4553 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4554 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4556 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4559 // Set AP support WPA mode
4560 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4561 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4563 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4568 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4570 // Fixed for WPA-None
4571 if (pBss->BssType == BSS_ADHOC)
4573 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4574 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4575 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4576 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4577 pBss->WepStatus = pBss->WPA.GroupCipher;
4578 // Patched bugs for old driver
4579 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4580 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4582 pBss->WepStatus = pBss->WPA2.PairCipher;
4584 // 6. Get RSN capability
4585 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4586 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4587 pTmp += sizeof(USHORT);
4589 // Check the Pair & Group, if different, turn on mixed mode flag
4590 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4591 pBss->WPA2.bMixMode = TRUE;
4597 Length -= (pEid->Len + 2);
4601 // ===========================================================================================
4603 // ===========================================================================================
4605 /*! \brief generates a random mac address value for IBSS BSSID
4606 * \param Addr the bssid location
4611 VOID MacAddrRandomBssid(
4612 IN PRTMP_ADAPTER pAd,
4617 for (i = 0; i < MAC_ADDR_LEN; i++)
4619 pAddr[i] = RandomByte(pAd);
4622 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4625 /*! \brief init the management mac frame header
4626 * \param p_hdr mac header
4627 * \param subtype subtype of the frame
4628 * \param p_ds destination address, don't care if it is a broadcast address
4630 * \pre the station has the following information in the pAd->StaCfg
4634 * \note this function initializes the following field
4636 IRQL = PASSIVE_LEVEL
4637 IRQL = DISPATCH_LEVEL
4640 VOID MgtMacHeaderInit(
4641 IN PRTMP_ADAPTER pAd,
4642 IN OUT PHEADER_802_11 pHdr80211,
4648 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4650 pHdr80211->FC.Type = BTYPE_MGMT;
4651 pHdr80211->FC.SubType = SubType;
4652 pHdr80211->FC.ToDs = ToDs;
4653 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4654 #ifdef CONFIG_STA_SUPPORT
4655 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4656 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4657 #endif // CONFIG_STA_SUPPORT //
4658 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4661 // ===========================================================================================
4663 // ===========================================================================================
4665 /*!***************************************************************************
4666 * This routine build an outgoing frame, and fill all information specified
4667 * in argument list to the frame body. The actual frame size is the summation
4670 * Buffer - pointer to a pre-allocated memory segment
4671 * args - a list of <int arg_size, arg> pairs.
4672 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4673 * function will FAIL!!!
4675 * Size of the buffer
4677 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4679 IRQL = PASSIVE_LEVEL
4680 IRQL = DISPATCH_LEVEL
4682 ****************************************************************************/
4683 ULONG MakeOutgoingFrame(
4685 OUT ULONG *FrameLen, ...)
4692 // calculates the total length
4694 va_start(Args, FrameLen);
4697 leng = va_arg(Args, int);
4698 if (leng == END_OF_ARGS)
4702 p = va_arg(Args, PVOID);
4703 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4704 TotLeng = TotLeng + leng;
4707 va_end(Args); /* clean up */
4708 *FrameLen = TotLeng;
4712 // ===========================================================================================
4714 // ===========================================================================================
4716 /*! \brief Initialize The MLME Queue, used by MLME Functions
4717 * \param *Queue The MLME Queue
4718 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4721 * \note Because this is done only once (at the init stage), no need to be locked
4723 IRQL = PASSIVE_LEVEL
4726 NDIS_STATUS MlmeQueueInit(
4727 IN MLME_QUEUE *Queue)
4731 NdisAllocateSpinLock(&Queue->Lock);
4737 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4739 Queue->Entry[i].Occupied = FALSE;
4740 Queue->Entry[i].MsgLen = 0;
4741 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4744 return NDIS_STATUS_SUCCESS;
4747 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4748 * \param *Queue The MLME Queue
4749 * \param Machine The State Machine Id
4750 * \param MsgType The Message Type
4751 * \param MsgLen The Message length
4752 * \param *Msg The message pointer
4753 * \return TRUE if enqueue is successful, FALSE if the queue is full
4756 * \note The message has to be initialized
4758 IRQL = PASSIVE_LEVEL
4759 IRQL = DISPATCH_LEVEL
4762 BOOLEAN MlmeEnqueue(
4763 IN PRTMP_ADAPTER pAd,
4770 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4772 // Do nothing if the driver is starting halt state.
4773 // This might happen when timer already been fired before cancel timer with mlmehalt
4774 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4777 // First check the size, it MUST not exceed the mlme queue size
4778 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4780 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4784 if (MlmeQueueFull(Queue))
4789 NdisAcquireSpinLock(&(Queue->Lock));
4793 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4798 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4799 Queue->Entry[Tail].Occupied = TRUE;
4800 Queue->Entry[Tail].Machine = Machine;
4801 Queue->Entry[Tail].MsgType = MsgType;
4802 Queue->Entry[Tail].MsgLen = MsgLen;
4806 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4809 NdisReleaseSpinLock(&(Queue->Lock));
4813 /*! \brief This function is used when Recv gets a MLME message
4814 * \param *Queue The MLME Queue
4815 * \param TimeStampHigh The upper 32 bit of timestamp
4816 * \param TimeStampLow The lower 32 bit of timestamp
4817 * \param Rssi The receiving RSSI strength
4818 * \param MsgLen The length of the message
4819 * \param *Msg The message pointer
4820 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4824 IRQL = DISPATCH_LEVEL
4827 BOOLEAN MlmeEnqueueForRecv(
4828 IN PRTMP_ADAPTER pAd,
4830 IN ULONG TimeStampHigh,
4831 IN ULONG TimeStampLow,
4840 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4842 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4844 // Do nothing if the driver is starting halt state.
4845 // This might happen when timer already been fired before cancel timer with mlmehalt
4846 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4848 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4852 // First check the size, it MUST not exceed the mlme queue size
4853 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4855 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4859 if (MlmeQueueFull(Queue))
4864 #ifdef CONFIG_STA_SUPPORT
4865 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4867 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4869 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4873 #endif // CONFIG_STA_SUPPORT //
4875 // OK, we got all the informations, it is time to put things into queue
4876 NdisAcquireSpinLock(&(Queue->Lock));
4880 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4884 Queue->Entry[Tail].Occupied = TRUE;
4885 Queue->Entry[Tail].Machine = Machine;
4886 Queue->Entry[Tail].MsgType = MsgType;
4887 Queue->Entry[Tail].MsgLen = MsgLen;
4888 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4889 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4890 Queue->Entry[Tail].Rssi0 = Rssi0;
4891 Queue->Entry[Tail].Rssi1 = Rssi1;
4892 Queue->Entry[Tail].Rssi2 = Rssi2;
4893 Queue->Entry[Tail].Signal = Signal;
4894 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4896 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4900 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4903 NdisReleaseSpinLock(&(Queue->Lock));
4905 RT28XX_MLME_HANDLER(pAd);
4911 /*! \brief Dequeue a message from the MLME Queue
4912 * \param *Queue The MLME Queue
4913 * \param *Elem The message dequeued from MLME Queue
4914 * \return TRUE if the Elem contains something, FALSE otherwise
4918 IRQL = DISPATCH_LEVEL
4921 BOOLEAN MlmeDequeue(
4922 IN MLME_QUEUE *Queue,
4923 OUT MLME_QUEUE_ELEM **Elem)
4925 NdisAcquireSpinLock(&(Queue->Lock));
4926 *Elem = &(Queue->Entry[Queue->Head]);
4929 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4933 NdisReleaseSpinLock(&(Queue->Lock));
4937 // IRQL = DISPATCH_LEVEL
4938 VOID MlmeRestartStateMachine(
4939 IN PRTMP_ADAPTER pAd)
4941 MLME_QUEUE_ELEM *Elem = NULL;
4942 #ifdef CONFIG_STA_SUPPORT
4944 #endif // CONFIG_STA_SUPPORT //
4946 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4948 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4949 if(pAd->Mlme.bRunning)
4951 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4956 pAd->Mlme.bRunning = TRUE;
4958 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4960 // Remove all Mlme queues elements
4961 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4963 //From message type, determine which state machine I should drive
4964 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4966 // free MLME element
4967 Elem->Occupied = FALSE;
4972 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4976 #ifdef CONFIG_STA_SUPPORT
4977 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4979 #ifdef QOS_DLS_SUPPORT
4981 #endif // QOS_DLS_SUPPORT //
4982 // Cancel all timer events
4983 // Be careful to cancel new added timer
4984 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4985 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4986 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4987 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4988 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4989 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4991 #ifdef QOS_DLS_SUPPORT
4992 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
4994 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
4996 #endif // QOS_DLS_SUPPORT //
4998 #endif // CONFIG_STA_SUPPORT //
5000 // Change back to original channel in case of doing scan
5001 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
5002 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
5004 // Resume MSDU which is turned off durning scan
5005 RTMPResumeMsduTransmission(pAd);
5007 #ifdef CONFIG_STA_SUPPORT
5008 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5010 // Set all state machines back IDLE
5011 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
5012 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
5013 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
5014 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
5015 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
5016 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
5017 #ifdef QOS_DLS_SUPPORT
5018 pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
5019 #endif // QOS_DLS_SUPPORT //
5021 #endif // CONFIG_STA_SUPPORT //
5023 // Remove running state
5024 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
5025 pAd->Mlme.bRunning = FALSE;
5026 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
5029 /*! \brief test if the MLME Queue is empty
5030 * \param *Queue The MLME Queue
5031 * \return TRUE if the Queue is empty, FALSE otherwise
5035 IRQL = DISPATCH_LEVEL
5038 BOOLEAN MlmeQueueEmpty(
5039 IN MLME_QUEUE *Queue)
5043 NdisAcquireSpinLock(&(Queue->Lock));
5044 Ans = (Queue->Num == 0);
5045 NdisReleaseSpinLock(&(Queue->Lock));
5050 /*! \brief test if the MLME Queue is full
5051 * \param *Queue The MLME Queue
5052 * \return TRUE if the Queue is empty, FALSE otherwise
5056 IRQL = PASSIVE_LEVEL
5057 IRQL = DISPATCH_LEVEL
5060 BOOLEAN MlmeQueueFull(
5061 IN MLME_QUEUE *Queue)
5065 NdisAcquireSpinLock(&(Queue->Lock));
5066 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5067 NdisReleaseSpinLock(&(Queue->Lock));
5072 /*! \brief The destructor of MLME Queue
5077 * \note Clear Mlme Queue, Set Queue->Num to Zero.
5079 IRQL = PASSIVE_LEVEL
5082 VOID MlmeQueueDestroy(
5083 IN MLME_QUEUE *pQueue)
5085 NdisAcquireSpinLock(&(pQueue->Lock));
5089 NdisReleaseSpinLock(&(pQueue->Lock));
5090 NdisFreeSpinLock(&(pQueue->Lock));
5093 /*! \brief To substitute the message type if the message is coming from external
5094 * \param pFrame The frame received
5095 * \param *Machine The state machine
5096 * \param *MsgType the message type for the state machine
5097 * \return TRUE if the substitution is successful, FALSE otherwise
5101 IRQL = DISPATCH_LEVEL
5104 #ifdef CONFIG_STA_SUPPORT
5105 BOOLEAN MsgTypeSubst(
5106 IN PRTMP_ADAPTER pAd,
5107 IN PFRAME_802_11 pFrame,
5115 // Pointer to start of data frames including SNAP header
5116 pData = (PUCHAR) pFrame + LENGTH_802_11;
5118 // The only data type will pass to this function is EAPOL frame
5119 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5121 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5123 // Cisco Aironet SNAP header
5124 *Machine = AIRONET_STATE_MACHINE;
5125 *MsgType = MT2_AIRONET_MSG;
5129 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5132 *Machine = LEAP_STATE_MACHINE;
5133 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5134 return (LeapMsgTypeSubst(EAPType, MsgType));
5137 #endif // LEAP_SUPPORT //
5139 *Machine = WPA_PSK_STATE_MACHINE;
5140 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5141 return(WpaMsgTypeSubst(EAPType, MsgType));
5145 switch (pFrame->Hdr.FC.SubType)
5147 case SUBTYPE_ASSOC_REQ:
5148 *Machine = ASSOC_STATE_MACHINE;
5149 *MsgType = MT2_PEER_ASSOC_REQ;
5151 case SUBTYPE_ASSOC_RSP:
5152 *Machine = ASSOC_STATE_MACHINE;
5153 *MsgType = MT2_PEER_ASSOC_RSP;
5155 case SUBTYPE_REASSOC_REQ:
5156 *Machine = ASSOC_STATE_MACHINE;
5157 *MsgType = MT2_PEER_REASSOC_REQ;
5159 case SUBTYPE_REASSOC_RSP:
5160 *Machine = ASSOC_STATE_MACHINE;
5161 *MsgType = MT2_PEER_REASSOC_RSP;
5163 case SUBTYPE_PROBE_REQ:
5164 *Machine = SYNC_STATE_MACHINE;
5165 *MsgType = MT2_PEER_PROBE_REQ;
5167 case SUBTYPE_PROBE_RSP:
5168 *Machine = SYNC_STATE_MACHINE;
5169 *MsgType = MT2_PEER_PROBE_RSP;
5171 case SUBTYPE_BEACON:
5172 *Machine = SYNC_STATE_MACHINE;
5173 *MsgType = MT2_PEER_BEACON;
5176 *Machine = SYNC_STATE_MACHINE;
5177 *MsgType = MT2_PEER_ATIM;
5179 case SUBTYPE_DISASSOC:
5180 *Machine = ASSOC_STATE_MACHINE;
5181 *MsgType = MT2_PEER_DISASSOC_REQ;
5184 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5185 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5186 if (Seq == 1 || Seq == 3)
5188 *Machine = AUTH_RSP_STATE_MACHINE;
5189 *MsgType = MT2_PEER_AUTH_ODD;
5191 else if (Seq == 2 || Seq == 4)
5193 *Machine = AUTH_STATE_MACHINE;
5194 *MsgType = MT2_PEER_AUTH_EVEN;
5201 case SUBTYPE_DEAUTH:
5202 *Machine = AUTH_RSP_STATE_MACHINE;
5203 *MsgType = MT2_PEER_DEAUTH;
5205 case SUBTYPE_ACTION:
5206 *Machine = ACTION_STATE_MACHINE;
5207 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5208 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5210 *MsgType = MT2_ACT_INVALID;
5214 *MsgType = (pFrame->Octet[0]&0x7F);
5224 #endif // CONFIG_STA_SUPPORT //
5226 // ===========================================================================================
5228 // ===========================================================================================
5230 /*! \brief Initialize the state machine.
5231 * \param *S pointer to the state machine
5232 * \param Trans State machine transition function
5233 * \param StNr number of states
5234 * \param MsgNr number of messages
5235 * \param DefFunc default function, when there is invalid state/message combination
5236 * \param InitState initial state of the state machine
5237 * \param Base StateMachine base, internal use only
5238 * \pre p_sm should be a legal pointer
5241 IRQL = PASSIVE_LEVEL
5244 VOID StateMachineInit(
5245 IN STATE_MACHINE *S,
5246 IN STATE_MACHINE_FUNC Trans[],
5249 IN STATE_MACHINE_FUNC DefFunc,
5255 // set number of states and messages
5260 S->TransFunc = Trans;
5262 // init all state transition to default function
5263 for (i = 0; i < StNr; i++)
5265 for (j = 0; j < MsgNr; j++)
5267 S->TransFunc[i * MsgNr + j] = DefFunc;
5271 // set the starting state
5272 S->CurrState = InitState;
5275 /*! \brief This function fills in the function pointer into the cell in the state machine
5276 * \param *S pointer to the state machine
5278 * \param Msg incoming message
5279 * \param f the function to be executed when (state, message) combination occurs at the state machine
5280 * \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
5283 IRQL = PASSIVE_LEVEL
5286 VOID StateMachineSetAction(
5287 IN STATE_MACHINE *S,
5290 IN STATE_MACHINE_FUNC Func)
5294 MsgIdx = Msg - S->Base;
5296 if (St < S->NrState && MsgIdx < S->NrMsg)
5298 // boundary checking before setting the action
5299 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5303 /*! \brief This function does the state transition
5304 * \param *Adapter the NIC adapter pointer
5305 * \param *S the state machine
5306 * \param *Elem the message to be executed
5309 IRQL = DISPATCH_LEVEL
5312 VOID StateMachinePerformAction(
5313 IN PRTMP_ADAPTER pAd,
5314 IN STATE_MACHINE *S,
5315 IN MLME_QUEUE_ELEM *Elem)
5317 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5321 ==========================================================================
5323 The drop function, when machine executes this, the message is simply
5324 ignored. This function does nothing, the message is freed in
5325 StateMachinePerformAction()
5326 ==========================================================================
5329 IN PRTMP_ADAPTER pAd,
5330 IN MLME_QUEUE_ELEM *Elem)
5334 // ===========================================================================================
5336 // ===========================================================================================
5339 ==========================================================================
5342 IRQL = PASSIVE_LEVEL
5344 ==========================================================================
5347 IN PRTMP_ADAPTER pAd,
5351 pAd->Mlme.ShiftReg = 1;
5353 pAd->Mlme.ShiftReg = Seed;
5357 ==========================================================================
5359 ==========================================================================
5362 IN PRTMP_ADAPTER pAd)
5369 if (pAd->Mlme.ShiftReg == 0)
5370 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5372 for (i = 0; i < 8; i++)
5374 if (pAd->Mlme.ShiftReg & 0x00000001)
5376 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5381 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5384 R = (R << 1) | Result;
5390 VOID AsicUpdateAutoFallBackTable(
5391 IN PRTMP_ADAPTER pAd,
5392 IN PUCHAR pRateTable)
5395 HT_FBK_CFG0_STRUC HtCfg0;
5396 HT_FBK_CFG1_STRUC HtCfg1;
5397 LG_FBK_CFG0_STRUC LgCfg0;
5398 LG_FBK_CFG1_STRUC LgCfg1;
5399 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5401 // set to initial value
5402 HtCfg0.word = 0x65432100;
5403 HtCfg1.word = 0xedcba988;
5404 LgCfg0.word = 0xedcba988;
5405 LgCfg1.word = 0x00002100;
5407 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5408 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5410 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5411 switch (pCurrTxRate->Mode)
5417 switch(pCurrTxRate->CurrMCS)
5420 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5423 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5426 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5429 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5432 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5435 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5438 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5441 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5446 #ifdef DOT11_N_SUPPORT
5450 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5452 switch(pCurrTxRate->CurrMCS)
5455 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5458 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5461 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5464 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5467 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5470 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5473 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5476 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5479 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5482 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5485 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5488 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5491 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5494 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5497 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5500 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5503 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5508 #endif // DOT11_N_SUPPORT //
5511 pNextTxRate = pCurrTxRate;
5514 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5515 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5516 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5517 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5521 ========================================================================
5523 Routine Description:
5524 Set MAC register value according operation mode.
5525 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5526 If MM or GF mask is not set, those passing argument doesn't not take effect.
5528 Operation mode meaning:
5529 = 0 : Pure HT, no preotection.
5530 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5531 = 0x10: No Transmission in 40M is protected.
5532 = 0x11: Transmission in both 40M and 20M shall be protected
5534 we should choose not to use GF. But still set correct ASIC registers.
5535 ========================================================================
5537 VOID AsicUpdateProtect(
5538 IN PRTMP_ADAPTER pAd,
5539 IN USHORT OperationMode,
5541 IN BOOLEAN bDisableBGProtect,
5542 IN BOOLEAN bNonGFExist)
5544 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5550 #ifdef DOT11_N_SUPPORT
5551 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5556 if (pAd->BATable.numAsOriginator)
5559 // enable the RTS/CTS to avoid channel collision
5561 SetMask = ALLN_SETPROTECT;
5564 #endif // DOT11_N_SUPPORT //
5566 // Config ASIC RTS threshold register
5567 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5568 MacReg &= 0xFF0000FF;
5570 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5572 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5574 #ifdef DOT11_N_SUPPORT
5575 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5576 #endif // DOT11_N_SUPPORT //
5577 (pAd->CommonCfg.bAggregationCapable == TRUE))
5578 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5580 MacReg |= (0x1000 << 8);
5584 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5588 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5590 // Initial common protection settings
5591 RTMPZeroMemory(Protect, sizeof(Protect));
5594 ProtCfg.field.TxopAllowGF40 = 1;
5595 ProtCfg.field.TxopAllowGF20 = 1;
5596 ProtCfg.field.TxopAllowMM40 = 1;
5597 ProtCfg.field.TxopAllowMM20 = 1;
5598 ProtCfg.field.TxopAllowOfdm = 1;
5599 ProtCfg.field.TxopAllowCck = 1;
5600 ProtCfg.field.RTSThEn = 1;
5601 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5603 // update PHY mode and rate
5604 if (pAd->CommonCfg.Channel > 14)
5605 ProtCfg.field.ProtectRate = 0x4000;
5606 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5608 // Handle legacy(B/G) protection
5609 if (bDisableBGProtect)
5611 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5612 ProtCfg.field.ProtectCtrl = 0;
5613 Protect[0] = ProtCfg.word;
5614 Protect[1] = ProtCfg.word;
5618 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5619 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5620 Protect[0] = ProtCfg.word;
5621 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5622 Protect[1] = ProtCfg.word;
5625 #ifdef DOT11_N_SUPPORT
5626 // Decide HT frame protection.
5627 if ((SetMask & ALLN_SETPROTECT) != 0)
5629 switch(OperationMode)
5633 // 1.All STAs in the BSS are 20/40 MHz HT
5634 // 2. in ai 20/40MHz BSS
5635 // 3. all STAs are 20MHz in a 20MHz BSS
5636 // Pure HT. no protection.
5640 // PROT_TXOP(25:20) -- 010111
5641 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5642 // PROT_CTRL(17:16) -- 00 (None)
5643 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5644 Protect[2] = 0x01744004;
5648 // PROT_TXOP(25:20) -- 111111
5649 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5650 // PROT_CTRL(17:16) -- 00 (None)
5651 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5652 Protect[3] = 0x03f44084;
5656 // PROT_TXOP(25:20) -- 010111
5657 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5658 // PROT_CTRL(17:16) -- 00 (None)
5659 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5660 Protect[4] = 0x01744004;
5664 // PROT_TXOP(25:20) -- 111111
5665 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5666 // PROT_CTRL(17:16) -- 00 (None)
5667 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5668 Protect[5] = 0x03f44084;
5672 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5673 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5674 Protect[4] = 0x01754004;
5675 Protect[5] = 0x03f54084;
5677 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5681 // This is "HT non-member protection mode."
5682 // If there may be non-HT STAs my BSS
5683 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5684 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5685 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5687 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5688 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5690 //Assign Protection method for 20&40 MHz packets
5691 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5692 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5693 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5694 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5695 Protect[2] = ProtCfg.word;
5696 Protect[3] = ProtCfg4.word;
5697 Protect[4] = ProtCfg.word;
5698 Protect[5] = ProtCfg4.word;
5699 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5703 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5704 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5705 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5707 //Assign Protection method for 40MHz packets
5708 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5709 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5710 Protect[2] = ProtCfg.word;
5711 Protect[3] = ProtCfg4.word;
5714 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5715 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5717 Protect[4] = ProtCfg.word;
5718 Protect[5] = ProtCfg4.word;
5720 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5724 // HT mixed mode. PROTECT ALL!
5726 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5727 ProtCfg4.word = 0x03f44084;
5728 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5729 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5731 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5732 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5734 //Assign Protection method for 20&40 MHz packets
5735 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5736 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5737 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5738 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5739 Protect[2] = ProtCfg.word;
5740 Protect[3] = ProtCfg4.word;
5741 Protect[4] = ProtCfg.word;
5742 Protect[5] = ProtCfg4.word;
5743 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5747 // Special on for Atheros problem n chip.
5748 Protect[2] = 0x01754004;
5749 Protect[3] = 0x03f54084;
5750 Protect[4] = 0x01754004;
5751 Protect[5] = 0x03f54084;
5752 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5756 #endif // DOT11_N_SUPPORT //
5758 offset = CCK_PROT_CFG;
5759 for (i = 0;i < 6;i++)
5761 if ((SetMask & (1<< i)))
5763 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5769 ==========================================================================
5772 IRQL = PASSIVE_LEVEL
5773 IRQL = DISPATCH_LEVEL
5775 ==========================================================================
5777 VOID AsicSwitchChannel(
5778 IN PRTMP_ADAPTER pAd,
5782 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5783 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5785 UINT32 Value = 0; //BbpReg, Value;
5786 RTMP_RF_REGS *RFRegTable;
5788 // Search Tx power value
5789 for (index = 0; index < pAd->ChannelListNum; index++)
5791 if (Channel == pAd->ChannelList[index].Channel)
5793 TxPwer = pAd->ChannelList[index].Power;
5794 TxPwer2 = pAd->ChannelList[index].Power2;
5799 if (index == MAX_NUM_OF_CHANNELS)
5801 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5805 RFRegTable = RF2850RegTable;
5807 switch (pAd->RfIcType)
5814 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5816 if (Channel == RFRegTable[index].Channel)
5818 R2 = RFRegTable[index].R2;
5819 if (pAd->Antenna.field.TxPath == 1)
5821 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5824 if (pAd->Antenna.field.RxPath == 2)
5826 R2 |= 0x40; // write 1 to off Rxpath.
5828 else if (pAd->Antenna.field.RxPath == 1)
5830 R2 |= 0x20040; // write 1 to off RxPath
5835 // initialize R3, R4
5836 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5837 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5839 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5841 if ((TxPwer >= -7) && (TxPwer < 0))
5843 TxPwer = (7+TxPwer);
5844 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5845 R3 |= (TxPwer << 10);
5846 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5850 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5851 R3 |= (TxPwer << 10) | (1 << 9);
5855 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5857 TxPwer2 = (7+TxPwer2);
5858 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5859 R4 |= (TxPwer2 << 7);
5860 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5864 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5865 R4 |= (TxPwer2 << 7) | (1 << 6);
5870 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5871 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5874 // Based on BBP current mode before changing RF channel.
5875 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5881 pAd->LatchRfRegs.Channel = Channel;
5882 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5883 pAd->LatchRfRegs.R2 = R2;
5884 pAd->LatchRfRegs.R3 = R3;
5885 pAd->LatchRfRegs.R4 = R4;
5887 // Set RF value 1's set R3[bit2] = [0]
5888 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5889 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5890 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5891 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5895 // Set RF value 2's set R3[bit2] = [1]
5896 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5897 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5898 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5899 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5903 // Set RF value 3's set R3[bit2] = [0]
5904 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5905 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5906 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5907 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5919 // Change BBP setting during siwtch from a->g, g->a
5922 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5924 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5925 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5926 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5927 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.
5928 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5930 // Rx High power VGA offset for LNA select
5931 if (pAd->NicConfig2.field.ExternalLNAForG)
5933 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5934 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5938 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5939 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5942 // 5G band selection PIN, bit1 and bit2 are complement
5943 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5946 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5948 // Turn off unused PA or LNA when only 1T or 1R
5949 if (pAd->Antenna.field.TxPath == 1)
5951 TxPinCfg &= 0xFFFFFFF3;
5953 if (pAd->Antenna.field.RxPath == 1)
5955 TxPinCfg &= 0xFFFFF3FF;
5958 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5962 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5964 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5965 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5966 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5967 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.
5968 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5970 // Rx High power VGA offset for LNA select
5971 if (pAd->NicConfig2.field.ExternalLNAForA)
5973 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5977 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5980 // 5G band selection PIN, bit1 and bit2 are complement
5981 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5984 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5986 // Turn off unused PA or LNA when only 1T or 1R
5987 if (pAd->Antenna.field.TxPath == 1)
5989 TxPinCfg &= 0xFFFFFFF3;
5991 if (pAd->Antenna.field.RxPath == 1)
5993 TxPinCfg &= 0xFFFFF3FF;
5996 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5999 // R66 should be set according to Channel and use 20MHz when scanning
6000 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6002 RTMPSetAGCInitValue(pAd, BW_20);
6004 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6007 // On 11A, We should delay and wait RF/BBP to be stable
6008 // and the appropriate time should be 1000 micro seconds
6009 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6011 RTMPusecDelay(1000);
6013 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",
6016 (R3 & 0x00003e00) >> 9,
6017 (R4 & 0x000007c0) >> 6,
6018 pAd->Antenna.field.TxPath,
6019 pAd->LatchRfRegs.R1,
6020 pAd->LatchRfRegs.R2,
6021 pAd->LatchRfRegs.R3,
6022 pAd->LatchRfRegs.R4));
6026 ==========================================================================
6028 This function is required for 2421 only, and should not be used during
6029 site survey. It's only required after NIC decided to stay at a channel
6030 for a longer period.
6031 When this function is called, it's always after AsicSwitchChannel().
6033 IRQL = PASSIVE_LEVEL
6034 IRQL = DISPATCH_LEVEL
6036 ==========================================================================
6038 VOID AsicLockChannel(
6039 IN PRTMP_ADAPTER pAd,
6045 ==========================================================================
6048 IRQL = PASSIVE_LEVEL
6049 IRQL = DISPATCH_LEVEL
6051 ==========================================================================
6053 VOID AsicAntennaSelect(
6054 IN PRTMP_ADAPTER pAd,
6060 ========================================================================
6062 Routine Description:
6063 Antenna miscellaneous setting.
6066 pAd Pointer to our adapter
6067 BandState Indicate current Band State.
6072 IRQL <= DISPATCH_LEVEL
6075 1.) Frame End type control
6076 only valid for G only (RF_2527 & RF_2529)
6077 0: means DPDT, set BBP R4 bit 5 to 1
6078 1: means SPDT, set BBP R4 bit 5 to 0
6081 ========================================================================
6083 VOID AsicAntennaSetting(
6084 IN PRTMP_ADAPTER pAd,
6085 IN ABGBAND_STATE BandState)
6089 VOID AsicRfTuningExec(
6090 IN PVOID SystemSpecific1,
6091 IN PVOID FunctionContext,
6092 IN PVOID SystemSpecific2,
6093 IN PVOID SystemSpecific3)
6098 ==========================================================================
6100 Gives CCK TX rate 2 more dB TX power.
6101 This routine works only in LINK UP in INFRASTRUCTURE mode.
6103 calculate desired Tx power in RF R3.Tx0~5, should consider -
6104 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6105 1. TxPowerPercentage
6106 2. auto calibration based on TSSI feedback
6107 3. extra 2 db for CCK
6108 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6110 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6111 it should be called AFTER MlmeDynamicTxRatSwitching()
6112 ==========================================================================
6114 VOID AsicAdjustTxPower(
6115 IN PRTMP_ADAPTER pAd)
6119 BOOLEAN bAutoTxAgc = FALSE;
6120 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6121 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6122 PCHAR pTxAgcCompensate;
6126 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
6127 || (pAd->bPCIclkOff == TRUE)
6128 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
6129 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
6132 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6134 if (pAd->CommonCfg.CentralChannel > 14)
6136 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6137 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6138 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6139 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6140 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6144 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6145 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6146 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6147 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6148 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6153 if (pAd->CommonCfg.Channel > 14)
6155 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6156 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6157 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6158 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6159 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6163 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6164 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6165 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6166 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6167 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6171 // TX power compensation for temperature variation based on TSSI. try every 4 second
6172 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6174 if (pAd->CommonCfg.Channel <= 14)
6177 bAutoTxAgc = pAd->bAutoTxAgcG;
6178 TssiRef = pAd->TssiRefG;
6179 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6180 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6181 TxAgcStep = pAd->TxAgcStepG;
6182 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6187 bAutoTxAgc = pAd->bAutoTxAgcA;
6188 TssiRef = pAd->TssiRefA;
6189 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6190 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6191 TxAgcStep = pAd->TxAgcStepA;
6192 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6197 /* BbpR1 is unsigned char */
6198 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6200 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6201 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6202 /* step value is defined in pAd->TxAgcStepG for tx power value */
6204 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6205 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6206 above value are examined in mass factory production */
6207 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6209 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6210 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6211 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6213 if (BbpR49 > pTssiMinusBoundary[1])
6215 // Reading is larger than the reference value
6216 // check for how large we need to decrease the Tx power
6217 for (idx = 1; idx < 5; idx++)
6219 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6222 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6223 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6225 DeltaPwr += (*pTxAgcCompensate);
6226 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6227 BbpR49, TssiRef, TxAgcStep, idx-1));
6229 else if (BbpR49 < pTssiPlusBoundary[1])
6231 // Reading is smaller than the reference value
6232 // check for how large we need to increase the Tx power
6233 for (idx = 1; idx < 5; idx++)
6235 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6238 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6239 *pTxAgcCompensate = TxAgcStep * (idx-1);
6240 DeltaPwr += (*pTxAgcCompensate);
6241 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6242 BbpR49, TssiRef, TxAgcStep, idx-1));
6246 *pTxAgcCompensate = 0;
6247 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6248 BbpR49, TssiRef, TxAgcStep, 0));
6254 if (pAd->CommonCfg.Channel <= 14)
6256 bAutoTxAgc = pAd->bAutoTxAgcG;
6257 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6261 bAutoTxAgc = pAd->bAutoTxAgcA;
6262 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6266 DeltaPwr += (*pTxAgcCompensate);
6269 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6273 // Handle regulatory max tx power constrain
6276 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6277 UCHAR AdjustMaxTxPwr[40];
6279 if (pAd->CommonCfg.Channel > 14) // 5G band
6280 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6282 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6283 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6285 // error handling, range check
6286 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6288 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6292 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6294 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6296 // Adjust max tx power according to the relationship of tx power in E2PROM
6299 // CCK will have 4dBm larger than OFDM
6300 // Therefore, we should separate to parse the tx power field
6305 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6309 // CCK will have 4dBm larger than OFDM
6310 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6314 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6316 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6323 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6325 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6326 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6331 // Adjust tx power according to the relationship
6334 if (TxPwr[i] != 0xffffffff)
6338 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6340 // The system tx power is larger than the regulatory, the power should be restrain
6341 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6343 // decrease to zero and don't need to take care BBPR1
6344 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6345 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6349 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6352 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6354 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6359 #endif // SINGLE_SKU //
6361 /* calculate delta power based on the percentage specified from UI */
6362 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6363 // We lower TX power here according to the percentage specified from UI
6364 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6366 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6368 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6372 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6376 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6380 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6385 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6390 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6392 /* reset different new tx power for different TX rate */
6395 if (TxPwr[i] != 0xffffffff)
6399 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6401 if ((Value + DeltaPwr) < 0)
6403 Value = 0; /* min */
6405 else if ((Value + DeltaPwr) > 0xF)
6407 Value = 0xF; /* max */
6411 Value += DeltaPwr; /* temperature compensation */
6414 /* fill new value to CSR offset */
6415 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6418 /* write tx power value to CSR */
6419 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6420 TX power for OFDM 6M/9M
6421 TX power for CCK5.5M/11M
6422 TX power for CCK1M/2M */
6423 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6424 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6430 #ifdef CONFIG_STA_SUPPORT
6432 ==========================================================================
6434 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6435 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6436 the wakeup timer timeout. Driver has to issue a separate command to wake
6439 IRQL = DISPATCH_LEVEL
6441 ==========================================================================
6443 VOID AsicSleepThenAutoWakeup(
6444 IN PRTMP_ADAPTER pAd,
6445 IN USHORT TbttNumToNextWakeUp)
6447 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6451 ==========================================================================
6453 AsicForceWakeup() is used whenever manual wakeup is required
6454 AsicForceSleep() should only be used when not in INFRA BSS. When
6455 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6456 ==========================================================================
6458 VOID AsicForceSleep(
6459 IN PRTMP_ADAPTER pAd)
6465 ==========================================================================
6467 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6470 IRQL = PASSIVE_LEVEL
6471 IRQL = DISPATCH_LEVEL
6472 ==========================================================================
6474 VOID AsicForceWakeup(
6475 IN PRTMP_ADAPTER pAd,
6478 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6479 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6481 #endif // CONFIG_STA_SUPPORT //
6483 ==========================================================================
6487 IRQL = DISPATCH_LEVEL
6489 ==========================================================================
6492 IN PRTMP_ADAPTER pAd,
6496 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6497 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6499 Addr4 = (ULONG)(pBssid[0]) |
6500 (ULONG)(pBssid[1] << 8) |
6501 (ULONG)(pBssid[2] << 16) |
6502 (ULONG)(pBssid[3] << 24);
6503 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6506 // always one BSSID in STA mode
6507 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6509 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6512 VOID AsicSetMcastWC(
6513 IN PRTMP_ADAPTER pAd)
6515 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6518 pEntry->Sst = SST_ASSOC;
6519 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6520 pEntry->PsMode = PWR_ACTIVE;
6521 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6522 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6526 ==========================================================================
6529 IRQL = DISPATCH_LEVEL
6531 ==========================================================================
6533 VOID AsicDelWcidTab(
6534 IN PRTMP_ADAPTER pAd,
6537 ULONG Addr0 = 0x0, Addr1 = 0x0;
6540 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6541 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6542 RTMP_IO_WRITE32(pAd, offset, Addr0);
6544 RTMP_IO_WRITE32(pAd, offset, Addr1);
6548 ==========================================================================
6551 IRQL = DISPATCH_LEVEL
6553 ==========================================================================
6556 IN PRTMP_ADAPTER pAd)
6558 TX_LINK_CFG_STRUC TxLinkCfg;
6561 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6562 TxLinkCfg.field.TxRDGEn = 1;
6563 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6565 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6568 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6570 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6574 ==========================================================================
6577 IRQL = DISPATCH_LEVEL
6579 ==========================================================================
6581 VOID AsicDisableRDG(
6582 IN PRTMP_ADAPTER pAd)
6584 TX_LINK_CFG_STRUC TxLinkCfg;
6588 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6589 TxLinkCfg.field.TxRDGEn = 0;
6590 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6592 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6595 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6596 #ifdef DOT11_N_SUPPORT
6597 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6598 #endif // DOT11_N_SUPPORT //
6601 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6602 if (pAd->CommonCfg.bEnableTxBurst)
6605 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6609 ==========================================================================
6612 IRQL = PASSIVE_LEVEL
6613 IRQL = DISPATCH_LEVEL
6615 ==========================================================================
6617 VOID AsicDisableSync(
6618 IN PRTMP_ADAPTER pAd)
6620 BCN_TIME_CFG_STRUC csr;
6622 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6624 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6625 // that NIC will never wakes up because TSF stops and no more
6627 pAd->TbttTickCount = 0;
6628 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6629 csr.field.bBeaconGen = 0;
6630 csr.field.bTBTTEnable = 0;
6631 csr.field.TsfSyncMode = 0;
6632 csr.field.bTsfTicking = 0;
6633 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6638 ==========================================================================
6641 IRQL = DISPATCH_LEVEL
6643 ==========================================================================
6645 VOID AsicEnableBssSync(
6646 IN PRTMP_ADAPTER pAd)
6648 BCN_TIME_CFG_STRUC csr;
6650 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6652 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6653 #ifdef CONFIG_STA_SUPPORT
6654 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6656 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6657 csr.field.bTsfTicking = 1;
6658 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6659 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6660 csr.field.bTBTTEnable = 1;
6662 #endif // CONFIG_STA_SUPPORT //
6663 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6667 ==========================================================================
6670 BEACON frame in shared memory should be built ok before this routine
6671 can be called. Otherwise, a garbage frame maybe transmitted out every
6674 IRQL = DISPATCH_LEVEL
6676 ==========================================================================
6678 VOID AsicEnableIbssSync(
6679 IN PRTMP_ADAPTER pAd)
6681 BCN_TIME_CFG_STRUC csr9;
6685 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6687 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6688 csr9.field.bBeaconGen = 0;
6689 csr9.field.bTBTTEnable = 0;
6690 csr9.field.bTsfTicking = 0;
6691 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6693 // move BEACON TXD and frame content to on-chip memory
6694 ptr = (PUCHAR)&pAd->BeaconTxWI;
6695 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6697 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6698 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6702 // start right after the 16-byte TXWI field
6703 ptr = pAd->BeaconBuf;
6704 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6706 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6707 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6711 // start sending BEACON
6712 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6713 csr9.field.bTsfTicking = 1;
6714 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6715 csr9.field.bTBTTEnable = 1;
6716 csr9.field.bBeaconGen = 1;
6717 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6721 ==========================================================================
6724 IRQL = PASSIVE_LEVEL
6725 IRQL = DISPATCH_LEVEL
6727 ==========================================================================
6729 VOID AsicSetEdcaParm(
6730 IN PRTMP_ADAPTER pAd,
6731 IN PEDCA_PARM pEdcaParm)
6733 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6734 AC_TXOP_CSR0_STRUC csr0;
6735 AC_TXOP_CSR1_STRUC csr1;
6736 AIFSN_CSR_STRUC AifsnCsr;
6737 CWMIN_CSR_STRUC CwminCsr;
6738 CWMAX_CSR_STRUC CwmaxCsr;
6745 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6747 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6748 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6749 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6751 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6752 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6755 //========================================================
6756 // MAC Register has a copy .
6757 //========================================================
6758 if( pAd->CommonCfg.bEnableTxBurst )
6760 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6761 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6764 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6765 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6766 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6767 Ac0Cfg.field.Aifsn = 2;
6768 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6770 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6771 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6772 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6773 Ac1Cfg.field.Aifsn = 2;
6774 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6776 if (pAd->CommonCfg.PhyMode == PHY_11B)
6778 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6779 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6783 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6784 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6786 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6787 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6788 Ac2Cfg.field.Aifsn = 2;
6789 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6790 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6791 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6792 Ac3Cfg.field.Aifsn = 2;
6793 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6795 //========================================================
6796 // DMA Register has a copy too.
6797 //========================================================
6798 csr0.field.Ac0Txop = 0; // QID_AC_BE
6799 csr0.field.Ac1Txop = 0; // QID_AC_BK
6800 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6801 if (pAd->CommonCfg.PhyMode == PHY_11B)
6803 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6804 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6808 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6809 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6811 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6814 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6815 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6816 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6817 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6818 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6821 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6822 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6823 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6824 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6825 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6827 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6829 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6833 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6834 //========================================================
6835 // MAC Register has a copy.
6836 //========================================================
6838 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6839 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6841 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6843 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6844 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6845 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6846 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6848 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6849 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6850 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6851 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6853 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6854 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6855 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6856 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6857 #ifdef CONFIG_STA_SUPPORT
6858 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6860 // Tuning for Wi-Fi WMM S06
6861 if (pAd->CommonCfg.bWiFiTest &&
6862 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6863 Ac2Cfg.field.Aifsn -= 1;
6865 // Tuning for TGn Wi-Fi 5.2.32
6866 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6867 if (STA_TGN_WIFI_ON(pAd) &&
6868 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6870 Ac0Cfg.field.Aifsn = 3;
6871 Ac2Cfg.field.AcTxop = 5;
6874 #endif // CONFIG_STA_SUPPORT //
6876 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6877 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6878 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6879 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6882 if (pAd->CommonCfg.bWiFiTest)
6884 if (Ac3Cfg.field.AcTxop == 102)
6886 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6887 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6888 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6889 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6890 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6893 //#endif // WIFI_TEST //
6895 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6896 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6897 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6898 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6901 //========================================================
6902 // DMA Register has a copy too.
6903 //========================================================
6904 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6905 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6906 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6908 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6909 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6910 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6913 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6914 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6915 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6916 #ifdef CONFIG_STA_SUPPORT
6917 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6918 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6919 #endif // CONFIG_STA_SUPPORT //
6920 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6923 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6924 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6925 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6926 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6927 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6930 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6931 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6932 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6933 #ifdef CONFIG_STA_SUPPORT
6934 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6936 // Tuning for Wi-Fi WMM S06
6937 if (pAd->CommonCfg.bWiFiTest &&
6938 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6939 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6941 // Tuning for TGn Wi-Fi 5.2.32
6942 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6943 if (STA_TGN_WIFI_ON(pAd) &&
6944 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6946 AifsnCsr.field.Aifsn0 = 3;
6947 AifsnCsr.field.Aifsn2 = 7;
6950 #endif // CONFIG_STA_SUPPORT //
6952 #ifdef CONFIG_STA_SUPPORT
6953 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6954 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6955 #endif // CONFIG_STA_SUPPORT //
6956 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6958 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6961 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6962 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6963 pEdcaParm->Aifsn[0],
6964 pEdcaParm->Cwmin[0],
6965 pEdcaParm->Cwmax[0],
6966 pEdcaParm->Txop[0]<<5,
6967 pEdcaParm->bACM[0]));
6968 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6969 pEdcaParm->Aifsn[1],
6970 pEdcaParm->Cwmin[1],
6971 pEdcaParm->Cwmax[1],
6972 pEdcaParm->Txop[1]<<5,
6973 pEdcaParm->bACM[1]));
6974 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6975 pEdcaParm->Aifsn[2],
6976 pEdcaParm->Cwmin[2],
6977 pEdcaParm->Cwmax[2],
6978 pEdcaParm->Txop[2]<<5,
6979 pEdcaParm->bACM[2]));
6980 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6981 pEdcaParm->Aifsn[3],
6982 pEdcaParm->Cwmin[3],
6983 pEdcaParm->Cwmax[3],
6984 pEdcaParm->Txop[3]<<5,
6985 pEdcaParm->bACM[3]));
6991 ==========================================================================
6994 IRQL = PASSIVE_LEVEL
6995 IRQL = DISPATCH_LEVEL
6997 ==========================================================================
6999 VOID AsicSetSlotTime(
7000 IN PRTMP_ADAPTER pAd,
7001 IN BOOLEAN bUseShortSlotTime)
7004 UINT32 RegValue = 0;
7006 #ifdef CONFIG_STA_SUPPORT
7007 if (pAd->CommonCfg.Channel > 14)
7008 bUseShortSlotTime = TRUE;
7009 #endif // CONFIG_STA_SUPPORT //
7011 if (bUseShortSlotTime)
7012 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7014 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7016 SlotTime = (bUseShortSlotTime)? 9 : 20;
7018 #ifdef CONFIG_STA_SUPPORT
7019 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7021 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7022 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7023 #ifdef DOT11_N_SUPPORT
7024 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7025 #endif // DOT11_N_SUPPORT //
7028 // In this case, we will think it is doing Wi-Fi test
7029 // And we will not set to short slot when bEnableTxBurst is TRUE.
7031 else if (pAd->CommonCfg.bEnableTxBurst)
7034 #endif // CONFIG_STA_SUPPORT //
7037 // For some reasons, always set it to short slot time.
7039 // ToDo: Should consider capability with 11B
7041 #ifdef CONFIG_STA_SUPPORT
7042 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7044 if (pAd->StaCfg.BssType == BSS_ADHOC)
7047 #endif // CONFIG_STA_SUPPORT //
7049 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7050 RegValue = RegValue & 0xFFFFFF00;
7052 RegValue |= SlotTime;
7054 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7058 ========================================================================
7060 Add Shared key information into ASIC.
7061 Update shared key, TxMic and RxMic to Asic Shared key table
7062 Update its cipherAlg to Asic Shared key Mode.
7065 ========================================================================
7067 VOID AsicAddSharedKeyEntry(
7068 IN PRTMP_ADAPTER pAd,
7076 ULONG offset; //, csr0;
7077 SHAREDKEY_MODE_STRUC csr1;
7080 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7081 //============================================================================================
7083 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7084 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7085 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]));
7088 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7089 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7093 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7094 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7096 //============================================================================================
7098 // fill key material - key + TX MIC + RX MIC
7100 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7101 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
7103 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7106 offset += MAX_LEN_OF_SHARE_KEY;
7111 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7120 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7126 // Update cipher algorithm. WSTA always use BSS0
7128 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7129 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7130 if ((BssIndex%2) == 0)
7133 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7134 else if (KeyIdx == 1)
7135 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7136 else if (KeyIdx == 2)
7137 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7139 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7144 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7145 else if (KeyIdx == 1)
7146 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7147 else if (KeyIdx == 2)
7148 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7150 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7152 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7153 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7157 // IRQL = DISPATCH_LEVEL
7158 VOID AsicRemoveSharedKeyEntry(
7159 IN PRTMP_ADAPTER pAd,
7164 SHAREDKEY_MODE_STRUC csr1;
7166 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7168 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7169 if ((BssIndex%2) == 0)
7172 csr1.field.Bss0Key0CipherAlg = 0;
7173 else if (KeyIdx == 1)
7174 csr1.field.Bss0Key1CipherAlg = 0;
7175 else if (KeyIdx == 2)
7176 csr1.field.Bss0Key2CipherAlg = 0;
7178 csr1.field.Bss0Key3CipherAlg = 0;
7183 csr1.field.Bss1Key0CipherAlg = 0;
7184 else if (KeyIdx == 1)
7185 csr1.field.Bss1Key1CipherAlg = 0;
7186 else if (KeyIdx == 2)
7187 csr1.field.Bss1Key2CipherAlg = 0;
7189 csr1.field.Bss1Key3CipherAlg = 0;
7191 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7192 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7193 ASSERT(BssIndex < 4);
7199 VOID AsicUpdateWCIDAttribute(
7200 IN PRTMP_ADAPTER pAd,
7204 IN BOOLEAN bUsePairewiseKeyTable)
7206 ULONG WCIDAttri = 0, offset;
7209 // Update WCID attribute.
7210 // Only TxKey could update WCID attribute.
7212 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7213 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7214 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7217 VOID AsicUpdateWCIDIVEIV(
7218 IN PRTMP_ADAPTER pAd,
7225 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7227 RTMP_IO_WRITE32(pAd, offset, uIV);
7228 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7231 VOID AsicUpdateRxWCIDTable(
7232 IN PRTMP_ADAPTER pAd,
7239 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7240 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7241 RTMP_IO_WRITE32(pAd, offset, Addr);
7242 Addr = pAddr[4] + (pAddr[5] << 8);
7243 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7248 ========================================================================
7250 Routine Description:
7251 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7254 pAd Pointer to our adapter
7255 WCID WCID Entry number.
7256 BssIndex BSSID index, station or none multiple BSSID support
7257 this value should be 0.
7258 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7259 pCipherKey Pointer to Cipher Key.
7260 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7261 otherwise PairewiseKey table
7262 bTxKey This is the transmit key if enabled.
7268 This routine will set the relative key stuff to Asic including WCID attribute,
7269 Cipher Key, Cipher algorithm and IV/EIV.
7271 IV/EIV will be update if this CipherKey is the transmission key because
7272 ASIC will base on IV's KeyID value to select Cipher Key.
7274 If bTxKey sets to FALSE, this is not the TX key, but it could be
7277 For AP mode bTxKey must be always set to TRUE.
7278 ========================================================================
7280 VOID AsicAddKeyEntry(
7281 IN PRTMP_ADAPTER pAd,
7285 IN PCIPHER_KEY pCipherKey,
7286 IN BOOLEAN bUsePairewiseKeyTable,
7291 PUCHAR pKey = pCipherKey->Key;
7292 PUCHAR pTxMic = pCipherKey->TxMic;
7293 PUCHAR pRxMic = pCipherKey->RxMic;
7294 PUCHAR pTxtsc = pCipherKey->TxTsc;
7295 UCHAR CipherAlg = pCipherKey->CipherAlg;
7296 SHAREDKEY_MODE_STRUC csr1;
7299 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7301 // 1.) decide key table offset
7303 if (bUsePairewiseKeyTable)
7304 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7306 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7309 // 2.) Set Key to Asic
7311 //for (i = 0; i < KeyLen; i++)
7312 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
7314 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7316 offset += MAX_LEN_OF_PEER_KEY;
7319 // 3.) Set MIC key if available
7323 for (i = 0; i < 8; i++)
7325 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
7328 offset += LEN_TKIP_TXMICK;
7332 for (i = 0; i < 8; i++)
7334 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
7340 // 4.) Modify IV/EIV if needs
7341 // This will force Asic to use this key ID by setting IV.
7345 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7349 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
7350 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
7351 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
7353 IV4 = (KeyIdx << 6);
7354 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7355 IV4 |= 0x20; // turn on extension bit means EIV existence
7357 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
7363 for (i = 0; i < 4; i++)
7365 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7368 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7371 if (!bUsePairewiseKeyTable)
7374 // Only update the shared key security mode
7376 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7377 if ((BssIndex % 2) == 0)
7380 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7381 else if (KeyIdx == 1)
7382 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7383 else if (KeyIdx == 2)
7384 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7386 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7391 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7392 else if (KeyIdx == 1)
7393 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7394 else if (KeyIdx == 2)
7395 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7397 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7399 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7402 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7407 ========================================================================
7409 Add Pair-wise key material into ASIC.
7410 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7413 ========================================================================
7415 VOID AsicAddPairwiseKeyEntry(
7416 IN PRTMP_ADAPTER pAd,
7419 IN CIPHER_KEY *pCipherKey)
7423 PUCHAR pKey = pCipherKey->Key;
7424 PUCHAR pTxMic = pCipherKey->TxMic;
7425 PUCHAR pRxMic = pCipherKey->RxMic;
7427 UCHAR CipherAlg = pCipherKey->CipherAlg;
7431 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7432 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7434 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7436 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7439 RTMP_IO_READ32(pAd, offset + i, &Value);
7442 offset += MAX_LEN_OF_PEER_KEY;
7449 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7457 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7461 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7462 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7463 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]));
7466 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7467 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7471 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7472 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7476 ========================================================================
7478 Remove Pair-wise key material from ASIC.
7481 ========================================================================
7483 VOID AsicRemovePairwiseKeyEntry(
7484 IN PRTMP_ADAPTER pAd,
7491 // re-set the entry's WCID attribute as OPEN-NONE.
7492 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7493 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7494 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7497 BOOLEAN AsicSendCommandToMcu(
7498 IN PRTMP_ADAPTER pAd,
7504 HOST_CMD_CSR_STRUC H2MCmd;
7505 H2M_MAILBOX_STRUC H2MMailbox;
7510 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7511 if (H2MMailbox.field.Owner == 0)
7523 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7525 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7527 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7528 // Reset DMA/CPU ring index
7529 RTMPRingCleanUp(pAd, QID_AC_BK);
7530 RTMPRingCleanUp(pAd, QID_AC_BE);
7531 RTMPRingCleanUp(pAd, QID_AC_VI);
7532 RTMPRingCleanUp(pAd, QID_AC_VO);
7533 RTMPRingCleanUp(pAd, QID_HCCA);
7534 RTMPRingCleanUp(pAd, QID_MGMT);
7535 RTMPRingCleanUp(pAd, QID_RX);
7538 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7540 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7541 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7546 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7547 H2MMailbox.field.CmdToken = Token;
7548 H2MMailbox.field.HighByte = Arg1;
7549 H2MMailbox.field.LowByte = Arg0;
7550 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7553 H2MCmd.field.HostCommand = Command;
7554 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7556 if (Command != 0x80)
7563 BOOLEAN AsicCheckCommanOk(
7564 IN PRTMP_ADAPTER pAd,
7567 UINT32 CmdStatus = 0, CID = 0, i;
7568 UINT32 ThisCIDMask = 0;
7573 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7574 // Find where the command is. Because this is randomly specified by firmware.
7575 if ((CID & CID0MASK) == Command)
7577 ThisCIDMask = CID0MASK;
7580 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7582 ThisCIDMask = CID1MASK;
7585 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7587 ThisCIDMask = CID2MASK;
7590 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7592 ThisCIDMask = CID3MASK;
7600 // Get CommandStatus Value
7601 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7603 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7606 // If Status is 1, the comamnd is success.
7607 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7608 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7610 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7611 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7612 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7615 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7619 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7621 // Clear Command and Status.
7622 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7623 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7629 ========================================================================
7631 Routine Description:
7632 Verify the support rate for different PHY type
7635 pAd Pointer to our adapter
7640 IRQL = PASSIVE_LEVEL
7642 ========================================================================
7644 VOID RTMPCheckRates(
7645 IN PRTMP_ADAPTER pAd,
7646 IN OUT UCHAR SupRate[],
7647 IN OUT UCHAR *SupRateLen)
7649 UCHAR RateIdx, i, j;
7650 UCHAR NewRate[12], NewRateLen;
7654 if (pAd->CommonCfg.PhyMode == PHY_11B)
7659 // Check for support rates exclude basic rate bit
7660 for (i = 0; i < *SupRateLen; i++)
7661 for (j = 0; j < RateIdx; j++)
7662 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7663 NewRate[NewRateLen++] = SupRate[i];
7665 *SupRateLen = NewRateLen;
7666 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7669 #ifdef CONFIG_STA_SUPPORT
7670 #ifdef DOT11_N_SUPPORT
7671 BOOLEAN RTMPCheckChannel(
7672 IN PRTMP_ADAPTER pAd,
7673 IN UCHAR CentralChannel,
7677 UCHAR UpperChannel = 0, LowerChannel = 0;
7678 UCHAR NoEffectChannelinList = 0;
7680 // Find upper and lower channel according to 40MHz current operation.
7681 if (CentralChannel < Channel)
7683 UpperChannel = Channel;
7684 if (CentralChannel > 2)
7685 LowerChannel = CentralChannel - 2;
7689 else if (CentralChannel > Channel)
7691 UpperChannel = CentralChannel + 2;
7692 LowerChannel = Channel;
7695 for (k = 0;k < pAd->ChannelListNum;k++)
7697 if (pAd->ChannelList[k].Channel == UpperChannel)
7699 NoEffectChannelinList ++;
7701 if (pAd->ChannelList[k].Channel == LowerChannel)
7703 NoEffectChannelinList ++;
7707 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7708 if (NoEffectChannelinList == 2)
7715 ========================================================================
7717 Routine Description:
7718 Verify the support rate for HT phy type
7721 pAd Pointer to our adapter
7724 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7726 IRQL = PASSIVE_LEVEL
7728 ========================================================================
7730 BOOLEAN RTMPCheckHt(
7731 IN PRTMP_ADAPTER pAd,
7733 IN HT_CAPABILITY_IE *pHtCapability,
7734 IN ADD_HT_INFO_IE *pAddHtInfo)
7736 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7739 // If use AMSDU, set flag.
7740 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7741 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7742 // Save Peer Capability
7743 if (pHtCapability->HtCapInfo.ShortGIfor20)
7744 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7745 if (pHtCapability->HtCapInfo.ShortGIfor40)
7746 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7747 if (pHtCapability->HtCapInfo.TxSTBC)
7748 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7749 if (pHtCapability->HtCapInfo.RxSTBC)
7750 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7751 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7753 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7756 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7758 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7761 // Will check ChannelWidth for MCSSet[4] below
7762 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7763 switch (pAd->CommonCfg.RxStream)
7766 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7767 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7768 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7769 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7772 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7773 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7774 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7775 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7778 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7779 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7780 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7781 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7785 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7787 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7788 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7789 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7791 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7793 // Send Assoc Req with my HT capability.
7794 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7795 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7796 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7797 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7798 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7799 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7800 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7801 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7802 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7803 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7804 if (pAd->CommonCfg.bRdg)
7806 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7807 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7810 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7811 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7813 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7816 #endif // DOT11_N_SUPPORT //
7817 #endif // CONFIG_STA_SUPPORT //
7820 ========================================================================
7822 Routine Description:
7823 Verify the support rate for different PHY type
7826 pAd Pointer to our adapter
7831 IRQL = PASSIVE_LEVEL
7833 ========================================================================
7835 VOID RTMPUpdateMlmeRate(
7836 IN PRTMP_ADAPTER pAd)
7839 UCHAR ProperMlmeRate; //= RATE_54;
7840 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7841 BOOLEAN bMatch = FALSE;
7843 switch (pAd->CommonCfg.PhyMode)
7846 ProperMlmeRate = RATE_11;
7847 MinimumRate = RATE_1;
7849 case PHY_11BG_MIXED:
7850 #ifdef DOT11_N_SUPPORT
7851 case PHY_11ABGN_MIXED:
7852 case PHY_11BGN_MIXED:
7853 #endif // DOT11_N_SUPPORT //
7854 if ((pAd->MlmeAux.SupRateLen == 4) &&
7855 (pAd->MlmeAux.ExtRateLen == 0))
7857 ProperMlmeRate = RATE_11;
7859 ProperMlmeRate = RATE_24;
7861 if (pAd->MlmeAux.Channel <= 14)
7862 MinimumRate = RATE_1;
7864 MinimumRate = RATE_6;
7867 #ifdef DOT11_N_SUPPORT
7868 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7869 case PHY_11GN_MIXED:
7870 case PHY_11AGN_MIXED:
7871 case PHY_11AN_MIXED:
7873 #endif // DOT11_N_SUPPORT //
7874 ProperMlmeRate = RATE_24;
7875 MinimumRate = RATE_6;
7877 case PHY_11ABG_MIXED:
7878 ProperMlmeRate = RATE_24;
7879 if (pAd->MlmeAux.Channel <= 14)
7880 MinimumRate = RATE_1;
7882 MinimumRate = RATE_6;
7885 ProperMlmeRate = RATE_1;
7886 MinimumRate = RATE_1;
7890 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7892 for (j = 0; j < RateIdx; j++)
7894 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7896 if (j == ProperMlmeRate)
7908 if (bMatch == FALSE)
7910 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7912 for (j = 0; j < RateIdx; j++)
7914 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7916 if (j == ProperMlmeRate)
7929 if (bMatch == FALSE)
7931 ProperMlmeRate = MinimumRate;
7934 pAd->CommonCfg.MlmeRate = MinimumRate;
7935 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7936 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7938 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7939 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7940 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7941 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7945 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7946 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7947 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7948 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7951 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7955 IN PRTMP_ADAPTER pAd,
7962 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7967 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7969 larger = max(Rssi0, Rssi1);
7972 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7974 larger = max(larger, Rssi2);
7984 ========================================================================
7985 Routine Description:
7986 Periodic evaluate antenna link status
7989 pAd - Adapter pointer
7994 ========================================================================
7996 VOID AsicEvaluateRxAnt(
7997 IN PRTMP_ADAPTER pAd)
8001 #ifdef CONFIG_STA_SUPPORT
8002 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8004 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8005 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8006 fRTMP_ADAPTER_RADIO_OFF |
8007 fRTMP_ADAPTER_NIC_NOT_EXIST |
8008 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
8011 if (pAd->StaCfg.Psm == PWR_SAVE)
8014 #endif // CONFIG_STA_SUPPORT //
8016 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8018 if(pAd->Antenna.field.RxPath == 3)
8022 else if(pAd->Antenna.field.RxPath == 2)
8026 else if(pAd->Antenna.field.RxPath == 1)
8030 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8031 #ifdef CONFIG_STA_SUPPORT
8032 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8033 pAd->StaCfg.BBPR3 = BBPR3;
8034 #endif // CONFIG_STA_SUPPORT //
8035 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8038 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8039 pAd->RalinkCounters.OneSecTxRetryOkCount +
8040 pAd->RalinkCounters.OneSecTxFailCount;
8042 if (TxTotalCnt > 50)
8044 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8045 pAd->Mlme.bLowThroughput = FALSE;
8049 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8050 pAd->Mlme.bLowThroughput = TRUE;
8056 ========================================================================
8057 Routine Description:
8058 After evaluation, check antenna link status
8061 pAd - Adapter pointer
8066 ========================================================================
8068 VOID AsicRxAntEvalTimeout(
8069 IN PVOID SystemSpecific1,
8070 IN PVOID FunctionContext,
8071 IN PVOID SystemSpecific2,
8072 IN PVOID SystemSpecific3)
8074 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8075 #ifdef CONFIG_STA_SUPPORT
8077 CHAR larger = -127, rssi0, rssi1, rssi2;
8078 #endif // CONFIG_STA_SUPPORT //
8080 #ifdef CONFIG_STA_SUPPORT
8081 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8083 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8084 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8085 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8086 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8089 if (pAd->StaCfg.Psm == PWR_SAVE)
8093 // if the traffic is low, use average rssi as the criteria
8094 if (pAd->Mlme.bLowThroughput == TRUE)
8096 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8097 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8098 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8102 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8103 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8104 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8107 if(pAd->Antenna.field.RxPath == 3)
8109 larger = max(rssi0, rssi1);
8111 if (larger > (rssi2 + 20))
8112 pAd->Mlme.RealRxPath = 2;
8114 pAd->Mlme.RealRxPath = 3;
8116 else if(pAd->Antenna.field.RxPath == 2)
8118 if (rssi0 > (rssi1 + 20))
8119 pAd->Mlme.RealRxPath = 1;
8121 pAd->Mlme.RealRxPath = 2;
8124 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8126 if(pAd->Mlme.RealRxPath == 3)
8130 else if(pAd->Mlme.RealRxPath == 2)
8134 else if(pAd->Mlme.RealRxPath == 1)
8138 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8139 pAd->StaCfg.BBPR3 = BBPR3;
8142 #endif // CONFIG_STA_SUPPORT //
8148 VOID APSDPeriodicExec(
8149 IN PVOID SystemSpecific1,
8150 IN PVOID FunctionContext,
8151 IN PVOID SystemSpecific2,
8152 IN PVOID SystemSpecific3)
8154 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8156 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8159 pAd->CommonCfg.TriggerTimerCount++;
8164 ========================================================================
8165 Routine Description:
8166 Set/reset MAC registers according to bPiggyBack parameter
8169 pAd - Adapter pointer
8170 bPiggyBack - Enable / Disable Piggy-Back
8175 ========================================================================
8177 VOID RTMPSetPiggyBack(
8178 IN PRTMP_ADAPTER pAd,
8179 IN BOOLEAN bPiggyBack)
8181 TX_LINK_CFG_STRUC TxLinkCfg;
8183 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8185 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8186 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8190 ========================================================================
8191 Routine Description:
8192 check if this entry need to switch rate automatically
8202 ========================================================================
8204 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8205 IN PRTMP_ADAPTER pAd,
8206 IN PMAC_TABLE_ENTRY pEntry)
8208 BOOLEAN result = TRUE;
8211 #ifdef CONFIG_STA_SUPPORT
8212 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8214 // only associated STA counts
8215 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8217 result = pAd->StaCfg.bAutoTxRateSwitch;
8222 #ifdef QOS_DLS_SUPPORT
8223 if (pEntry && (pEntry->ValidAsDls))
8224 result = pAd->StaCfg.bAutoTxRateSwitch;
8225 #endif // QOS_DLS_SUPPORT //
8227 #endif // CONFIG_STA_SUPPORT //
8235 BOOLEAN RTMPAutoRateSwitchCheck(
8236 IN PRTMP_ADAPTER pAd)
8239 #ifdef CONFIG_STA_SUPPORT
8240 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8242 if (pAd->StaCfg.bAutoTxRateSwitch)
8245 #endif // CONFIG_STA_SUPPORT //
8251 ========================================================================
8252 Routine Description:
8253 check if this entry need to fix tx legacy rate
8263 ========================================================================
8265 UCHAR RTMPStaFixedTxMode(
8266 IN PRTMP_ADAPTER pAd,
8267 IN PMAC_TABLE_ENTRY pEntry)
8269 UCHAR tx_mode = FIXED_TXMODE_HT;
8272 #ifdef CONFIG_STA_SUPPORT
8273 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8275 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8277 #endif // CONFIG_STA_SUPPORT //
8283 ========================================================================
8284 Routine Description:
8285 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8295 ========================================================================
8297 VOID RTMPUpdateLegacyTxSetting(
8298 UCHAR fixed_tx_mode,
8299 PMAC_TABLE_ENTRY pEntry)
8301 HTTRANSMIT_SETTING TransmitSetting;
8303 if (fixed_tx_mode == FIXED_TXMODE_HT)
8306 TransmitSetting.word = 0;
8308 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8309 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8311 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8313 TransmitSetting.field.MODE = MODE_CCK;
8314 // CCK mode allow MCS 0~3
8315 if (TransmitSetting.field.MCS > MCS_3)
8316 TransmitSetting.field.MCS = MCS_3;
8320 TransmitSetting.field.MODE = MODE_OFDM;
8321 // OFDM mode allow MCS 0~7
8322 if (TransmitSetting.field.MCS > MCS_7)
8323 TransmitSetting.field.MCS = MCS_7;
8326 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8328 pEntry->HTPhyMode.word = TransmitSetting.word;
8329 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8330 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8334 #ifdef CONFIG_STA_SUPPORT
8336 ==========================================================================
8338 dynamic tune BBP R66 to find a balance between sensibility and
8341 IRQL = DISPATCH_LEVEL
8343 ==========================================================================
8345 VOID AsicStaBbpTuning(
8346 IN PRTMP_ADAPTER pAd)
8348 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8351 // 2860C did not support Fase CCA, therefore can't tune
8352 if (pAd->MACVersion == 0x28600100)
8358 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8361 if ((pAd->OpMode == OPMODE_STA)
8362 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8364 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8365 && (pAd->bPCIclkOff == FALSE))
8367 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8370 if (pAd->Antenna.field.RxPath > 1)
8371 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8373 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8375 if (pAd->LatchRfRegs.Channel <= 14)
8378 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8380 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8381 if (OrigR66Value != R66)
8383 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8388 R66 = 0x2E + GET_LNA_GAIN(pAd);
8389 if (OrigR66Value != R66)
8391 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8398 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8400 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8402 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8403 if (OrigR66Value != R66)
8405 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8410 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8411 if (OrigR66Value != R66)
8413 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8419 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8421 R66 = 0x3A + (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 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8430 if (OrigR66Value != R66)
8432 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8442 VOID AsicResetFromDMABusy(
8443 IN PRTMP_ADAPTER pAd)
8446 BOOLEAN bCtrl = FALSE;
8448 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8450 // Be sure restore link control value so we can write register.
8451 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8452 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8454 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8455 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8456 RTMPusecDelay(6000);
8457 pAd->bPCIclkOff = FALSE;
8461 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8463 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8465 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8466 // Reset DMA/CPU ring index
8467 RTMPRingCleanUp(pAd, QID_AC_BK);
8468 RTMPRingCleanUp(pAd, QID_AC_BE);
8469 RTMPRingCleanUp(pAd, QID_AC_VI);
8470 RTMPRingCleanUp(pAd, QID_AC_VO);
8471 RTMPRingCleanUp(pAd, QID_HCCA);
8472 RTMPRingCleanUp(pAd, QID_MGMT);
8473 RTMPRingCleanUp(pAd, QID_RX);
8476 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8478 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8480 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8481 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8482 RTMPPCIeLinkCtrlSetting(pAd, 3);
8484 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8485 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8486 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8490 IN PRTMP_ADAPTER pAd)
8492 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8494 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8495 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8496 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8498 // After hard-reset BBP, initialize all BBP values.
8499 NICRestoreBBPValue(pAd);
8500 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8504 IN PRTMP_ADAPTER pAd)
8508 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8509 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8511 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8513 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8515 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8519 IN PRTMP_ADAPTER pAd)
8521 ULONG Value1, Value2;
8524 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8525 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8528 // sum should be equals to 0xff, which is the total buffer size.
8529 if ((Value1 + Value2) < 0xff)
8531 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8532 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8534 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8536 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8538 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8541 #endif // CONFIG_STA_SUPPORT //
8543 VOID RTMPSetAGCInitValue(
8544 IN PRTMP_ADAPTER pAd,
8549 if (pAd->LatchRfRegs.Channel <= 14)
8551 R66 = 0x2E + GET_LNA_GAIN(pAd);
8552 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8556 if (BandWidth == BW_20)
8558 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8559 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8561 #ifdef DOT11_N_SUPPORT
8564 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8565 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8567 #endif // DOT11_N_SUPPORT //
8572 VOID AsicTurnOffRFClk(
8573 IN PRTMP_ADAPTER pAd,
8578 UINT32 R1 = 0, R2 = 0, R3 = 0;
8580 RTMP_RF_REGS *RFRegTable;
8582 RFRegTable = RF2850RegTable;
8584 switch (pAd->RfIcType)
8591 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8593 if (Channel == RFRegTable[index].Channel)
8595 R1 = RFRegTable[index].R1 & 0xffffdfff;
8596 R2 = RFRegTable[index].R2 & 0xfffbffff;
8597 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8599 RTMP_RF_IO_WRITE32(pAd, R1);
8600 RTMP_RF_IO_WRITE32(pAd, R2);
8602 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8603 // Set RF R2 bit18=0, R3 bit[18:19]=0
8604 //if (pAd->StaCfg.bRadio == FALSE)
8607 RTMP_RF_IO_WRITE32(pAd, R3);
8609 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8610 Channel, pAd->RfIcType, R2, R3));
8613 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8614 Channel, pAd->RfIcType, R2));
8626 VOID AsicTurnOnRFClk(
8627 IN PRTMP_ADAPTER pAd,
8632 UINT32 R1 = 0, R2 = 0, R3 = 0;
8634 RTMP_RF_REGS *RFRegTable;
8636 RFRegTable = RF2850RegTable;
8638 switch (pAd->RfIcType)
8645 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8647 if (Channel == RFRegTable[index].Channel)
8649 R3 = pAd->LatchRfRegs.R3;
8652 RTMP_RF_IO_WRITE32(pAd, R3);
8654 R1 = RFRegTable[index].R1;
8655 RTMP_RF_IO_WRITE32(pAd, R1);
8657 R2 = RFRegTable[index].R2;
8658 if (pAd->Antenna.field.TxPath == 1)
8660 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8663 if (pAd->Antenna.field.RxPath == 2)
8665 R2 |= 0x40; // write 1 to off Rxpath.
8667 else if (pAd->Antenna.field.RxPath == 1)
8669 R2 |= 0x20040; // write 1 to off RxPath
8671 RTMP_RF_IO_WRITE32(pAd, R2);
8682 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",