2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-08-25 Modify from RT2500 code base
36 John Chang 2004-09-06 modified for RT2600
39 #include "../rt_config.h"
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
44 UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45 UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
46 UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
47 UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
48 UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
49 UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
50 UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
51 UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
52 UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
53 #ifdef CONFIG_STA_SUPPORT
54 #ifdef DOT11_N_SUPPORT
55 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
56 #endif // DOT11_N_SUPPORT //
57 #endif // CONFIG_STA_SUPPORT //
59 UCHAR RateSwitchTable[] = {
60 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
61 0x11, 0x00, 0, 0, 0, // Initial used item after association
62 0x00, 0x00, 0, 40, 101,
63 0x01, 0x00, 1, 40, 50,
64 0x02, 0x00, 2, 35, 45,
65 0x03, 0x00, 3, 20, 45,
66 0x04, 0x21, 0, 30, 50,
67 0x05, 0x21, 1, 20, 50,
68 0x06, 0x21, 2, 20, 50,
69 0x07, 0x21, 3, 15, 50,
70 0x08, 0x21, 4, 15, 30,
71 0x09, 0x21, 5, 10, 25,
74 0x0c, 0x20, 12, 15, 30,
75 0x0d, 0x20, 13, 8, 20,
76 0x0e, 0x20, 14, 8, 20,
77 0x0f, 0x20, 15, 8, 25,
78 0x10, 0x22, 15, 8, 25,
96 UCHAR RateSwitchTable11B[] = {
97 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
98 0x04, 0x03, 0, 0, 0, // Initial used item after association
99 0x00, 0x00, 0, 40, 101,
100 0x01, 0x00, 1, 40, 50,
101 0x02, 0x00, 2, 35, 45,
102 0x03, 0x00, 3, 20, 45,
105 UCHAR RateSwitchTable11BG[] = {
106 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
107 0x0a, 0x00, 0, 0, 0, // Initial used item after association
108 0x00, 0x00, 0, 40, 101,
109 0x01, 0x00, 1, 40, 50,
110 0x02, 0x00, 2, 35, 45,
111 0x03, 0x00, 3, 20, 45,
112 0x04, 0x10, 2, 20, 35,
113 0x05, 0x10, 3, 16, 35,
114 0x06, 0x10, 4, 10, 25,
115 0x07, 0x10, 5, 16, 25,
116 0x08, 0x10, 6, 10, 25,
117 0x09, 0x10, 7, 10, 13,
120 UCHAR RateSwitchTable11G[] = {
121 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
122 0x08, 0x00, 0, 0, 0, // Initial used item after association
123 0x00, 0x10, 0, 20, 101,
124 0x01, 0x10, 1, 20, 35,
125 0x02, 0x10, 2, 20, 35,
126 0x03, 0x10, 3, 16, 35,
127 0x04, 0x10, 4, 10, 25,
128 0x05, 0x10, 5, 16, 25,
129 0x06, 0x10, 6, 10, 25,
130 0x07, 0x10, 7, 10, 13,
133 #ifdef DOT11_N_SUPPORT
134 UCHAR RateSwitchTable11N1S[] = {
135 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
136 0x09, 0x00, 0, 0, 0, // Initial used item after association
137 0x00, 0x21, 0, 30, 101,
138 0x01, 0x21, 1, 20, 50,
139 0x02, 0x21, 2, 20, 50,
140 0x03, 0x21, 3, 15, 50,
141 0x04, 0x21, 4, 15, 30,
142 0x05, 0x21, 5, 10, 25,
143 0x06, 0x21, 6, 8, 14,
144 0x07, 0x21, 7, 8, 14,
145 0x08, 0x23, 7, 8, 14,
148 UCHAR RateSwitchTable11N2S[] = {
149 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
150 0x0a, 0x00, 0, 0, 0, // Initial used item after association
151 0x00, 0x21, 0, 30, 101,
152 0x01, 0x21, 1, 20, 50,
153 0x02, 0x21, 2, 20, 50,
154 0x03, 0x21, 3, 15, 50,
155 0x04, 0x21, 4, 15, 30,
156 0x05, 0x20, 12, 15, 30,
157 0x06, 0x20, 13, 8, 20,
158 0x07, 0x20, 14, 8, 20,
159 0x08, 0x20, 15, 8, 25,
160 0x09, 0x22, 15, 8, 25,
163 UCHAR RateSwitchTable11N3S[] = {
164 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
165 0x0a, 0x00, 0, 0, 0, // Initial used item after association
166 0x00, 0x21, 0, 30, 101,
167 0x01, 0x21, 1, 20, 50,
168 0x02, 0x21, 2, 20, 50,
169 0x03, 0x21, 3, 15, 50,
170 0x04, 0x21, 4, 15, 30,
171 0x05, 0x20, 12, 15, 30,
172 0x06, 0x20, 13, 8, 20,
173 0x07, 0x20, 14, 8, 20,
174 0x08, 0x20, 15, 8, 25,
175 0x09, 0x22, 15, 8, 25,
178 UCHAR RateSwitchTable11N2SForABand[] = {
179 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
180 0x0b, 0x09, 0, 0, 0, // Initial used item after association
181 0x00, 0x21, 0, 30, 101,
182 0x01, 0x21, 1, 20, 50,
183 0x02, 0x21, 2, 20, 50,
184 0x03, 0x21, 3, 15, 50,
185 0x04, 0x21, 4, 15, 30,
186 0x05, 0x21, 5, 15, 30,
187 0x06, 0x20, 12, 15, 30,
188 0x07, 0x20, 13, 8, 20,
189 0x08, 0x20, 14, 8, 20,
190 0x09, 0x20, 15, 8, 25,
191 0x0a, 0x22, 15, 8, 25,
194 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
195 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
196 0x0b, 0x09, 0, 0, 0, // Initial used item after association
197 0x00, 0x21, 0, 30, 101,
198 0x01, 0x21, 1, 20, 50,
199 0x02, 0x21, 2, 20, 50,
200 0x03, 0x21, 3, 15, 50,
201 0x04, 0x21, 4, 15, 30,
202 0x05, 0x21, 5, 15, 30,
203 0x06, 0x20, 12, 15, 30,
204 0x07, 0x20, 13, 8, 20,
205 0x08, 0x20, 14, 8, 20,
206 0x09, 0x20, 15, 8, 25,
207 0x0a, 0x22, 15, 8, 25,
210 UCHAR RateSwitchTable11BGN1S[] = {
211 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
212 0x0d, 0x00, 0, 0, 0, // Initial used item after association
213 0x00, 0x00, 0, 40, 101,
214 0x01, 0x00, 1, 40, 50,
215 0x02, 0x00, 2, 35, 45,
216 0x03, 0x00, 3, 20, 45,
217 0x04, 0x21, 0, 30,101, //50
218 0x05, 0x21, 1, 20, 50,
219 0x06, 0x21, 2, 20, 50,
220 0x07, 0x21, 3, 15, 50,
221 0x08, 0x21, 4, 15, 30,
222 0x09, 0x21, 5, 10, 25,
223 0x0a, 0x21, 6, 8, 14,
224 0x0b, 0x21, 7, 8, 14,
225 0x0c, 0x23, 7, 8, 14,
228 UCHAR RateSwitchTable11BGN2S[] = {
229 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
230 0x0a, 0x00, 0, 0, 0, // Initial used item after association
231 0x00, 0x21, 0, 30,101, //50
232 0x01, 0x21, 1, 20, 50,
233 0x02, 0x21, 2, 20, 50,
234 0x03, 0x21, 3, 15, 50,
235 0x04, 0x21, 4, 15, 30,
236 0x05, 0x20, 12, 15, 30,
237 0x06, 0x20, 13, 8, 20,
238 0x07, 0x20, 14, 8, 20,
239 0x08, 0x20, 15, 8, 25,
240 0x09, 0x22, 15, 8, 25,
243 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
244 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
245 0x0a, 0x00, 0, 0, 0, // Initial used item after association
246 0x00, 0x21, 0, 30,101, //50
247 0x01, 0x21, 1, 20, 50,
248 0x02, 0x21, 2, 20, 50,
249 0x03, 0x21, 3, 20, 50,
250 0x04, 0x21, 4, 15, 50,
252 0x05, 0x20, 20, 15, 30,
253 0x06, 0x20, 21, 8, 20,
254 0x07, 0x20, 22, 8, 20,
255 0x08, 0x20, 23, 8, 25,
256 0x09, 0x22, 23, 8, 25,
257 #else // for RT2860 2*3 test
258 0x05, 0x20, 12, 15, 30,
259 0x06, 0x20, 13, 8, 20,
260 0x07, 0x20, 14, 8, 20,
261 0x08, 0x20, 15, 8, 25,
262 0x09, 0x22, 15, 8, 25,
266 UCHAR RateSwitchTable11BGN2SForABand[] = {
267 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
268 0x0b, 0x09, 0, 0, 0, // Initial used item after association
269 0x00, 0x21, 0, 30,101, //50
270 0x01, 0x21, 1, 20, 50,
271 0x02, 0x21, 2, 20, 50,
272 0x03, 0x21, 3, 15, 50,
273 0x04, 0x21, 4, 15, 30,
274 0x05, 0x21, 5, 15, 30,
275 0x06, 0x20, 12, 15, 30,
276 0x07, 0x20, 13, 8, 20,
277 0x08, 0x20, 14, 8, 20,
278 0x09, 0x20, 15, 8, 25,
279 0x0a, 0x22, 15, 8, 25,
282 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
283 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
284 0x0c, 0x09, 0, 0, 0, // Initial used item after association
285 0x00, 0x21, 0, 30,101, //50
286 0x01, 0x21, 1, 20, 50,
287 0x02, 0x21, 2, 20, 50,
288 0x03, 0x21, 3, 15, 50,
289 0x04, 0x21, 4, 15, 30,
290 0x05, 0x21, 5, 15, 30,
291 0x06, 0x21, 12, 15, 30,
292 0x07, 0x20, 20, 15, 30,
293 0x08, 0x20, 21, 8, 20,
294 0x09, 0x20, 22, 8, 20,
295 0x0a, 0x20, 23, 8, 25,
296 0x0b, 0x22, 23, 8, 25,
298 #endif // DOT11_N_SUPPORT //
300 PUCHAR ReasonString[] = {
302 /* 1 */ "Unspecified Reason",
303 /* 2 */ "Previous Auth no longer valid",
304 /* 3 */ "STA is leaving / has left",
305 /* 4 */ "DIS-ASSOC due to inactivity",
306 /* 5 */ "AP unable to hanle all associations",
307 /* 6 */ "class 2 error",
308 /* 7 */ "class 3 error",
309 /* 8 */ "STA is leaving / has left",
310 /* 9 */ "require auth before assoc/re-assoc",
314 /* 13 */ "invalid IE",
315 /* 14 */ "MIC error",
316 /* 15 */ "4-way handshake timeout",
317 /* 16 */ "2-way (group key) handshake timeout",
318 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
322 extern UCHAR OfdmRateToRxwiMCS[];
323 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
324 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
325 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
326 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
327 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
329 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
330 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
331 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
333 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
334 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
335 // clean environment.
336 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
337 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
339 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
340 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
342 UCHAR SsidIe = IE_SSID;
343 UCHAR SupRateIe = IE_SUPP_RATES;
344 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
345 #ifdef DOT11_N_SUPPORT
346 UCHAR HtCapIe = IE_HT_CAP;
347 UCHAR AddHtInfoIe = IE_ADD_HT;
348 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
350 UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
351 #endif // DOT11N_DRAFT3 //
352 #endif // DOT11_N_SUPPORT //
353 UCHAR ErpIe = IE_ERP;
354 UCHAR DsIe = IE_DS_PARM;
355 UCHAR TimIe = IE_TIM;
356 UCHAR WpaIe = IE_WPA;
357 UCHAR Wpa2Ie = IE_WPA2;
358 UCHAR IbssIe = IE_IBSS_PARM;
359 UCHAR Ccx2Ie = IE_CCX_V2;
360 UCHAR WapiIe = IE_WAPI;
362 extern UCHAR WPA_OUI[];
364 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
366 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
367 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
369 // Reset the RFIC setting to new series
370 RTMP_RF_REGS RF2850RegTable[] = {
371 // ch R1 R2 R3(TX0~4=0) R4
372 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
373 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
374 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
375 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
376 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
377 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
378 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
379 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
380 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
381 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
382 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
383 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
384 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
385 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
387 // 802.11 UNI / HyperLan 2
388 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
389 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
390 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
391 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
392 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
393 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
394 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
395 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
396 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
397 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
398 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
399 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
402 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
404 // 2008.04.30 modified
405 // The system team has AN to improve the EVM value
406 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
407 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
408 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
409 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
411 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
412 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
413 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
414 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
415 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
416 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
417 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
418 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
419 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
420 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
421 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
422 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
425 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
426 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
427 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
428 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
429 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
430 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
431 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
434 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
435 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
436 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
437 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
438 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
439 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
440 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
442 // still lack of MMAC(Japan) ch 34,38,42,46
444 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
446 FREQUENCY_ITEM FreqItems3020[] =
448 /**************************************************/
449 // ISM : 2.4 to 2.483 GHz //
450 /**************************************************/
452 /**************************************************/
453 //-CH---N-------R---K-----------
469 //2008/07/10:KH Modified to share this variable
470 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
473 ==========================================================================
475 initialize the MLME task and its data structure (queue, spinlock,
476 timer, state machines).
481 always return NDIS_STATUS_SUCCESS
483 ==========================================================================
485 NDIS_STATUS MlmeInit(
486 IN PRTMP_ADAPTER pAd)
488 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
490 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
494 Status = MlmeQueueInit(&pAd->Mlme.Queue);
495 if(Status != NDIS_STATUS_SUCCESS)
498 pAd->Mlme.bRunning = FALSE;
499 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
501 #ifdef CONFIG_STA_SUPPORT
502 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
504 BssTableInit(&pAd->ScanTab);
506 // init STA state machines
507 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
508 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
509 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
510 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
511 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
512 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
514 // Since we are using switch/case to implement it, the init is different from the above
515 // state machine init
516 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
518 #endif // CONFIG_STA_SUPPORT //
522 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
524 // Init mlme periodic timer
525 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
527 // Set mlme periodic timer
528 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
530 // software-based RX Antenna diversity
531 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
534 #ifdef CONFIG_STA_SUPPORT
535 #endif // CONFIG_STA_SUPPORT //
539 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
545 ==========================================================================
547 main loop of the MLME
549 Mlme has to be initialized, and there are something inside the queue
551 This function is invoked from MPSetInformation and MPReceive;
552 This task guarantee only one MlmeHandler will run.
554 IRQL = DISPATCH_LEVEL
556 ==========================================================================
559 IN PRTMP_ADAPTER pAd)
561 MLME_QUEUE_ELEM *Elem = NULL;
563 // Only accept MLME and Frame from peer side, no other (control/data) frame should
564 // get into this state machine
566 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
567 if(pAd->Mlme.bRunning)
569 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
574 pAd->Mlme.bRunning = TRUE;
576 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
578 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
580 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
581 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
582 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
584 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
588 //From message type, determine which state machine I should drive
589 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
592 if (Elem->MsgType == MT2_RESET_CONF)
594 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
595 MlmeRestartStateMachine(pAd);
596 Elem->Occupied = FALSE;
602 // if dequeue success
603 switch (Elem->Machine)
605 // STA state machines
606 #ifdef CONFIG_STA_SUPPORT
607 case ASSOC_STATE_MACHINE:
608 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
610 case AUTH_STATE_MACHINE:
611 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
613 case AUTH_RSP_STATE_MACHINE:
614 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
616 case SYNC_STATE_MACHINE:
617 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
619 case MLME_CNTL_STATE_MACHINE:
620 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
622 case WPA_PSK_STATE_MACHINE:
623 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
626 case LEAP_STATE_MACHINE:
627 LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
630 case AIRONET_STATE_MACHINE:
631 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
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 UINT32 TxPinCfg = 0x00050F0F;
683 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
685 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
687 // disable BEACON generation and other BEACON related hardware timers
688 AsicDisableSync(pAd);
691 #ifdef CONFIG_STA_SUPPORT
692 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
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);
702 #endif // CONFIG_STA_SUPPORT //
704 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
705 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
709 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
712 RTMPSetLED(pAd, LED_HALT);
713 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
716 LED_CFG_STRUC LedCfg;
717 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
718 LedCfg.field.LedPolar = 0;
719 LedCfg.field.RLedMode = 0;
720 LedCfg.field.GLedMode = 0;
721 LedCfg.field.YLedMode = 0;
722 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
729 if (IS_RT3070(pAd) || IS_RT3071(pAd))
731 TxPinCfg &= 0xFFFFF0F0;
732 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
737 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
739 MlmeQueueDestroy(&pAd->Mlme.Queue);
740 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
742 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
745 VOID MlmeResetRalinkCounters(
746 IN PRTMP_ADAPTER pAd)
748 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
749 // clear all OneSecxxx counters.
750 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
751 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
752 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
753 pAd->RalinkCounters.OneSecRxOkCnt = 0;
754 pAd->RalinkCounters.OneSecTxFailCount = 0;
755 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
756 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
757 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
759 // TODO: for debug only. to be removed
760 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
761 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
762 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
763 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
764 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
765 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
766 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
767 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
768 pAd->RalinkCounters.OneSecTxDoneCount = 0;
769 pAd->RalinkCounters.OneSecRxCount = 0;
770 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
771 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
776 unsigned long rx_AMSDU;
777 unsigned long rx_Total;
780 ==========================================================================
782 This routine is executed periodically to -
783 1. Decide if it's a right time to turn on PwrMgmt bit of all
785 2. Calculate ChannelQuality based on statistics of the last
786 period, so that TX rate won't toggling very frequently between a
787 successful TX and a failed TX.
788 3. If the calculated ChannelQuality indicated current connection not
789 healthy, then a ROAMing attempt is tried here.
791 IRQL = DISPATCH_LEVEL
793 ==========================================================================
795 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
796 VOID MlmePeriodicExec(
797 IN PVOID SystemSpecific1,
798 IN PVOID FunctionContext,
799 IN PVOID SystemSpecific2,
800 IN PVOID SystemSpecific3)
803 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
805 #ifdef CONFIG_STA_SUPPORT
806 #endif // CONFIG_STA_SUPPORT //
808 // Do nothing if the driver is starting halt state.
809 // This might happen when timer already been fired before cancel timer with mlmehalt
810 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
811 fRTMP_ADAPTER_RADIO_OFF |
812 fRTMP_ADAPTER_RADIO_MEASUREMENT |
813 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
816 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
818 #ifdef CONFIG_STA_SUPPORT
819 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
821 // Do nothing if monitor mode is on
825 if (pAd->Mlme.PeriodicRound & 0x1)
827 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
828 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
829 (STA_TGN_WIFI_ON(pAd)) &&
830 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
833 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
834 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
836 else if ((STA_TGN_WIFI_ON(pAd)) &&
837 ((pAd->MACVersion & 0xffff) == 0x0101))
839 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
840 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
844 #endif // CONFIG_STA_SUPPORT //
846 pAd->bUpdateBcnCntDone = FALSE;
848 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
849 pAd->Mlme.PeriodicRound ++;
852 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
853 NICUpdateFifoStaCounters(pAd);
855 // execute every 500ms
856 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
858 #ifdef CONFIG_STA_SUPPORT
859 // perform dynamic tx rate switching based on past TX history
860 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
862 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
864 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
865 MlmeDynamicTxRateSwitching(pAd);
867 #endif // CONFIG_STA_SUPPORT //
870 // Normal 1 second Mlme PeriodicExec.
871 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
873 pAd->Mlme.OneSecPeriodicRound ++;
883 //ORIBATimerTimeout(pAd);
885 // Media status changed, report to NDIS
886 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
888 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
889 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
891 pAd->IndicateMediaState = NdisMediaStateConnected;
892 RTMP_IndicateMediaState(pAd);
897 pAd->IndicateMediaState = NdisMediaStateDisconnected;
898 RTMP_IndicateMediaState(pAd);
902 NdisGetSystemUpTime(&pAd->Mlme.Now32);
904 // add the most up-to-date h/w raw counters into software variable, so that
905 // the dynamic tuning mechanism below are based on most up-to-date information
906 NICUpdateRawCounters(pAd);
909 RT2870_WatchDog(pAd);
912 #ifdef DOT11_N_SUPPORT
913 // Need statistics after read counter. So put after NICUpdateRawCounters
914 ORIBATimerTimeout(pAd);
915 #endif // DOT11_N_SUPPORT //
917 // The time period for checking antenna is according to traffic
919 if (pAd->Mlme.bEnableAutoAntennaCheck)
921 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
922 pAd->RalinkCounters.OneSecTxRetryOkCount +
923 pAd->RalinkCounters.OneSecTxFailCount;
925 // dynamic adjust antenna evaluation period according to the traffic
928 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
930 AsicEvaluateRxAnt(pAd);
935 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
937 AsicEvaluateRxAnt(pAd);
943 #ifdef CONFIG_STA_SUPPORT
944 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
945 STAMlmePeriodicExec(pAd);
946 #endif // CONFIG_STA_SUPPORT //
948 MlmeResetRalinkCounters(pAd);
950 #ifdef CONFIG_STA_SUPPORT
951 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
954 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
955 // and sending CTS-to-self over and over.
956 // Software Patch Solution:
957 // 1. Polling debug state register 0x10F4 every one second.
958 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
959 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
963 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
964 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
966 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
968 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
970 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
974 #endif // CONFIG_STA_SUPPORT //
976 RT28XX_MLME_HANDLER(pAd);
980 pAd->bUpdateBcnCntDone = FALSE;
983 #ifdef CONFIG_STA_SUPPORT
984 VOID STAMlmePeriodicExec(
990 #ifdef WPA_SUPPLICANT_SUPPORT
991 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
992 #endif // WPA_SUPPLICANT_SUPPORT //
994 // WPA MIC error should block association attempt for 60 seconds
995 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
996 pAd->StaCfg.bBlockAssoc = FALSE;
999 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1001 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1003 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1005 pAd->PreMediaState = pAd->IndicateMediaState;
1011 AsicStaBbpTuning(pAd);
1013 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1014 pAd->RalinkCounters.OneSecTxRetryOkCount +
1015 pAd->RalinkCounters.OneSecTxFailCount;
1017 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1019 // update channel quality for Roaming and UI LinkQuality display
1020 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1023 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1024 // Radio is currently in noisy environment
1025 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1026 AsicAdjustTxPower(pAd);
1030 // Is PSM bit consistent with user power management policy?
1031 // This is the only place that will set PSM bit ON.
1032 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1033 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1035 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1037 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1038 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1039 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1041 RTMPSetAGCInitValue(pAd, BW_20);
1042 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1045 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1046 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1048 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1050 // When APSD is enabled, the period changes as 20 sec
1051 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1052 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1056 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1057 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1059 if (pAd->CommonCfg.bWmmCapable)
1060 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1062 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1067 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1069 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1070 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1071 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1073 // Lost AP, send disconnect & link down event
1074 LinkDown(pAd, FALSE);
1076 #ifdef WPA_SUPPLICANT_SUPPORT
1077 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1078 if (pAd->StaCfg.WpaSupplicantUP)
1080 union iwreq_data wrqu;
1081 //send disassociate event to wpa_supplicant
1082 memset(&wrqu, 0, sizeof(wrqu));
1083 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1084 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1086 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1087 #endif // WPA_SUPPLICANT_SUPPORT //
1089 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1091 union iwreq_data wrqu;
1092 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1093 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1095 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1097 // RTMPPatchMacBbpBug(pAd);
1098 MlmeAutoReconnectLastSSID(pAd);
1100 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1102 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1103 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1104 MlmeAutoReconnectLastSSID(pAd);
1107 // Add auto seamless roaming
1108 if (pAd->StaCfg.bFastRoaming)
1110 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1112 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));
1114 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1116 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1120 else if (ADHOC_ON(pAd))
1123 if ((pAd->CommonCfg.Channel > 14)
1124 && (pAd->CommonCfg.bIEEE80211H == 1)
1125 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1127 RadarDetectPeriodic(pAd);
1130 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1131 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1133 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1134 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1136 MLME_START_REQ_STRUCT StartReq;
1138 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1139 LinkDown(pAd, FALSE);
1141 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1142 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1143 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1146 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1148 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1150 if (pEntry->ValidAsCLI == FALSE)
1153 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1154 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1157 else // no INFRA nor ADHOC connection
1160 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1161 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1162 goto SKIP_AUTO_SCAN_CONN;
1164 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1166 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1167 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1168 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1170 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1172 MLME_SCAN_REQ_STRUCT ScanReq;
1174 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1176 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1177 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1178 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1179 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1180 // Reset Missed scan number
1181 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1183 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1184 MlmeAutoReconnectLastSSID(pAd);
1186 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1188 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1191 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1195 MlmeAutoReconnectLastSSID(pAd);
1201 SKIP_AUTO_SCAN_CONN:
1203 #ifdef DOT11_N_SUPPORT
1204 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1206 pAd->MacTab.fAnyBASession = TRUE;
1207 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1209 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1211 pAd->MacTab.fAnyBASession = FALSE;
1212 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1214 #endif // DOT11_N_SUPPORT //
1217 #ifdef DOT11_N_SUPPORT
1218 #ifdef DOT11N_DRAFT3
1219 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1220 TriEventCounterMaintenance(pAd);
1221 #endif // DOT11N_DRAFT3 //
1222 #endif // DOT11_N_SUPPORT //
1229 IN PVOID SystemSpecific1,
1230 IN PVOID FunctionContext,
1231 IN PVOID SystemSpecific2,
1232 IN PVOID SystemSpecific3)
1235 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1237 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1238 RTMP_IndicateMediaState(pAd);
1239 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1242 // IRQL = DISPATCH_LEVEL
1244 IN PRTMP_ADAPTER pAd)
1246 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1247 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1249 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1251 MLME_CNTL_STATE_MACHINE,
1252 OID_802_11_BSSID_LIST_SCAN,
1255 RT28XX_MLME_HANDLER(pAd);
1259 // IRQL = DISPATCH_LEVEL
1260 VOID MlmeAutoReconnectLastSSID(
1261 IN PRTMP_ADAPTER pAd)
1265 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1266 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1267 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1269 NDIS_802_11_SSID OidSsid;
1270 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1271 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1273 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1275 MLME_CNTL_STATE_MACHINE,
1277 sizeof(NDIS_802_11_SSID),
1279 RT28XX_MLME_HANDLER(pAd);
1282 #endif // CONFIG_STA_SUPPORT //
1285 ==========================================================================
1286 Validate SSID for connection try and rescan purpose
1287 Valid SSID will have visible chars only.
1288 The valid length is from 0 to 32.
1289 IRQL = DISPATCH_LEVEL
1290 ==========================================================================
1292 BOOLEAN MlmeValidateSSID(
1298 if (SsidLen > MAX_LEN_OF_SSID)
1301 // Check each character value
1302 for (index = 0; index < SsidLen; index++)
1304 if (pSsid[index] < 0x20)
1312 VOID MlmeSelectTxRateTable(
1313 IN PRTMP_ADAPTER pAd,
1314 IN PMAC_TABLE_ENTRY pEntry,
1316 IN PUCHAR pTableSize,
1317 IN PUCHAR pInitTxRateIdx)
1321 // decide the rate table for tuning
1322 if (pAd->CommonCfg.TxRateTableSize > 0)
1324 *ppTable = RateSwitchTable;
1325 *pTableSize = RateSwitchTable[0];
1326 *pInitTxRateIdx = RateSwitchTable[1];
1331 #ifdef CONFIG_STA_SUPPORT
1332 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1334 #ifdef DOT11_N_SUPPORT
1335 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1336 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1337 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1339 *ppTable = RateSwitchTable11N1S;
1340 *pTableSize = RateSwitchTable11N1S[0];
1341 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1344 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1345 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1346 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1347 (pAd->Antenna.field.TxPath == 2))
1349 if (pAd->LatchRfRegs.Channel <= 14)
1351 *ppTable = RateSwitchTable11N2S;
1352 *pTableSize = RateSwitchTable11N2S[0];
1353 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1357 *ppTable = RateSwitchTable11N2SForABand;
1358 *pTableSize = RateSwitchTable11N2SForABand[0];
1359 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1364 #endif // DOT11_N_SUPPORT //
1365 if ((pEntry->RateLen == 4)
1366 #ifdef DOT11_N_SUPPORT
1367 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1368 #endif // DOT11_N_SUPPORT //
1371 *ppTable = RateSwitchTable11B;
1372 *pTableSize = RateSwitchTable11B[0];
1373 *pInitTxRateIdx = RateSwitchTable11B[1];
1376 else if (pAd->LatchRfRegs.Channel <= 14)
1378 *ppTable = RateSwitchTable11BG;
1379 *pTableSize = RateSwitchTable11BG[0];
1380 *pInitTxRateIdx = RateSwitchTable11BG[1];
1385 *ppTable = RateSwitchTable11G;
1386 *pTableSize = RateSwitchTable11G[0];
1387 *pInitTxRateIdx = RateSwitchTable11G[1];
1392 #endif // CONFIG_STA_SUPPORT //
1394 #ifdef DOT11_N_SUPPORT
1395 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1396 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1397 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1398 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1400 *ppTable = RateSwitchTable11BGN1S;
1401 *pTableSize = RateSwitchTable11BGN1S[0];
1402 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1407 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1408 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1409 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1410 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1412 if (pAd->LatchRfRegs.Channel <= 14)
1414 *ppTable = RateSwitchTable11BGN2S;
1415 *pTableSize = RateSwitchTable11BGN2S[0];
1416 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1421 *ppTable = RateSwitchTable11BGN2SForABand;
1422 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1423 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1429 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1430 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1432 *ppTable = RateSwitchTable11N1S;
1433 *pTableSize = RateSwitchTable11N1S[0];
1434 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1439 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1440 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1442 if (pAd->LatchRfRegs.Channel <= 14)
1444 *ppTable = RateSwitchTable11N2S;
1445 *pTableSize = RateSwitchTable11N2S[0];
1446 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1450 *ppTable = RateSwitchTable11N2SForABand;
1451 *pTableSize = RateSwitchTable11N2SForABand[0];
1452 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1457 #endif // DOT11_N_SUPPORT //
1458 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1459 if ((pEntry->RateLen == 4)
1460 #ifdef DOT11_N_SUPPORT
1461 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1462 // && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1463 #endif // DOT11_N_SUPPORT //
1466 *ppTable = RateSwitchTable11B;
1467 *pTableSize = RateSwitchTable11B[0];
1468 *pInitTxRateIdx = RateSwitchTable11B[1];
1473 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1474 if ((pEntry->RateLen > 8)
1475 #ifdef DOT11_N_SUPPORT
1476 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1477 #endif // DOT11_N_SUPPORT //
1480 *ppTable = RateSwitchTable11BG;
1481 *pTableSize = RateSwitchTable11BG[0];
1482 *pInitTxRateIdx = RateSwitchTable11BG[1];
1487 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1488 if ((pEntry->RateLen == 8)
1489 #ifdef DOT11_N_SUPPORT
1490 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1491 #endif // DOT11_N_SUPPORT //
1494 *ppTable = RateSwitchTable11G;
1495 *pTableSize = RateSwitchTable11G[0];
1496 *pInitTxRateIdx = RateSwitchTable11G[1];
1500 #ifdef DOT11_N_SUPPORT
1501 #endif // DOT11_N_SUPPORT //
1503 #ifdef CONFIG_STA_SUPPORT
1504 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1506 #ifdef DOT11_N_SUPPORT
1507 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1508 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1509 #endif // DOT11_N_SUPPORT //
1511 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1513 *ppTable = RateSwitchTable11B;
1514 *pTableSize = RateSwitchTable11B[0];
1515 *pInitTxRateIdx = RateSwitchTable11B[1];
1517 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1519 *ppTable = RateSwitchTable11G;
1520 *pTableSize = RateSwitchTable11G[0];
1521 *pInitTxRateIdx = RateSwitchTable11G[1];
1526 *ppTable = RateSwitchTable11BG;
1527 *pTableSize = RateSwitchTable11BG[0];
1528 *pInitTxRateIdx = RateSwitchTable11BG[1];
1532 #ifdef DOT11_N_SUPPORT
1533 if (pAd->LatchRfRegs.Channel <= 14)
1535 if (pAd->CommonCfg.TxStream == 1)
1537 *ppTable = RateSwitchTable11N1S;
1538 *pTableSize = RateSwitchTable11N1S[0];
1539 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1540 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1544 *ppTable = RateSwitchTable11N2S;
1545 *pTableSize = RateSwitchTable11N2S[0];
1546 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1547 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1552 if (pAd->CommonCfg.TxStream == 1)
1554 *ppTable = RateSwitchTable11N1S;
1555 *pTableSize = RateSwitchTable11N1S[0];
1556 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1557 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1561 *ppTable = RateSwitchTable11N2SForABand;
1562 *pTableSize = RateSwitchTable11N2SForABand[0];
1563 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1564 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1567 #endif // DOT11_N_SUPPORT //
1568 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1569 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1571 #endif // CONFIG_STA_SUPPORT //
1575 #ifdef CONFIG_STA_SUPPORT
1577 ==========================================================================
1579 This routine checks if there're other APs out there capable for
1580 roaming. Caller should call this routine only when Link up in INFRA mode
1581 and channel quality is below CQI_GOOD_THRESHOLD.
1583 IRQL = DISPATCH_LEVEL
1586 ==========================================================================
1588 VOID MlmeCheckForRoaming(
1589 IN PRTMP_ADAPTER pAd,
1593 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1596 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1597 // put all roaming candidates into RoamTab, and sort in RSSI order
1598 BssTableInit(pRoamTab);
1599 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1601 pBss = &pAd->ScanTab.BssEntry[i];
1603 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1604 continue; // AP disappear
1605 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1606 continue; // RSSI too weak. forget it.
1607 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1608 continue; // skip current AP
1609 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1610 continue; // only AP with stronger RSSI is eligible for roaming
1612 // AP passing all above rules is put into roaming candidate table
1613 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1614 pRoamTab->BssNr += 1;
1617 if (pRoamTab->BssNr > 0)
1619 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1620 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1622 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1623 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1624 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1625 RT28XX_MLME_HANDLER(pAd);
1628 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1632 ==========================================================================
1634 This routine checks if there're other APs out there capable for
1635 roaming. Caller should call this routine only when link up in INFRA mode
1636 and channel quality is below CQI_GOOD_THRESHOLD.
1638 IRQL = DISPATCH_LEVEL
1641 ==========================================================================
1643 VOID MlmeCheckForFastRoaming(
1644 IN PRTMP_ADAPTER pAd,
1648 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1651 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1652 // put all roaming candidates into RoamTab, and sort in RSSI order
1653 BssTableInit(pRoamTab);
1654 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1656 pBss = &pAd->ScanTab.BssEntry[i];
1658 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1659 continue; // RSSI too weak. forget it.
1660 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1661 continue; // skip current AP
1662 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1663 continue; // skip different SSID
1664 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1665 continue; // skip AP without better RSSI
1667 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));
1668 // AP passing all above rules is put into roaming candidate table
1669 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1670 pRoamTab->BssNr += 1;
1673 if (pRoamTab->BssNr > 0)
1675 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1676 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1678 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1679 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1680 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1681 RT28XX_MLME_HANDLER(pAd);
1684 // Maybe site survey required
1687 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1689 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1690 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1691 pAd->StaCfg.ScanCnt = 2;
1692 pAd->StaCfg.LastScanTime = Now;
1697 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1701 ==========================================================================
1703 This routine calculates TxPER, RxPER of the past N-sec period. And
1704 according to the calculation result, ChannelQuality is calculated here
1705 to decide if current AP is still doing the job.
1707 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1709 StaCfg.ChannelQuality - 0..100
1711 IRQL = DISPATCH_LEVEL
1713 NOTE: This routine decide channle quality based on RX CRC error ratio.
1714 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1715 is performed right before this routine, so that this routine can decide
1716 channel quality based on the most up-to-date information
1717 ==========================================================================
1719 VOID MlmeCalculateChannelQuality(
1720 IN PRTMP_ADAPTER pAd,
1723 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1727 ULONG BeaconLostTime = BEACON_LOST_TIME;
1729 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1732 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1734 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1735 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1743 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1744 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1748 // calculate RX PER - don't take RxPER into consideration if too few sample
1750 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1754 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1757 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1759 if (INFRA_ON(pAd) &&
1760 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1761 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1763 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1764 pAd->Mlme.ChannelQuality = 0;
1771 else if (MaxRssi < -90)
1774 NorRssi = (MaxRssi + 90) * 2;
1776 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1777 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1778 TX_WEIGHTING * (100 - TxPRR) +
1779 RX_WEIGHTING* (100 - RxPER)) / 100;
1780 if (pAd->Mlme.ChannelQuality >= 100)
1781 pAd->Mlme.ChannelQuality = 100;
1787 IN PRTMP_ADAPTER pAd,
1788 IN PMAC_TABLE_ENTRY pEntry,
1789 IN PRTMP_TX_RATE_SWITCH pTxRate)
1791 UCHAR MaxMode = MODE_OFDM;
1793 #ifdef DOT11_N_SUPPORT
1794 MaxMode = MODE_HTGREENFIELD;
1796 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1797 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1799 #endif // DOT11_N_SUPPORT //
1800 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1802 if (pTxRate->CurrMCS < MCS_AUTO)
1803 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1805 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1806 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1810 // If peer adhoc is b-only mode, we can't send 11g rate.
1811 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1812 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1815 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1817 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1818 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1819 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1821 // Patch speed error in status page
1822 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1826 if (pTxRate->Mode <= MaxMode)
1827 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1829 #ifdef DOT11_N_SUPPORT
1830 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1831 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1833 #endif // DOT11_N_SUPPORT //
1834 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1836 #ifdef DOT11_N_SUPPORT
1837 // Reexam each bandwidth's SGI support.
1838 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1840 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1841 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1842 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1843 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1846 // Turn RTS/CTS rate to 6Mbps.
1847 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1849 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1850 if (pAd->MacTab.fAnyBASession)
1852 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1856 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1859 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1861 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1862 if (pAd->MacTab.fAnyBASession)
1864 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1868 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1871 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1873 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1876 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1878 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1880 #endif // DOT11_N_SUPPORT //
1882 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1883 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1884 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1885 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1886 #ifdef DOT11_N_SUPPORT
1887 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1888 pAd->WIFItestbed.bGreenField)
1889 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1890 #endif // DOT11_N_SUPPORT //
1893 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1897 ==========================================================================
1899 This routine calculates the acumulated TxPER of eaxh TxRate. And
1900 according to the calculation result, change CommonCfg.TxRate which
1901 is the stable TX Rate we expect the Radio situation could sustained.
1903 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1907 IRQL = DISPATCH_LEVEL
1910 call this routine every second
1911 ==========================================================================
1913 VOID MlmeDynamicTxRateSwitching(
1914 IN PRTMP_ADAPTER pAd)
1916 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1917 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1918 ULONG TxErrorRatio = 0;
1919 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1920 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1922 UCHAR TableSize = 0;
1923 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1924 CHAR Rssi, RssiOffset = 0;
1925 TX_STA_CNT1_STRUC StaTx1;
1926 TX_STA_CNT0_STRUC TxStaCnt0;
1927 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1928 MAC_TABLE_ENTRY *pEntry;
1931 // walk through MAC table, see if need to change AP's TX rate toward each entry
1933 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1935 pEntry = &pAd->MacTab.Content[i];
1937 // check if this entry need to switch rate automatically
1938 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1941 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1943 Rssi = RTMPMaxRssi(pAd,
1944 pAd->StaCfg.RssiSample.AvgRssi0,
1945 pAd->StaCfg.RssiSample.AvgRssi1,
1946 pAd->StaCfg.RssiSample.AvgRssi2);
1948 // Update statistic counter
1949 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1950 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1951 pAd->bUpdateBcnCntDone = TRUE;
1952 TxRetransmit = StaTx1.field.TxRetransmit;
1953 TxSuccess = StaTx1.field.TxSuccess;
1954 TxFailCount = TxStaCnt0.field.TxFailCount;
1955 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1957 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1958 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1959 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1960 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1961 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1962 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1964 // if no traffic in the past 1-sec period, don't change TX rate,
1965 // but clear all bad history. because the bad history may affect the next
1966 // Chariot throughput test
1967 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1968 pAd->RalinkCounters.OneSecTxRetryOkCount +
1969 pAd->RalinkCounters.OneSecTxFailCount;
1972 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1976 if (INFRA_ON(pAd) && (i == 1))
1977 Rssi = RTMPMaxRssi(pAd,
1978 pAd->StaCfg.RssiSample.AvgRssi0,
1979 pAd->StaCfg.RssiSample.AvgRssi1,
1980 pAd->StaCfg.RssiSample.AvgRssi2);
1982 Rssi = RTMPMaxRssi(pAd,
1983 pEntry->RssiSample.AvgRssi0,
1984 pEntry->RssiSample.AvgRssi1,
1985 pEntry->RssiSample.AvgRssi2);
1987 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1988 pEntry->OneSecTxRetryOkCount +
1989 pEntry->OneSecTxFailCount;
1992 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1995 CurrRateIdx = pEntry->CurrTxRateIndex;
1997 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1999 if (CurrRateIdx >= TableSize)
2001 CurrRateIdx = TableSize - 1;
2004 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2005 // So need to sync here.
2006 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2007 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2008 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2012 // Need to sync Real Tx rate and our record.
2013 // Then return for next DRS.
2014 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2015 pEntry->CurrTxRateIndex = InitTxRateIdx;
2016 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2018 // reset all OneSecTx counters
2019 RESET_ONE_SEC_TX_CNT(pEntry);
2023 // decide the next upgrade rate and downgrade rate, if any
2024 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2026 UpRateIdx = CurrRateIdx + 1;
2027 DownRateIdx = CurrRateIdx -1;
2029 else if (CurrRateIdx == 0)
2031 UpRateIdx = CurrRateIdx + 1;
2032 DownRateIdx = CurrRateIdx;
2034 else if (CurrRateIdx == (TableSize - 1))
2036 UpRateIdx = CurrRateIdx;
2037 DownRateIdx = CurrRateIdx - 1;
2040 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2042 #ifdef DOT11_N_SUPPORT
2043 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2045 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2046 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2049 #endif // DOT11_N_SUPPORT //
2051 TrainUp = pCurrTxRate->TrainUp;
2052 TrainDown = pCurrTxRate->TrainDown;
2055 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2058 // Keep the last time TxRateChangeAction status.
2060 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2065 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2066 // (criteria copied from RT2500 for Netopia case)
2068 if (TxTotalCnt <= 15)
2072 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2073 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2074 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2075 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2077 // check the existence and index of each needed MCS
2078 while (idx < pTable[0])
2080 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2082 if (pCurrTxRate->CurrMCS == MCS_0)
2086 else if (pCurrTxRate->CurrMCS == MCS_1)
2090 else if (pCurrTxRate->CurrMCS == MCS_2)
2094 else if (pCurrTxRate->CurrMCS == MCS_3)
2098 else if (pCurrTxRate->CurrMCS == MCS_4)
2102 else if (pCurrTxRate->CurrMCS == MCS_5)
2106 else if (pCurrTxRate->CurrMCS == MCS_6)
2110 //else if (pCurrTxRate->CurrMCS == MCS_7)
2111 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2115 else if (pCurrTxRate->CurrMCS == MCS_12)
2119 else if (pCurrTxRate->CurrMCS == MCS_13)
2123 else if (pCurrTxRate->CurrMCS == MCS_14)
2127 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800))
2131 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2135 else if (pCurrTxRate->CurrMCS == MCS_21)
2139 else if (pCurrTxRate->CurrMCS == MCS_22)
2143 else if (pCurrTxRate->CurrMCS == MCS_23)
2150 if (pAd->LatchRfRegs.Channel <= 14)
2152 if (pAd->NicConfig2.field.ExternalLNAForG)
2163 if (pAd->NicConfig2.field.ExternalLNAForA)
2172 #ifdef DOT11_N_SUPPORT
2174 if ((pTable == RateSwitchTable11BGN3S) ||
2175 (pTable == RateSwitchTable11N3S) ||
2176 (pTable == RateSwitchTable))
2177 {// N mode with 3 stream // 3*3
2178 if (MCS23 && (Rssi >= -70))
2180 else if (MCS22 && (Rssi >= -72))
2182 else if (MCS21 && (Rssi >= -76))
2184 else if (MCS20 && (Rssi >= -78))
2186 else if (MCS4 && (Rssi >= -82))
2188 else if (MCS3 && (Rssi >= -84))
2190 else if (MCS2 && (Rssi >= -86))
2192 else if (MCS1 && (Rssi >= -88))
2197 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2198 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2199 {// N mode with 2 stream
2200 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2202 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2204 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2206 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2208 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2210 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2212 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2214 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2219 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2220 {// N mode with 1 stream
2221 if (MCS7 && (Rssi > (-72+RssiOffset)))
2223 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2225 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2227 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2229 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2231 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2233 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2239 #endif // DOT11_N_SUPPORT //
2241 if (MCS7 && (Rssi > -70))
2243 else if (MCS6 && (Rssi > -74))
2245 else if (MCS5 && (Rssi > -78))
2247 else if (MCS4 && (Rssi > -82))
2249 else if (MCS4 == 0) // for B-only mode
2251 else if (MCS3 && (Rssi > -85))
2253 else if (MCS2 && (Rssi > -87))
2255 else if (MCS1 && (Rssi > -90))
2261 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2263 pEntry->CurrTxRateIndex = TxRateIdx;
2264 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2265 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2268 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2269 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2270 pEntry->fLastSecAccordingRSSI = TRUE;
2271 // reset all OneSecTx counters
2272 RESET_ONE_SEC_TX_CNT(pEntry);
2277 if (pEntry->fLastSecAccordingRSSI == TRUE)
2279 pEntry->fLastSecAccordingRSSI = FALSE;
2280 pEntry->LastSecTxRateChangeAction = 0;
2281 // reset all OneSecTx counters
2282 RESET_ONE_SEC_TX_CNT(pEntry);
2289 BOOLEAN bTrainUpDown = FALSE;
2291 pEntry->CurrTxRateStableTime ++;
2293 // downgrade TX quality if PER >= Rate-Down threshold
2294 if (TxErrorRatio >= TrainDown)
2296 bTrainUpDown = TRUE;
2297 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2299 // upgrade TX quality if PER <= Rate-Up threshold
2300 else if (TxErrorRatio <= TrainUp)
2302 bTrainUpDown = TRUE;
2303 bUpgradeQuality = TRUE;
2304 if (pEntry->TxQuality[CurrRateIdx])
2305 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2307 if (pEntry->TxRateUpPenalty)
2308 pEntry->TxRateUpPenalty --;
2309 else if (pEntry->TxQuality[UpRateIdx])
2310 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2313 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2317 // perform DRS - consider TxRate Down first, then rate up.
2318 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2320 pEntry->CurrTxRateIndex = DownRateIdx;
2322 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2324 pEntry->CurrTxRateIndex = UpRateIdx;
2329 // if rate-up happen, clear all bad history of all TX rates
2330 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2332 pEntry->CurrTxRateStableTime = 0;
2333 pEntry->TxRateUpPenalty = 0;
2334 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2335 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2336 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2339 // For TxRate fast train up
2341 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2343 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2345 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2347 bTxRateChanged = TRUE;
2349 // if rate-down happen, only clear DownRate's bad history
2350 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2352 pEntry->CurrTxRateStableTime = 0;
2353 pEntry->TxRateUpPenalty = 0; // no penalty
2354 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2355 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2356 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2359 // For TxRate fast train down
2361 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2363 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2365 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2367 bTxRateChanged = TRUE;
2371 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2372 bTxRateChanged = FALSE;
2375 pEntry->LastTxOkCount = TxSuccess;
2377 // reset all OneSecTx counters
2378 RESET_ONE_SEC_TX_CNT(pEntry);
2380 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2381 if (bTxRateChanged && pNextTxRate)
2383 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2389 ========================================================================
2390 Routine Description:
2391 Station side, Auto TxRate faster train up timer call back function.
2394 SystemSpecific1 - Not used.
2395 FunctionContext - Pointer to our Adapter context.
2396 SystemSpecific2 - Not used.
2397 SystemSpecific3 - Not used.
2402 ========================================================================
2404 VOID StaQuickResponeForRateUpExec(
2405 IN PVOID SystemSpecific1,
2406 IN PVOID FunctionContext,
2407 IN PVOID SystemSpecific2,
2408 IN PVOID SystemSpecific3)
2410 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2411 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2413 ULONG TxErrorRatio = 0;
2414 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2415 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2417 UCHAR TableSize = 0;
2418 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2419 TX_STA_CNT1_STRUC StaTx1;
2420 TX_STA_CNT0_STRUC TxStaCnt0;
2422 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2423 MAC_TABLE_ENTRY *pEntry;
2426 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2429 // walk through MAC table, see if need to change AP's TX rate toward each entry
2431 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2433 pEntry = &pAd->MacTab.Content[i];
2435 // check if this entry need to switch rate automatically
2436 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2439 if (INFRA_ON(pAd) && (i == 1))
2440 Rssi = RTMPMaxRssi(pAd,
2441 pAd->StaCfg.RssiSample.AvgRssi0,
2442 pAd->StaCfg.RssiSample.AvgRssi1,
2443 pAd->StaCfg.RssiSample.AvgRssi2);
2445 Rssi = RTMPMaxRssi(pAd,
2446 pEntry->RssiSample.AvgRssi0,
2447 pEntry->RssiSample.AvgRssi1,
2448 pEntry->RssiSample.AvgRssi2);
2450 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2452 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2454 // decide the next upgrade rate and downgrade rate, if any
2455 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2457 UpRateIdx = CurrRateIdx + 1;
2458 DownRateIdx = CurrRateIdx -1;
2460 else if (CurrRateIdx == 0)
2462 UpRateIdx = CurrRateIdx + 1;
2463 DownRateIdx = CurrRateIdx;
2465 else if (CurrRateIdx == (TableSize - 1))
2467 UpRateIdx = CurrRateIdx;
2468 DownRateIdx = CurrRateIdx - 1;
2471 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2473 #ifdef DOT11_N_SUPPORT
2474 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2476 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2477 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2480 #endif // DOT11_N_SUPPORT //
2482 TrainUp = pCurrTxRate->TrainUp;
2483 TrainDown = pCurrTxRate->TrainDown;
2486 if (pAd->MacTab.Size == 1)
2488 // Update statistic counter
2489 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2490 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2492 TxRetransmit = StaTx1.field.TxRetransmit;
2493 TxSuccess = StaTx1.field.TxSuccess;
2494 TxFailCount = TxStaCnt0.field.TxFailCount;
2495 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2497 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2498 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2499 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2500 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2501 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2502 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2505 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2509 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2510 pEntry->OneSecTxRetryOkCount +
2511 pEntry->OneSecTxFailCount;
2514 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2519 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2520 // (criteria copied from RT2500 for Netopia case)
2522 if (TxTotalCnt <= 12)
2524 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2525 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2527 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2529 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2530 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2532 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2534 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2537 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2543 ULONG OneSecTxNoRetryOKRationCount;
2545 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2550 // downgrade TX quality if PER >= Rate-Down threshold
2551 if (TxErrorRatio >= TrainDown)
2553 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2556 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2558 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2560 // perform DRS - consider TxRate Down first, then rate up.
2561 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2563 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2565 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2566 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2571 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2573 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2577 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2579 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2584 // if rate-up happen, clear all bad history of all TX rates
2585 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2587 pAd->DrsCounters.TxRateUpPenalty = 0;
2588 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2589 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2590 bTxRateChanged = TRUE;
2592 // if rate-down happen, only clear DownRate's bad history
2593 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2595 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2597 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2598 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2599 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2600 bTxRateChanged = TRUE;
2604 bTxRateChanged = FALSE;
2607 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2608 if (bTxRateChanged && pNextTxRate)
2610 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2616 ==========================================================================
2618 This routine is executed periodically inside MlmePeriodicExec() after
2619 association with an AP.
2620 It checks if StaCfg.Psm is consistent with user policy (recorded in
2621 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2622 there're some conditions to consider:
2623 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2624 the time when Mibss==TRUE
2625 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2626 if outgoing traffic available in TxRing or MgmtRing.
2628 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2630 IRQL = DISPATCH_LEVEL
2632 ==========================================================================
2634 VOID MlmeCheckPsmChange(
2635 IN PRTMP_ADAPTER pAd,
2641 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2642 // 2. user wants either MAX_PSP or FAST_PSP
2643 // 3. but current psm is not in PWR_SAVE
2644 // 4. CNTL state machine is not doing SCANning
2645 // 5. no TX SUCCESS event for the past 1-sec period
2646 #ifdef NDIS51_MINIPORT
2647 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2648 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2651 PowerMode = pAd->StaCfg.WindowsPowerMode;
2653 if (INFRA_ON(pAd) &&
2654 (PowerMode != Ndis802_11PowerModeCAM) &&
2655 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2656 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2657 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2658 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2659 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2661 // add by johnli, use Rx OK data count per second to calculate throughput
2662 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2663 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2664 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2666 (pAd->StaCfg.HTPhyMode.field.MODE <= MODE_OFDM) &&
2668 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2669 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2671 (pAd->StaCfg.HTPhyMode.field.MODE > MODE_OFDM) &&
2673 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2676 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2677 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2678 MlmeSetPsmBit(pAd, PWR_SAVE);
2679 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2681 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2685 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2691 // IRQL = PASSIVE_LEVEL
2692 // IRQL = DISPATCH_LEVEL
2694 IN PRTMP_ADAPTER pAd,
2697 AUTO_RSP_CFG_STRUC csr4;
2699 pAd->StaCfg.Psm = psm;
2700 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2701 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2702 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2704 #endif // CONFIG_STA_SUPPORT //
2707 // IRQL = DISPATCH_LEVEL
2708 VOID MlmeSetTxPreamble(
2709 IN PRTMP_ADAPTER pAd,
2710 IN USHORT TxPreamble)
2712 AUTO_RSP_CFG_STRUC csr4;
2715 // Always use Long preamble before verifiation short preamble functionality works well.
2716 // Todo: remove the following line if short preamble functionality works
2718 //TxPreamble = Rt802_11PreambleLong;
2720 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2721 if (TxPreamble == Rt802_11PreambleLong)
2723 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2724 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2725 csr4.field.AutoResponderPreamble = 0;
2729 // NOTE: 1Mbps should always use long preamble
2730 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2731 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2732 csr4.field.AutoResponderPreamble = 1;
2735 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2739 ==========================================================================
2741 Update basic rate bitmap
2742 ==========================================================================
2745 VOID UpdateBasicRateBitmap(
2746 IN PRTMP_ADAPTER pAdapter)
2749 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2750 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2751 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2752 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2753 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2756 /* if A mode, always use fix BasicRateBitMap */
2757 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2758 if (pAdapter->CommonCfg.Channel > 14)
2759 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2762 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2764 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2768 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2774 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2776 if (bitmap & (1 << i))
2778 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2780 if (sup_p[j] == rate[i])
2785 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2787 if (ext_p[j] == rate[i])
2793 } /* End of UpdateBasicRateBitmap */
2795 // IRQL = PASSIVE_LEVEL
2796 // IRQL = DISPATCH_LEVEL
2797 // bLinkUp is to identify the inital link speed.
2798 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2799 VOID MlmeUpdateTxRates(
2800 IN PRTMP_ADAPTER pAd,
2805 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2806 UCHAR MinSupport = RATE_54;
2807 ULONG BasicRateBitmap = 0;
2808 UCHAR CurrBasicRate = RATE_1;
2809 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2810 PHTTRANSMIT_SETTING pHtPhy = NULL;
2811 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2812 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2813 BOOLEAN *auto_rate_cur_p;
2814 UCHAR HtMcs = MCS_AUTO;
2816 // find max desired rate
2817 UpdateBasicRateBitmap(pAd);
2820 auto_rate_cur_p = NULL;
2821 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2823 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2825 case 2: Rate = RATE_1; num++; break;
2826 case 4: Rate = RATE_2; num++; break;
2827 case 11: Rate = RATE_5_5; num++; break;
2828 case 22: Rate = RATE_11; num++; break;
2829 case 12: Rate = RATE_6; num++; break;
2830 case 18: Rate = RATE_9; num++; break;
2831 case 24: Rate = RATE_12; num++; break;
2832 case 36: Rate = RATE_18; num++; break;
2833 case 48: Rate = RATE_24; num++; break;
2834 case 72: Rate = RATE_36; num++; break;
2835 case 96: Rate = RATE_48; num++; break;
2836 case 108: Rate = RATE_54; num++; break;
2837 //default: Rate = RATE_1; break;
2839 if (MaxDesire < Rate) MaxDesire = Rate;
2842 //===========================================================================
2843 //===========================================================================
2845 #ifdef CONFIG_STA_SUPPORT
2846 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2848 pHtPhy = &pAd->StaCfg.HTPhyMode;
2849 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2850 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2852 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2853 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2855 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2856 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2857 (MaxDesire > RATE_11))
2859 MaxDesire = RATE_11;
2862 #endif // CONFIG_STA_SUPPORT //
2864 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2865 pMinHtPhy->word = 0;
2866 pMaxHtPhy->word = 0;
2869 // Auto rate switching is enabled only if more than one DESIRED RATES are
2870 // specified; otherwise disabled
2873 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2874 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2875 *auto_rate_cur_p = FALSE;
2879 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2880 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2881 *auto_rate_cur_p = TRUE;
2885 if (HtMcs != MCS_AUTO)
2887 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2888 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2889 *auto_rate_cur_p = FALSE;
2893 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2894 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2895 *auto_rate_cur_p = TRUE;
2899 #ifdef CONFIG_STA_SUPPORT
2900 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2902 pSupRate = &pAd->StaActive.SupRate[0];
2903 pExtRate = &pAd->StaActive.ExtRate[0];
2904 SupRateLen = pAd->StaActive.SupRateLen;
2905 ExtRateLen = pAd->StaActive.ExtRateLen;
2908 #endif // CONFIG_STA_SUPPORT //
2910 pSupRate = &pAd->CommonCfg.SupRate[0];
2911 pExtRate = &pAd->CommonCfg.ExtRate[0];
2912 SupRateLen = pAd->CommonCfg.SupRateLen;
2913 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2916 // find max supported rate
2917 for (i=0; i<SupRateLen; i++)
2919 switch (pSupRate[i] & 0x7f)
2921 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2922 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2923 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2924 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2925 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2926 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2927 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2928 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2929 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2930 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2931 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2932 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2933 default: Rate = RATE_1; break;
2935 if (MaxSupport < Rate) MaxSupport = Rate;
2937 if (MinSupport > Rate) MinSupport = Rate;
2940 for (i=0; i<ExtRateLen; i++)
2942 switch (pExtRate[i] & 0x7f)
2944 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2945 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2946 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2947 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2948 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2949 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2950 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2951 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2952 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2953 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2954 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2955 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2956 default: Rate = RATE_1; break;
2958 if (MaxSupport < Rate) MaxSupport = Rate;
2960 if (MinSupport > Rate) MinSupport = Rate;
2963 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2965 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2966 // the DURATION field of outgoing uniicast DATA/MGMT frame
2967 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2969 if (BasicRateBitmap & (0x01 << i))
2970 CurrBasicRate = (UCHAR)i;
2971 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2974 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2975 // max tx rate = min {max desire rate, max supported rate}
2976 if (MaxSupport < MaxDesire)
2977 pAd->CommonCfg.MaxTxRate = MaxSupport;
2979 pAd->CommonCfg.MaxTxRate = MaxDesire;
2981 pAd->CommonCfg.MinTxRate = MinSupport;
2982 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
2983 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
2985 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
2986 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
2987 // 3. -75 > RSSI, start at 11 Mbps (long distance)
2988 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
2989 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
2990 if (*auto_rate_cur_p)
2993 #ifdef CONFIG_STA_SUPPORT
2994 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2995 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2996 #endif // CONFIG_STA_SUPPORT //
2997 if (bLinkUp == TRUE)
2998 pAd->CommonCfg.TxRate = RATE_24;
3000 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3003 pAd->CommonCfg.TxRate = RATE_11;
3005 pAd->CommonCfg.TxRate = RATE_24;
3007 // should never exceed MaxTxRate (consider 11B-only mode)
3008 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3009 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3011 pAd->CommonCfg.TxRateIndex = 0;
3015 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3016 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3017 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3019 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3020 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3021 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3022 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3025 if (pAd->CommonCfg.TxRate <= RATE_11)
3027 pMaxHtPhy->field.MODE = MODE_CCK;
3028 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3029 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3033 pMaxHtPhy->field.MODE = MODE_OFDM;
3034 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3035 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3036 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3038 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3041 pHtPhy->word = (pMaxHtPhy->word);
3042 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3044 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3045 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3046 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3050 switch (pAd->CommonCfg.PhyMode)
3052 case PHY_11BG_MIXED:
3054 #ifdef DOT11_N_SUPPORT
3055 case PHY_11BGN_MIXED:
3056 #endif // DOT11_N_SUPPORT //
3057 pAd->CommonCfg.MlmeRate = RATE_1;
3058 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3059 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3062 pAd->CommonCfg.RtsRate = RATE_11;
3064 // pAd->CommonCfg.RtsRate = RATE_1;
3069 #ifdef DOT11_N_SUPPORT
3070 case PHY_11AGN_MIXED:
3071 case PHY_11GN_MIXED:
3073 case PHY_11AN_MIXED:
3075 #endif // DOT11_N_SUPPORT //
3076 pAd->CommonCfg.MlmeRate = RATE_6;
3077 pAd->CommonCfg.RtsRate = RATE_6;
3078 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3079 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3081 case PHY_11ABG_MIXED:
3082 #ifdef DOT11_N_SUPPORT
3083 case PHY_11ABGN_MIXED:
3084 #endif // DOT11_N_SUPPORT //
3085 if (pAd->CommonCfg.Channel <= 14)
3087 pAd->CommonCfg.MlmeRate = RATE_1;
3088 pAd->CommonCfg.RtsRate = RATE_1;
3089 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3090 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3094 pAd->CommonCfg.MlmeRate = RATE_6;
3095 pAd->CommonCfg.RtsRate = RATE_6;
3096 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3097 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3101 pAd->CommonCfg.MlmeRate = RATE_6;
3102 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3103 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3104 pAd->CommonCfg.RtsRate = RATE_1;
3108 // Keep Basic Mlme Rate.
3110 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3111 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3112 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3114 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3115 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3118 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3119 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3120 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3121 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3122 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3123 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3124 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 ));
3127 #ifdef DOT11_N_SUPPORT
3129 ==========================================================================
3131 This function update HT Rate setting.
3132 Input Wcid value is valid for 2 case :
3133 1. it's used for Station in infra mode that copy AP rate to Mactable.
3134 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3136 IRQL = DISPATCH_LEVEL
3138 ==========================================================================
3140 VOID MlmeUpdateHtTxRates(
3141 IN PRTMP_ADAPTER pAd,
3144 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3146 RT_HT_CAPABILITY *pRtHtCap = NULL;
3147 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3150 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3151 PHTTRANSMIT_SETTING pHtPhy = NULL;
3152 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3153 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3154 BOOLEAN *auto_rate_cur_p;
3156 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3158 auto_rate_cur_p = NULL;
3160 #ifdef CONFIG_STA_SUPPORT
3161 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3163 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3164 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3165 pHtPhy = &pAd->StaCfg.HTPhyMode;
3166 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3167 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3169 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3171 #endif // CONFIG_STA_SUPPORT //
3173 #ifdef CONFIG_STA_SUPPORT
3174 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3176 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3179 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3180 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3181 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3182 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3183 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3184 pMaxHtPhy->field.STBC = STBC_USE;
3186 pMaxHtPhy->field.STBC = STBC_NONE;
3189 #endif // CONFIG_STA_SUPPORT //
3191 if (pDesireHtPhy->bHtEnable == FALSE)
3194 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3195 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3196 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3197 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3198 pMaxHtPhy->field.STBC = STBC_USE;
3200 pMaxHtPhy->field.STBC = STBC_NONE;
3203 // Decide MAX ht rate.
3204 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3205 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3207 pMaxHtPhy->field.MODE = MODE_HTMIX;
3209 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3210 pMaxHtPhy->field.BW = BW_40;
3212 pMaxHtPhy->field.BW = BW_20;
3214 if (pMaxHtPhy->field.BW == BW_20)
3215 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3217 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3219 for (i=23; i>=0; i--) // 3*3
3222 bitmask = (1<<(i-(j*8)));
3224 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3226 pMaxHtPhy->field.MCS = i;
3234 // Copy MIN ht rate. rt2860???
3235 pMinHtPhy->field.BW = BW_20;
3236 pMinHtPhy->field.MCS = 0;
3237 pMinHtPhy->field.STBC = 0;
3238 pMinHtPhy->field.ShortGI = 0;
3239 //If STA assigns fixed rate. update to fixed here.
3240 #ifdef CONFIG_STA_SUPPORT
3241 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3243 if (pDesireHtPhy->MCSSet[4] != 0)
3245 pMaxHtPhy->field.MCS = 32;
3246 pMinHtPhy->field.MCS = 32;
3247 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3250 for (i=23; (CHAR)i >= 0; i--) // 3*3
3253 bitmask = (1<<(i-(j*8)));
3254 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3256 pMaxHtPhy->field.MCS = i;
3257 pMinHtPhy->field.MCS = i;
3264 #endif // CONFIG_STA_SUPPORT //
3268 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3269 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3270 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3271 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3272 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3274 // use default now. rt2860
3275 if (pDesireHtPhy->MCSSet[0] != 0xff)
3276 *auto_rate_cur_p = FALSE;
3278 *auto_rate_cur_p = TRUE;
3280 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3281 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3282 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3283 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3285 #endif // DOT11_N_SUPPORT //
3287 // IRQL = DISPATCH_LEVEL
3289 IN PRTMP_ADAPTER pAd)
3291 RT28XX_MLME_RADIO_OFF(pAd);
3294 // IRQL = DISPATCH_LEVEL
3296 IN PRTMP_ADAPTER pAd)
3298 RT28XX_MLME_RADIO_ON(pAd);
3301 // ===========================================================================================
3303 // ===========================================================================================
3306 /*! \brief initialize BSS table
3307 * \param p_tab pointer to the table
3312 IRQL = PASSIVE_LEVEL
3313 IRQL = DISPATCH_LEVEL
3322 Tab->BssOverlapNr = 0;
3323 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3325 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3326 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3330 #ifdef DOT11_N_SUPPORT
3332 IN PRTMP_ADAPTER pAd,
3337 Tab->numAsOriginator = 0;
3338 Tab->numAsRecipient = 0;
3339 NdisAllocateSpinLock(&pAd->BATabLock);
3340 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3342 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3343 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3345 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3347 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3350 #endif // DOT11_N_SUPPORT //
3352 /*! \brief search the BSS table by SSID
3353 * \param p_tab pointer to the bss table
3354 * \param ssid SSID string
3355 * \return index of the table, BSS_NOT_FOUND if not in the table
3358 * \note search by sequential search
3360 IRQL = DISPATCH_LEVEL
3363 ULONG BssTableSearch(
3370 for (i = 0; i < Tab->BssNr; i++)
3373 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3374 // We should distinguish this case.
3376 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3377 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3378 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3383 return (ULONG)BSS_NOT_FOUND;
3386 ULONG BssSsidTableSearch(
3395 for (i = 0; i < Tab->BssNr; i++)
3398 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3399 // We should distinguish this case.
3401 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3402 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3403 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3404 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3409 return (ULONG)BSS_NOT_FOUND;
3412 ULONG BssTableSearchWithSSID(
3421 for (i = 0; i < Tab->BssNr; i++)
3423 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3424 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3425 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3426 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3427 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3428 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3433 return (ULONG)BSS_NOT_FOUND;
3436 // IRQL = DISPATCH_LEVEL
3437 VOID BssTableDeleteEntry(
3438 IN OUT BSS_TABLE *Tab,
3444 for (i = 0; i < Tab->BssNr; i++)
3446 if ((Tab->BssEntry[i].Channel == Channel) &&
3447 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3449 for (j = i; j < Tab->BssNr - 1; j++)
3451 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3453 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3460 #ifdef DOT11_N_SUPPORT
3462 ========================================================================
3463 Routine Description:
3464 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3467 // IRQL = DISPATCH_LEVEL
3468 ========================================================================
3470 VOID BATableDeleteORIEntry(
3471 IN OUT PRTMP_ADAPTER pAd,
3472 IN BA_ORI_ENTRY *pBAORIEntry)
3475 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3477 NdisAcquireSpinLock(&pAd->BATabLock);
3478 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3480 pAd->BATable.numAsOriginator -= 1;
3481 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3482 // Erase Bitmap flag.
3484 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3485 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3486 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3487 pBAORIEntry->Token = 1;
3488 // Not clear Sequence here.
3489 NdisReleaseSpinLock(&pAd->BATabLock);
3492 #endif // DOT11_N_SUPPORT //
3500 IRQL = DISPATCH_LEVEL
3504 IN PRTMP_ADAPTER pAd,
3505 OUT BSS_ENTRY *pBss,
3510 IN USHORT BeaconPeriod,
3511 IN PCF_PARM pCfParm,
3513 IN USHORT CapabilityInfo,
3515 IN UCHAR SupRateLen,
3517 IN UCHAR ExtRateLen,
3518 IN HT_CAPABILITY_IE *pHtCapability,
3519 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3520 IN UCHAR HtCapabilityLen,
3521 IN UCHAR AddHtInfoLen,
3522 IN UCHAR NewExtChanOffset,
3525 IN LARGE_INTEGER TimeStamp,
3527 IN PEDCA_PARM pEdcaParm,
3528 IN PQOS_CAPABILITY_PARM pQosCapability,
3529 IN PQBSS_LOAD_PARM pQbssLoad,
3530 IN USHORT LengthVIE,
3531 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3533 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3534 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3538 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3539 // Or send beacon /probe response with SSID len matching real SSID length,
3540 // but SSID is all zero. such as "00-00-00-00" with length 4.
3541 // We have to prevent this case overwrite correct table
3542 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3544 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3545 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3546 pBss->SsidLen = SsidLen;
3552 pBss->BssType = BssType;
3553 pBss->BeaconPeriod = BeaconPeriod;
3554 if (BssType == BSS_INFRA)
3556 if (pCfParm->bValid)
3558 pBss->CfpCount = pCfParm->CfpCount;
3559 pBss->CfpPeriod = pCfParm->CfpPeriod;
3560 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3561 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3566 pBss->AtimWin = AtimWin;
3569 pBss->CapabilityInfo = CapabilityInfo;
3570 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3571 // Combine with AuthMode, they will decide the connection methods.
3572 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3573 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3574 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3575 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3577 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3578 pBss->SupRateLen = SupRateLen;
3579 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3580 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3581 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3582 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3583 pBss->NewExtChanOffset = NewExtChanOffset;
3584 pBss->ExtRateLen = ExtRateLen;
3585 pBss->Channel = Channel;
3586 pBss->CentralChannel = Channel;
3588 // Update CkipFlag. if not exists, the value is 0x0
3589 pBss->CkipFlag = CkipFlag;
3591 // New for microsoft Fixed IEs
3592 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3593 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3594 pBss->FixIEs.Capabilities = CapabilityInfo;
3596 // New for microsoft Variable IEs
3599 pBss->VarIELen = LengthVIE;
3600 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3607 pBss->AddHtInfoLen = 0;
3608 pBss->HtCapabilityLen = 0;
3609 #ifdef DOT11_N_SUPPORT
3610 if (HtCapabilityLen> 0)
3612 pBss->HtCapabilityLen = HtCapabilityLen;
3613 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3614 if (AddHtInfoLen > 0)
3616 pBss->AddHtInfoLen = AddHtInfoLen;
3617 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3619 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3621 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3623 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3625 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3629 #endif // DOT11_N_SUPPORT //
3631 BssCipherParse(pBss);
3635 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3637 pBss->EdcaParm.bValid = FALSE;
3639 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3641 pBss->QosCapability.bValid = FALSE;
3643 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3645 pBss->QbssLoad.bValid = FALSE;
3647 #ifdef CONFIG_STA_SUPPORT
3648 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3654 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3655 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3656 #ifdef EXT_BUILD_CHANNEL_LIST
3657 NdisZeroMemory(&pBss->CountryString[0], 3);
3658 pBss->bHasCountryIE = FALSE;
3659 #endif // EXT_BUILD_CHANNEL_LIST //
3660 pEid = (PEID_STRUCT) pVIE;
3661 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3666 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3668 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3670 pBss->WpaIE.IELen = 0;
3673 pBss->WpaIE.IELen = pEid->Len + 2;
3674 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3678 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3680 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3682 pBss->RsnIE.IELen = 0;
3685 pBss->RsnIE.IELen = pEid->Len + 2;
3686 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3689 #ifdef EXT_BUILD_CHANNEL_LIST
3691 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3692 pBss->bHasCountryIE = TRUE;
3694 #endif // EXT_BUILD_CHANNEL_LIST //
3696 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3697 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3700 #endif // CONFIG_STA_SUPPORT //
3704 * \brief insert an entry into the bss table
3705 * \param p_tab The BSS table
3706 * \param Bssid BSSID
3708 * \param ssid_len Length of SSID
3710 * \param beacon_period
3717 * \param channel_idx
3721 * \note If SSID is identical, the old entry will be replaced by the new one
3723 IRQL = DISPATCH_LEVEL
3726 ULONG BssTableSetEntry(
3727 IN PRTMP_ADAPTER pAd,
3733 IN USHORT BeaconPeriod,
3736 IN USHORT CapabilityInfo,
3738 IN UCHAR SupRateLen,
3740 IN UCHAR ExtRateLen,
3741 IN HT_CAPABILITY_IE *pHtCapability,
3742 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3743 IN UCHAR HtCapabilityLen,
3744 IN UCHAR AddHtInfoLen,
3745 IN UCHAR NewExtChanOffset,
3748 IN LARGE_INTEGER TimeStamp,
3750 IN PEDCA_PARM pEdcaParm,
3751 IN PQOS_CAPABILITY_PARM pQosCapability,
3752 IN PQBSS_LOAD_PARM pQbssLoad,
3753 IN USHORT LengthVIE,
3754 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3758 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3759 if (Idx == BSS_NOT_FOUND)
3761 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3764 // It may happen when BSS Table was full.
3765 // The desired AP will not be added into BSS Table
3766 // In this case, if we found the desired AP then overwrite BSS Table.
3768 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3770 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3771 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3773 Idx = Tab->BssOverlapNr;
3774 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3775 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3776 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3777 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3783 return BSS_NOT_FOUND;
3787 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3788 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3789 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3794 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3795 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3796 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3798 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3799 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3800 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3807 #ifdef CONFIG_STA_SUPPORT
3808 #ifdef DOT11_N_SUPPORT
3809 #ifdef DOT11N_DRAFT3
3811 IN PRTMP_ADAPTER pAd)
3815 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3816 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3818 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3819 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3822 ULONG TriEventTableSetEntry(
3823 IN PRTMP_ADAPTER pAd,
3824 OUT TRIGGER_EVENT_TAB *Tab,
3826 IN HT_CAPABILITY_IE *pHtCapability,
3827 IN UCHAR HtCapabilityLen,
3832 if (HtCapabilityLen == 0)
3834 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3836 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3837 Tab->EventA[Tab->EventANo].bValid = TRUE;
3838 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3839 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3842 // Beacon has Regulatory class IE. So use beacon's
3843 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3847 // Use Station's Regulatory class instead.
3848 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3850 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3852 Tab->EventA[Tab->EventANo].RegClass = 32;
3854 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3855 Tab->EventA[Tab->EventANo].RegClass = 33;
3858 Tab->EventA[Tab->EventANo].RegClass = ??;
3865 else if (pHtCapability->HtCapInfo.Intolerant40)
3867 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3873 ========================================================================
3874 Routine Description:
3875 Trigger Event table Maintainence called once every second.
3878 // IRQL = DISPATCH_LEVEL
3879 ========================================================================
3881 VOID TriEventCounterMaintenance(
3882 IN PRTMP_ADAPTER pAd)
3885 BOOLEAN bNotify = FALSE;
3886 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3888 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3890 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3891 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3893 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3894 pAd->CommonCfg.TriggerEventTab.EventANo --;
3895 // Need to send 20/40 Coexistence Notify frame if has status change.
3900 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
3902 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
3903 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
3907 if (bNotify == TRUE)
3908 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
3910 #endif // DOT11N_DRAFT3 //
3911 #endif // DOT11_N_SUPPORT //
3913 // IRQL = DISPATCH_LEVEL
3914 VOID BssTableSsidSort(
3915 IN PRTMP_ADAPTER pAd,
3916 OUT BSS_TABLE *OutTab,
3921 BssTableInit(OutTab);
3923 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3925 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3926 BOOLEAN bIsHiddenApIncluded = FALSE;
3928 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3929 (pAd->MlmeAux.Channel > 14) &&
3930 RadarChannelCheck(pAd, pInBss->Channel))
3934 bIsHiddenApIncluded = TRUE;
3937 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3938 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3940 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3943 #ifdef EXT_BUILD_CHANNEL_LIST
3944 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
3945 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
3946 (pInBss->bHasCountryIE == FALSE))
3948 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
3951 #endif // EXT_BUILD_CHANNEL_LIST //
3953 #ifdef DOT11_N_SUPPORT
3954 // 2.4G/5G N only mode
3955 if ((pInBss->HtCapabilityLen == 0) &&
3956 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3958 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3961 #endif // DOT11_N_SUPPORT //
3964 // Check the Authmode first
3965 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3967 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3968 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3972 // Check cipher suite, AP must have more secured cipher than station setting
3973 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3975 // If it's not mixed mode, we should only let BSS pass with the same encryption
3976 if (pInBss->WPA.bMixMode == FALSE)
3977 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3980 // check group cipher
3981 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3984 // check pairwise cipher, skip if none matched
3985 // If profile set to AES, let it pass without question.
3986 // If profile set to TKIP, we must find one mateched
3987 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3988 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3989 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3992 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3994 // If it's not mixed mode, we should only let BSS pass with the same encryption
3995 if (pInBss->WPA2.bMixMode == FALSE)
3996 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3999 // check group cipher
4000 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4003 // check pairwise cipher, skip if none matched
4004 // If profile set to AES, let it pass without question.
4005 // If profile set to TKIP, we must find one mateched
4006 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4007 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4008 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4012 // Bss Type matched, SSID matched.
4013 // We will check wepstatus for qualification Bss
4014 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4016 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4018 // For the SESv2 case, we will not qualify WepStatus.
4024 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4025 // It definitely will fail. So, skip it.
4026 // CCX also require not even try to connect it!!
4030 #ifdef DOT11_N_SUPPORT
4031 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4032 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4033 if ((pInBss->CentralChannel != pInBss->Channel) &&
4034 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4036 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4038 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4040 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4044 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4050 #endif // DOT11_N_SUPPORT //
4052 // copy matching BSS from InTab to OutTab
4053 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4057 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4059 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4062 #ifdef DOT11_N_SUPPORT
4063 // 2.4G/5G N only mode
4064 if ((pInBss->HtCapabilityLen == 0) &&
4065 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4067 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4070 #endif // DOT11_N_SUPPORT //
4073 // Check the Authmode first
4074 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4076 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4077 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4081 // Check cipher suite, AP must have more secured cipher than station setting
4082 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4084 // If it's not mixed mode, we should only let BSS pass with the same encryption
4085 if (pInBss->WPA.bMixMode == FALSE)
4086 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4089 // check group cipher
4090 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4093 // check pairwise cipher, skip if none matched
4094 // If profile set to AES, let it pass without question.
4095 // If profile set to TKIP, we must find one mateched
4096 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4097 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4098 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4101 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4103 // If it's not mixed mode, we should only let BSS pass with the same encryption
4104 if (pInBss->WPA2.bMixMode == FALSE)
4105 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4108 // check group cipher
4109 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4112 // check pairwise cipher, skip if none matched
4113 // If profile set to AES, let it pass without question.
4114 // If profile set to TKIP, we must find one mateched
4115 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4116 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4117 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4121 // Bss Type matched, SSID matched.
4122 // We will check wepstatus for qualification Bss
4123 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4126 #ifdef DOT11_N_SUPPORT
4127 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4128 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4129 if ((pInBss->CentralChannel != pInBss->Channel) &&
4130 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4132 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4134 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4136 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4139 #endif // DOT11_N_SUPPORT //
4141 // copy matching BSS from InTab to OutTab
4142 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4147 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4151 BssTableSortByRssi(OutTab);
4155 // IRQL = DISPATCH_LEVEL
4156 VOID BssTableSortByRssi(
4157 IN OUT BSS_TABLE *OutTab)
4162 for (i = 0; i < OutTab->BssNr - 1; i++)
4164 for (j = i+1; j < OutTab->BssNr; j++)
4166 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4168 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4169 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4170 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4175 #endif // CONFIG_STA_SUPPORT //
4178 VOID BssCipherParse(
4179 IN OUT PBSS_ENTRY pBss)
4183 PRSN_IE_HEADER_STRUCT pRsnHeader;
4184 PCIPHER_SUITE_STRUCT pCipher;
4185 PAKM_SUITE_STRUCT pAKM;
4188 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4191 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4195 pBss->WepStatus = Ndis802_11WEPEnabled;
4199 pBss->WepStatus = Ndis802_11WEPDisabled;
4201 // Set default to disable & open authentication before parsing variable IE
4202 pBss->AuthMode = Ndis802_11AuthModeOpen;
4203 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4206 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4207 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4208 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4209 pBss->WPA.RsnCapability = 0;
4210 pBss->WPA.bMixMode = FALSE;
4212 // Init WPA2 setting
4213 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4214 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4215 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4216 pBss->WPA2.RsnCapability = 0;
4217 pBss->WPA2.bMixMode = FALSE;
4220 Length = (INT) pBss->VarIELen;
4224 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4225 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4226 pEid = (PEID_STRUCT) pTmp;
4230 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4231 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4237 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4238 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4239 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4240 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4243 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4244 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4245 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4248 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4249 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4250 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4256 // if Cisco IE_WPA, break
4259 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4264 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4266 // if unsupported vendor specific IE
4269 // Skip OUI, version, and multicast suite
4270 // This part should be improved in the future when AP supported multiple cipher suite.
4271 // For now, it's OK since almost all APs have fixed cipher suite supported.
4272 // pTmp = (PUCHAR) pEid->Octet;
4275 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4283 // Parse group cipher
4287 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4288 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4291 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4294 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4299 // number of unicast suite
4302 // skip all unicast cipher suites
4303 //Count = *(PUSHORT) pTmp;
4304 Count = (pTmp[1]<<8) + pTmp[0];
4305 pTmp += sizeof(USHORT);
4307 // Parsing all unicast cipher suite
4312 TmpCipher = Ndis802_11WEPDisabled;
4316 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4317 TmpCipher = Ndis802_11Encryption1Enabled;
4320 TmpCipher = Ndis802_11Encryption2Enabled;
4323 TmpCipher = Ndis802_11Encryption3Enabled;
4328 if (TmpCipher > pBss->WPA.PairCipher)
4330 // Move the lower cipher suite to PairCipherAux
4331 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4332 pBss->WPA.PairCipher = TmpCipher;
4336 pBss->WPA.PairCipherAux = TmpCipher;
4342 // 4. get AKM suite counts
4343 //Count = *(PUSHORT) pTmp;
4344 Count = (pTmp[1]<<8) + pTmp[0];
4345 pTmp += sizeof(USHORT);
4351 // Set AP support WPA mode
4352 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4353 pBss->AuthMode = Ndis802_11AuthModeWPA;
4355 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4358 // Set AP support WPA mode
4359 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4360 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4362 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4369 // Fixed for WPA-None
4370 if (pBss->BssType == BSS_ADHOC)
4372 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4373 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4374 pBss->WepStatus = pBss->WPA.GroupCipher;
4375 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4376 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4379 pBss->WepStatus = pBss->WPA.PairCipher;
4381 // Check the Pair & Group, if different, turn on mixed mode flag
4382 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4383 pBss->WPA.bMixMode = TRUE;
4388 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4390 // 0. Version must be 1
4391 if (le2cpu16(pRsnHeader->Version) != 1)
4393 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4395 // 1. Check group cipher
4396 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4397 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4400 // Parse group cipher
4401 switch (pCipher->Type)
4404 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4405 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4408 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4411 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4416 // set to correct offset for next parsing
4417 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4419 // 2. Get pairwise cipher counts
4420 //Count = *(PUSHORT) pTmp;
4421 Count = (pTmp[1]<<8) + pTmp[0];
4422 pTmp += sizeof(USHORT);
4424 // 3. Get pairwise cipher
4425 // Parsing all unicast cipher suite
4429 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4430 TmpCipher = Ndis802_11WEPDisabled;
4431 switch (pCipher->Type)
4434 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4435 TmpCipher = Ndis802_11Encryption1Enabled;
4438 TmpCipher = Ndis802_11Encryption2Enabled;
4441 TmpCipher = Ndis802_11Encryption3Enabled;
4446 if (TmpCipher > pBss->WPA2.PairCipher)
4448 // Move the lower cipher suite to PairCipherAux
4449 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4450 pBss->WPA2.PairCipher = TmpCipher;
4454 pBss->WPA2.PairCipherAux = TmpCipher;
4456 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4460 // 4. get AKM suite counts
4461 //Count = *(PUSHORT) pTmp;
4462 Count = (pTmp[1]<<8) + pTmp[0];
4463 pTmp += sizeof(USHORT);
4465 // 5. Get AKM ciphers
4466 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4467 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4473 // Set AP support WPA mode
4474 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4475 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4477 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4480 // Set AP support WPA mode
4481 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4482 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4484 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4489 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4491 // Fixed for WPA-None
4492 if (pBss->BssType == BSS_ADHOC)
4494 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4495 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4496 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4497 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4498 pBss->WepStatus = pBss->WPA.GroupCipher;
4499 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4500 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4502 pBss->WepStatus = pBss->WPA2.PairCipher;
4504 // 6. Get RSN capability
4505 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4506 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4507 pTmp += sizeof(USHORT);
4509 // Check the Pair & Group, if different, turn on mixed mode flag
4510 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4511 pBss->WPA2.bMixMode = TRUE;
4517 Length -= (pEid->Len + 2);
4521 // ===========================================================================================
4523 // ===========================================================================================
4525 /*! \brief generates a random mac address value for IBSS BSSID
4526 * \param Addr the bssid location
4531 VOID MacAddrRandomBssid(
4532 IN PRTMP_ADAPTER pAd,
4537 for (i = 0; i < MAC_ADDR_LEN; i++)
4539 pAddr[i] = RandomByte(pAd);
4542 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4545 /*! \brief init the management mac frame header
4546 * \param p_hdr mac header
4547 * \param subtype subtype of the frame
4548 * \param p_ds destination address, don't care if it is a broadcast address
4550 * \pre the station has the following information in the pAd->StaCfg
4554 * \note this function initializes the following field
4556 IRQL = PASSIVE_LEVEL
4557 IRQL = DISPATCH_LEVEL
4560 VOID MgtMacHeaderInit(
4561 IN PRTMP_ADAPTER pAd,
4562 IN OUT PHEADER_802_11 pHdr80211,
4568 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4570 pHdr80211->FC.Type = BTYPE_MGMT;
4571 pHdr80211->FC.SubType = SubType;
4572 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4573 // pHdr80211->FC.Type = BTYPE_CNTL;
4574 pHdr80211->FC.ToDs = ToDs;
4575 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4576 #ifdef CONFIG_STA_SUPPORT
4577 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4578 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4579 #endif // CONFIG_STA_SUPPORT //
4580 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4583 // ===========================================================================================
4585 // ===========================================================================================
4587 /*!***************************************************************************
4588 * This routine build an outgoing frame, and fill all information specified
4589 * in argument list to the frame body. The actual frame size is the summation
4592 * Buffer - pointer to a pre-allocated memory segment
4593 * args - a list of <int arg_size, arg> pairs.
4594 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4595 * function will FAIL!!!
4597 * Size of the buffer
4599 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4601 IRQL = PASSIVE_LEVEL
4602 IRQL = DISPATCH_LEVEL
4604 ****************************************************************************/
4605 ULONG MakeOutgoingFrame(
4607 OUT ULONG *FrameLen, ...)
4614 // calculates the total length
4616 va_start(Args, FrameLen);
4619 leng = va_arg(Args, int);
4620 if (leng == END_OF_ARGS)
4624 p = va_arg(Args, PVOID);
4625 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4626 TotLeng = TotLeng + leng;
4629 va_end(Args); /* clean up */
4630 *FrameLen = TotLeng;
4634 // ===========================================================================================
4636 // ===========================================================================================
4638 /*! \brief Initialize The MLME Queue, used by MLME Functions
4639 * \param *Queue The MLME Queue
4640 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4643 * \note Because this is done only once (at the init stage), no need to be locked
4645 IRQL = PASSIVE_LEVEL
4648 NDIS_STATUS MlmeQueueInit(
4649 IN MLME_QUEUE *Queue)
4653 NdisAllocateSpinLock(&Queue->Lock);
4659 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4661 Queue->Entry[i].Occupied = FALSE;
4662 Queue->Entry[i].MsgLen = 0;
4663 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4666 return NDIS_STATUS_SUCCESS;
4669 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4670 * \param *Queue The MLME Queue
4671 * \param Machine The State Machine Id
4672 * \param MsgType The Message Type
4673 * \param MsgLen The Message length
4674 * \param *Msg The message pointer
4675 * \return TRUE if enqueue is successful, FALSE if the queue is full
4678 * \note The message has to be initialized
4680 IRQL = PASSIVE_LEVEL
4681 IRQL = DISPATCH_LEVEL
4684 BOOLEAN MlmeEnqueue(
4685 IN PRTMP_ADAPTER pAd,
4692 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4694 // Do nothing if the driver is starting halt state.
4695 // This might happen when timer already been fired before cancel timer with mlmehalt
4696 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4699 // First check the size, it MUST not exceed the mlme queue size
4700 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4702 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4706 if (MlmeQueueFull(Queue))
4711 NdisAcquireSpinLock(&(Queue->Lock));
4715 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4720 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4721 Queue->Entry[Tail].Occupied = TRUE;
4722 Queue->Entry[Tail].Machine = Machine;
4723 Queue->Entry[Tail].MsgType = MsgType;
4724 Queue->Entry[Tail].MsgLen = MsgLen;
4728 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4731 NdisReleaseSpinLock(&(Queue->Lock));
4735 /*! \brief This function is used when Recv gets a MLME message
4736 * \param *Queue The MLME Queue
4737 * \param TimeStampHigh The upper 32 bit of timestamp
4738 * \param TimeStampLow The lower 32 bit of timestamp
4739 * \param Rssi The receiving RSSI strength
4740 * \param MsgLen The length of the message
4741 * \param *Msg The message pointer
4742 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4746 IRQL = DISPATCH_LEVEL
4749 BOOLEAN MlmeEnqueueForRecv(
4750 IN PRTMP_ADAPTER pAd,
4752 IN ULONG TimeStampHigh,
4753 IN ULONG TimeStampLow,
4762 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4764 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4766 // Do nothing if the driver is starting halt state.
4767 // This might happen when timer already been fired before cancel timer with mlmehalt
4768 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4770 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4774 // First check the size, it MUST not exceed the mlme queue size
4775 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4777 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4781 if (MlmeQueueFull(Queue))
4786 #ifdef CONFIG_STA_SUPPORT
4787 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4789 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4791 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4795 #endif // CONFIG_STA_SUPPORT //
4797 // OK, we got all the informations, it is time to put things into queue
4798 NdisAcquireSpinLock(&(Queue->Lock));
4802 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4806 Queue->Entry[Tail].Occupied = TRUE;
4807 Queue->Entry[Tail].Machine = Machine;
4808 Queue->Entry[Tail].MsgType = MsgType;
4809 Queue->Entry[Tail].MsgLen = MsgLen;
4810 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4811 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4812 Queue->Entry[Tail].Rssi0 = Rssi0;
4813 Queue->Entry[Tail].Rssi1 = Rssi1;
4814 Queue->Entry[Tail].Rssi2 = Rssi2;
4815 Queue->Entry[Tail].Signal = Signal;
4816 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4818 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4822 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4825 NdisReleaseSpinLock(&(Queue->Lock));
4827 RT28XX_MLME_HANDLER(pAd);
4833 /*! \brief Dequeue a message from the MLME Queue
4834 * \param *Queue The MLME Queue
4835 * \param *Elem The message dequeued from MLME Queue
4836 * \return TRUE if the Elem contains something, FALSE otherwise
4840 IRQL = DISPATCH_LEVEL
4843 BOOLEAN MlmeDequeue(
4844 IN MLME_QUEUE *Queue,
4845 OUT MLME_QUEUE_ELEM **Elem)
4847 NdisAcquireSpinLock(&(Queue->Lock));
4848 *Elem = &(Queue->Entry[Queue->Head]);
4851 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4855 NdisReleaseSpinLock(&(Queue->Lock));
4859 // IRQL = DISPATCH_LEVEL
4860 VOID MlmeRestartStateMachine(
4861 IN PRTMP_ADAPTER pAd)
4863 #ifdef CONFIG_STA_SUPPORT
4865 #endif // CONFIG_STA_SUPPORT //
4867 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4870 #ifdef CONFIG_STA_SUPPORT
4871 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4873 // Cancel all timer events
4874 // Be careful to cancel new added timer
4875 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4876 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4877 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4878 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4879 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4880 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4882 #endif // CONFIG_STA_SUPPORT //
4884 // Change back to original channel in case of doing scan
4885 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4886 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4888 // Resume MSDU which is turned off durning scan
4889 RTMPResumeMsduTransmission(pAd);
4891 #ifdef CONFIG_STA_SUPPORT
4892 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4894 // Set all state machines back IDLE
4895 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4896 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4897 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4898 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4899 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4900 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4902 #endif // CONFIG_STA_SUPPORT //
4906 /*! \brief test if the MLME Queue is empty
4907 * \param *Queue The MLME Queue
4908 * \return TRUE if the Queue is empty, FALSE otherwise
4912 IRQL = DISPATCH_LEVEL
4915 BOOLEAN MlmeQueueEmpty(
4916 IN MLME_QUEUE *Queue)
4920 NdisAcquireSpinLock(&(Queue->Lock));
4921 Ans = (Queue->Num == 0);
4922 NdisReleaseSpinLock(&(Queue->Lock));
4927 /*! \brief test if the MLME Queue is full
4928 * \param *Queue The MLME Queue
4929 * \return TRUE if the Queue is empty, FALSE otherwise
4933 IRQL = PASSIVE_LEVEL
4934 IRQL = DISPATCH_LEVEL
4937 BOOLEAN MlmeQueueFull(
4938 IN MLME_QUEUE *Queue)
4942 NdisAcquireSpinLock(&(Queue->Lock));
4943 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4944 NdisReleaseSpinLock(&(Queue->Lock));
4949 /*! \brief The destructor of MLME Queue
4954 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4956 IRQL = PASSIVE_LEVEL
4959 VOID MlmeQueueDestroy(
4960 IN MLME_QUEUE *pQueue)
4962 NdisAcquireSpinLock(&(pQueue->Lock));
4966 NdisReleaseSpinLock(&(pQueue->Lock));
4967 NdisFreeSpinLock(&(pQueue->Lock));
4970 /*! \brief To substitute the message type if the message is coming from external
4971 * \param pFrame The frame received
4972 * \param *Machine The state machine
4973 * \param *MsgType the message type for the state machine
4974 * \return TRUE if the substitution is successful, FALSE otherwise
4978 IRQL = DISPATCH_LEVEL
4981 #ifdef CONFIG_STA_SUPPORT
4982 BOOLEAN MsgTypeSubst(
4983 IN PRTMP_ADAPTER pAd,
4984 IN PFRAME_802_11 pFrame,
4992 // Pointer to start of data frames including SNAP header
4993 pData = (PUCHAR) pFrame + LENGTH_802_11;
4995 // The only data type will pass to this function is EAPOL frame
4996 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4998 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5000 // Cisco Aironet SNAP header
5001 *Machine = AIRONET_STATE_MACHINE;
5002 *MsgType = MT2_AIRONET_MSG;
5006 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5009 *Machine = LEAP_STATE_MACHINE;
5010 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5011 return (LeapMsgTypeSubst(EAPType, MsgType));
5014 #endif // LEAP_SUPPORT //
5016 *Machine = WPA_PSK_STATE_MACHINE;
5017 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5018 return(WpaMsgTypeSubst(EAPType, MsgType));
5022 switch (pFrame->Hdr.FC.SubType)
5024 case SUBTYPE_ASSOC_REQ:
5025 *Machine = ASSOC_STATE_MACHINE;
5026 *MsgType = MT2_PEER_ASSOC_REQ;
5028 case SUBTYPE_ASSOC_RSP:
5029 *Machine = ASSOC_STATE_MACHINE;
5030 *MsgType = MT2_PEER_ASSOC_RSP;
5032 case SUBTYPE_REASSOC_REQ:
5033 *Machine = ASSOC_STATE_MACHINE;
5034 *MsgType = MT2_PEER_REASSOC_REQ;
5036 case SUBTYPE_REASSOC_RSP:
5037 *Machine = ASSOC_STATE_MACHINE;
5038 *MsgType = MT2_PEER_REASSOC_RSP;
5040 case SUBTYPE_PROBE_REQ:
5041 *Machine = SYNC_STATE_MACHINE;
5042 *MsgType = MT2_PEER_PROBE_REQ;
5044 case SUBTYPE_PROBE_RSP:
5045 *Machine = SYNC_STATE_MACHINE;
5046 *MsgType = MT2_PEER_PROBE_RSP;
5048 case SUBTYPE_BEACON:
5049 *Machine = SYNC_STATE_MACHINE;
5050 *MsgType = MT2_PEER_BEACON;
5053 *Machine = SYNC_STATE_MACHINE;
5054 *MsgType = MT2_PEER_ATIM;
5056 case SUBTYPE_DISASSOC:
5057 *Machine = ASSOC_STATE_MACHINE;
5058 *MsgType = MT2_PEER_DISASSOC_REQ;
5061 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5062 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5063 if (Seq == 1 || Seq == 3)
5065 *Machine = AUTH_RSP_STATE_MACHINE;
5066 *MsgType = MT2_PEER_AUTH_ODD;
5068 else if (Seq == 2 || Seq == 4)
5070 *Machine = AUTH_STATE_MACHINE;
5071 *MsgType = MT2_PEER_AUTH_EVEN;
5078 case SUBTYPE_DEAUTH:
5079 *Machine = AUTH_RSP_STATE_MACHINE;
5080 *MsgType = MT2_PEER_DEAUTH;
5082 case SUBTYPE_ACTION:
5083 *Machine = ACTION_STATE_MACHINE;
5084 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5085 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5087 *MsgType = MT2_ACT_INVALID;
5091 *MsgType = (pFrame->Octet[0]&0x7F);
5101 #endif // CONFIG_STA_SUPPORT //
5103 // ===========================================================================================
5105 // ===========================================================================================
5107 /*! \brief Initialize the state machine.
5108 * \param *S pointer to the state machine
5109 * \param Trans State machine transition function
5110 * \param StNr number of states
5111 * \param MsgNr number of messages
5112 * \param DefFunc default function, when there is invalid state/message combination
5113 * \param InitState initial state of the state machine
5114 * \param Base StateMachine base, internal use only
5115 * \pre p_sm should be a legal pointer
5118 IRQL = PASSIVE_LEVEL
5121 VOID StateMachineInit(
5122 IN STATE_MACHINE *S,
5123 IN STATE_MACHINE_FUNC Trans[],
5126 IN STATE_MACHINE_FUNC DefFunc,
5132 // set number of states and messages
5137 S->TransFunc = Trans;
5139 // init all state transition to default function
5140 for (i = 0; i < StNr; i++)
5142 for (j = 0; j < MsgNr; j++)
5144 S->TransFunc[i * MsgNr + j] = DefFunc;
5148 // set the starting state
5149 S->CurrState = InitState;
5152 /*! \brief This function fills in the function pointer into the cell in the state machine
5153 * \param *S pointer to the state machine
5155 * \param Msg incoming message
5156 * \param f the function to be executed when (state, message) combination occurs at the state machine
5157 * \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
5160 IRQL = PASSIVE_LEVEL
5163 VOID StateMachineSetAction(
5164 IN STATE_MACHINE *S,
5167 IN STATE_MACHINE_FUNC Func)
5171 MsgIdx = Msg - S->Base;
5173 if (St < S->NrState && MsgIdx < S->NrMsg)
5175 // boundary checking before setting the action
5176 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5180 /*! \brief This function does the state transition
5181 * \param *Adapter the NIC adapter pointer
5182 * \param *S the state machine
5183 * \param *Elem the message to be executed
5186 IRQL = DISPATCH_LEVEL
5189 VOID StateMachinePerformAction(
5190 IN PRTMP_ADAPTER pAd,
5191 IN STATE_MACHINE *S,
5192 IN MLME_QUEUE_ELEM *Elem)
5194 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5198 ==========================================================================
5200 The drop function, when machine executes this, the message is simply
5201 ignored. This function does nothing, the message is freed in
5202 StateMachinePerformAction()
5203 ==========================================================================
5206 IN PRTMP_ADAPTER pAd,
5207 IN MLME_QUEUE_ELEM *Elem)
5211 // ===========================================================================================
5213 // ===========================================================================================
5216 ==========================================================================
5219 IRQL = PASSIVE_LEVEL
5221 ==========================================================================
5224 IN PRTMP_ADAPTER pAd,
5228 pAd->Mlme.ShiftReg = 1;
5230 pAd->Mlme.ShiftReg = Seed;
5234 ==========================================================================
5236 ==========================================================================
5239 IN PRTMP_ADAPTER pAd)
5246 if (pAd->Mlme.ShiftReg == 0)
5247 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5249 for (i = 0; i < 8; i++)
5251 if (pAd->Mlme.ShiftReg & 0x00000001)
5253 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5258 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5261 R = (R << 1) | Result;
5267 VOID AsicUpdateAutoFallBackTable(
5268 IN PRTMP_ADAPTER pAd,
5269 IN PUCHAR pRateTable)
5272 HT_FBK_CFG0_STRUC HtCfg0;
5273 HT_FBK_CFG1_STRUC HtCfg1;
5274 LG_FBK_CFG0_STRUC LgCfg0;
5275 LG_FBK_CFG1_STRUC LgCfg1;
5276 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5278 // set to initial value
5279 HtCfg0.word = 0x65432100;
5280 HtCfg1.word = 0xedcba988;
5281 LgCfg0.word = 0xedcba988;
5282 LgCfg1.word = 0x00002100;
5284 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5285 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5287 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5288 switch (pCurrTxRate->Mode)
5294 switch(pCurrTxRate->CurrMCS)
5297 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5300 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5303 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5306 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5309 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5312 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5315 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5318 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5323 #ifdef DOT11_N_SUPPORT
5327 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5329 switch(pCurrTxRate->CurrMCS)
5332 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5335 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5338 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5341 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5344 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5347 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5350 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5353 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5356 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5359 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5362 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5365 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5368 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5371 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5374 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5377 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5380 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5385 #endif // DOT11_N_SUPPORT //
5388 pNextTxRate = pCurrTxRate;
5391 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5392 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5393 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5394 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5398 ========================================================================
5400 Routine Description:
5401 Set MAC register value according operation mode.
5402 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5403 If MM or GF mask is not set, those passing argument doesn't not take effect.
5405 Operation mode meaning:
5406 = 0 : Pure HT, no preotection.
5407 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5408 = 0x10: No Transmission in 40M is protected.
5409 = 0x11: Transmission in both 40M and 20M shall be protected
5411 we should choose not to use GF. But still set correct ASIC registers.
5412 ========================================================================
5414 VOID AsicUpdateProtect(
5415 IN PRTMP_ADAPTER pAd,
5416 IN USHORT OperationMode,
5418 IN BOOLEAN bDisableBGProtect,
5419 IN BOOLEAN bNonGFExist)
5421 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5427 #ifdef DOT11_N_SUPPORT
5428 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5433 if (pAd->BATable.numAsOriginator)
5436 // enable the RTS/CTS to avoid channel collision
5438 SetMask = ALLN_SETPROTECT;
5441 #endif // DOT11_N_SUPPORT //
5443 // Config ASIC RTS threshold register
5444 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5445 MacReg &= 0xFF0000FF;
5447 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5449 #ifdef DOT11_N_SUPPORT
5450 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5451 #endif // DOT11_N_SUPPORT //
5452 (pAd->CommonCfg.bAggregationCapable == TRUE))
5453 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5455 MacReg |= (0x1000 << 8);
5459 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5462 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5464 // Initial common protection settings
5465 RTMPZeroMemory(Protect, sizeof(Protect));
5468 ProtCfg.field.TxopAllowGF40 = 1;
5469 ProtCfg.field.TxopAllowGF20 = 1;
5470 ProtCfg.field.TxopAllowMM40 = 1;
5471 ProtCfg.field.TxopAllowMM20 = 1;
5472 ProtCfg.field.TxopAllowOfdm = 1;
5473 ProtCfg.field.TxopAllowCck = 1;
5474 ProtCfg.field.RTSThEn = 1;
5475 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5477 // update PHY mode and rate
5478 if (pAd->CommonCfg.Channel > 14)
5479 ProtCfg.field.ProtectRate = 0x4000;
5480 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5482 // Handle legacy(B/G) protection
5483 if (bDisableBGProtect)
5485 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5486 ProtCfg.field.ProtectCtrl = 0;
5487 Protect[0] = ProtCfg.word;
5488 Protect[1] = ProtCfg.word;
5492 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5493 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5494 Protect[0] = ProtCfg.word;
5495 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5496 Protect[1] = ProtCfg.word;
5499 #ifdef DOT11_N_SUPPORT
5500 // Decide HT frame protection.
5501 if ((SetMask & ALLN_SETPROTECT) != 0)
5503 switch(OperationMode)
5507 // 1.All STAs in the BSS are 20/40 MHz HT
5508 // 2. in ai 20/40MHz BSS
5509 // 3. all STAs are 20MHz in a 20MHz BSS
5510 // Pure HT. no protection.
5514 // PROT_TXOP(25:20) -- 010111
5515 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5516 // PROT_CTRL(17:16) -- 00 (None)
5517 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5518 Protect[2] = 0x01744004;
5522 // PROT_TXOP(25:20) -- 111111
5523 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5524 // PROT_CTRL(17:16) -- 00 (None)
5525 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5526 Protect[3] = 0x03f44084;
5530 // PROT_TXOP(25:20) -- 010111
5531 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5532 // PROT_CTRL(17:16) -- 00 (None)
5533 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5534 Protect[4] = 0x01744004;
5538 // PROT_TXOP(25:20) -- 111111
5539 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5540 // PROT_CTRL(17:16) -- 00 (None)
5541 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5542 Protect[5] = 0x03f44084;
5546 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5547 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5548 Protect[4] = 0x01754004;
5549 Protect[5] = 0x03f54084;
5551 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5555 // This is "HT non-member protection mode."
5556 // If there may be non-HT STAs my BSS
5557 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5558 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5559 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5561 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5562 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5564 //Assign Protection method for 20&40 MHz packets
5565 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5566 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5567 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5568 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5569 Protect[2] = ProtCfg.word;
5570 Protect[3] = ProtCfg4.word;
5571 Protect[4] = ProtCfg.word;
5572 Protect[5] = ProtCfg4.word;
5573 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5577 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5578 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5579 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5581 //Assign Protection method for 40MHz packets
5582 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5583 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5584 Protect[2] = ProtCfg.word;
5585 Protect[3] = ProtCfg4.word;
5588 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5589 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5591 Protect[4] = ProtCfg.word;
5592 Protect[5] = ProtCfg4.word;
5594 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5598 // HT mixed mode. PROTECT ALL!
5600 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5601 ProtCfg4.word = 0x03f44084;
5602 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5603 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5605 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5606 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5608 //Assign Protection method for 20&40 MHz packets
5609 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5610 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5611 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5612 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5613 Protect[2] = ProtCfg.word;
5614 Protect[3] = ProtCfg4.word;
5615 Protect[4] = ProtCfg.word;
5616 Protect[5] = ProtCfg4.word;
5617 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5621 Protect[2] = 0x01754004;
5622 Protect[3] = 0x03f54084;
5623 Protect[4] = 0x01754004;
5624 Protect[5] = 0x03f54084;
5625 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5629 #endif // DOT11_N_SUPPORT //
5631 offset = CCK_PROT_CFG;
5632 for (i = 0;i < 6;i++)
5634 if ((SetMask & (1<< i)))
5636 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5644 ========================================================================
5646 Routine Description: Write RT30xx RF register through MAC
5656 ========================================================================
5658 NTSTATUS RT30xxWriteRFRegister(
5659 IN PRTMP_ADAPTER pAd,
5663 RF_CSR_CFG_STRUC rfcsr;
5668 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5670 if (!rfcsr.field.RF_CSR_KICK)
5674 while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
5676 if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
5678 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
5679 return STATUS_UNSUCCESSFUL;
5682 rfcsr.field.RF_CSR_WR = 1;
5683 rfcsr.field.RF_CSR_KICK = 1;
5684 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5685 rfcsr.field.RF_CSR_DATA = Value;
5687 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5689 return STATUS_SUCCESS;
5694 ========================================================================
5696 Routine Description: Read RT30xx RF register through MAC
5706 ========================================================================
5708 NTSTATUS RT30xxReadRFRegister(
5709 IN PRTMP_ADAPTER pAd,
5713 RF_CSR_CFG_STRUC rfcsr;
5716 for (i=0; i<MAX_BUSY_COUNT; i++)
5718 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5720 if (rfcsr.field.RF_CSR_KICK == BUSY)
5725 rfcsr.field.RF_CSR_WR = 0;
5726 rfcsr.field.RF_CSR_KICK = 1;
5727 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5728 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5729 for (k=0; k<MAX_BUSY_COUNT; k++)
5731 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5733 if (rfcsr.field.RF_CSR_KICK == IDLE)
5736 if ((rfcsr.field.RF_CSR_KICK == IDLE) &&
5737 (rfcsr.field.TESTCSR_RFACC_REGNUM == RegID))
5739 *pValue = (UCHAR)rfcsr.field.RF_CSR_DATA;
5743 if (rfcsr.field.RF_CSR_KICK == BUSY)
5745 DBGPRINT_ERR(("RF read R%d=0x%x fail, i[%d], k[%d]\n", RegID, rfcsr.word,i,k));
5746 return STATUS_UNSUCCESSFUL;
5749 return STATUS_SUCCESS;
5754 // add by johnli, RF power sequence setup
5756 ==========================================================================
5759 Load RF normal operation-mode setup
5761 ==========================================================================
5763 VOID RT30xxLoadRFNormalModeSetup(
5764 IN PRTMP_ADAPTER pAd)
5768 // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1
5769 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5770 RFValue = (RFValue & (~0x0C)) | 0x31;
5771 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5773 // TX_LO2_en, RF R15 register Bit 3 to 0
5774 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5776 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5778 // TX_LO1_en, RF R17 register Bit 3 to 0
5779 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5781 // to fix rx long range issue
5782 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5786 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5788 // RX_LO1_en, RF R20 register Bit 3 to 0
5789 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5791 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5793 // RX_LO2_en, RF R21 register Bit 3 to 0
5794 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5796 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5798 // LDORF_VC, RF R27 register Bit 2 to 0
5799 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5800 if ((pAd->MACVersion & 0xffff) < 0x0211)
5801 RFValue = (RFValue & (~0x77)) | 0x3;
5803 RFValue = (RFValue & (~0x77));
5804 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5809 ==========================================================================
5812 Load RF sleep-mode setup
5814 ==========================================================================
5816 VOID RT30xxLoadRFSleepModeSetup(
5817 IN PRTMP_ADAPTER pAd)
5822 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5823 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5825 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5827 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5828 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5830 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5832 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5833 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5835 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5837 // RX_CTB_en, RF R21 register Bit 7 to 0
5838 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5840 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5842 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5843 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5845 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5847 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5848 MACValue |= 0x1D000000;
5849 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5853 ==========================================================================
5856 Reverse RF sleep-mode setup
5858 ==========================================================================
5860 VOID RT30xxReverseRFSleepModeSetup(
5861 IN PRTMP_ADAPTER pAd)
5866 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5867 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5869 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5871 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5872 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5874 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5876 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5877 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5879 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5881 // RX_CTB_en, RF R21 register Bit 7 to 1
5882 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5884 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5886 // LDORF_VC, RF R27 register Bit 2 to 0
5887 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5888 if ((pAd->MACVersion & 0xffff) < 0x0211)
5889 RFValue = (RFValue & (~0x77)) | 0x3;
5891 RFValue = (RFValue & (~0x77));
5892 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5894 // RT3071 version E has fixed this issue
5895 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5897 // patch tx EVM issue temporarily
5898 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5899 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5900 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5904 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5905 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5906 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5913 ==========================================================================
5916 IRQL = PASSIVE_LEVEL
5917 IRQL = DISPATCH_LEVEL
5919 ==========================================================================
5921 VOID AsicSwitchChannel(
5922 IN PRTMP_ADAPTER pAd,
5926 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5927 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5929 UINT32 Value = 0; //BbpReg, Value;
5930 RTMP_RF_REGS *RFRegTable;
5932 // Search Tx power value
5934 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5935 // in ChannelList, so use TxPower array instead.
5937 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5939 if (Channel == pAd->TxPower[index].Channel)
5941 TxPwer = pAd->TxPower[index].Power;
5942 TxPwer2 = pAd->TxPower[index].Power2;
5947 for (index = 0; index < pAd->ChannelListNum; index++)
5949 if (Channel == pAd->ChannelList[index].Channel)
5951 TxPwer = pAd->ChannelList[index].Power;
5952 TxPwer2 = pAd->ChannelList[index].Power2;
5958 if (index == MAX_NUM_OF_CHANNELS)
5960 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5964 // The RF programming sequence is difference between 3xxx and 2xxx
5965 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5966 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5968 /* modify by WY for Read RF Reg. error */
5971 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5973 if (Channel == FreqItems3020[index].Channel)
5975 // Programming channel parameters
5976 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5977 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5978 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5979 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5980 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5983 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5984 RFValue = (RFValue & 0xE0) | TxPwer;
5985 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5988 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5989 RFValue = (RFValue & 0xE0) | TxPwer2;
5990 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5992 // Tx/Rx Stream setting
5993 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5994 //if (IS_RT3090(pAd))
5995 // RFValue |= 0x01; // Enable RF block.
5996 RFValue &= 0x03; //clear bit[7~2]
5997 if (pAd->Antenna.field.TxPath == 1)
5999 else if (pAd->Antenna.field.TxPath == 2)
6001 if (pAd->Antenna.field.RxPath == 1)
6003 else if (pAd->Antenna.field.RxPath == 2)
6005 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
6008 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
6009 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
6010 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
6013 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6015 RFValue = pAd->Mlme.CaliBW40RfR24;
6016 //DISABLE_11N_CHECK(pAd);
6020 RFValue = pAd->Mlme.CaliBW20RfR24;
6022 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
6023 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
6026 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
6027 RFValue = RFValue | 0x1;
6028 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
6030 // latch channel for future usage.
6031 pAd->LatchRfRegs.Channel = Channel;
6033 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
6038 pAd->Antenna.field.TxPath,
6039 FreqItems3020[index].N,
6040 FreqItems3020[index].K,
6041 FreqItems3020[index].R));
6051 RFRegTable = RF2850RegTable;
6053 switch (pAd->RfIcType)
6060 for (index = 0; index < NUM_OF_2850_CHNL; index++)
6062 if (Channel == RFRegTable[index].Channel)
6064 R2 = RFRegTable[index].R2;
6065 if (pAd->Antenna.field.TxPath == 1)
6067 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
6070 if (pAd->Antenna.field.RxPath == 2)
6072 R2 |= 0x40; // write 1 to off Rxpath.
6074 else if (pAd->Antenna.field.RxPath == 1)
6076 R2 |= 0x20040; // write 1 to off RxPath
6081 // initialize R3, R4
6082 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
6083 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
6085 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
6087 if ((TxPwer >= -7) && (TxPwer < 0))
6089 TxPwer = (7+TxPwer);
6090 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
6091 R3 |= (TxPwer << 10);
6092 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
6096 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
6097 R3 |= (TxPwer << 10) | (1 << 9);
6101 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
6103 TxPwer2 = (7+TxPwer2);
6104 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6105 R4 |= (TxPwer2 << 7);
6106 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
6110 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
6111 R4 |= (TxPwer2 << 7) | (1 << 6);
6116 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
6117 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
6120 // Based on BBP current mode before changing RF channel.
6121 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
6127 pAd->LatchRfRegs.Channel = Channel;
6128 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
6129 pAd->LatchRfRegs.R2 = R2;
6130 pAd->LatchRfRegs.R3 = R3;
6131 pAd->LatchRfRegs.R4 = R4;
6133 // Set RF value 1's set R3[bit2] = [0]
6134 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6135 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6136 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6137 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6141 // Set RF value 2's set R3[bit2] = [1]
6142 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6143 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6144 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
6145 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6149 // Set RF value 3's set R3[bit2] = [0]
6150 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6151 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6152 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6153 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6165 // Change BBP setting during siwtch from a->g, g->a
6168 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
6170 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6171 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6172 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6173 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.
6174 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6176 // Rx High power VGA offset for LNA select
6177 if (pAd->NicConfig2.field.ExternalLNAForG)
6179 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6180 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6184 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6185 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6188 // 5G band selection PIN, bit1 and bit2 are complement
6189 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6192 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6194 // Turn off unused PA or LNA when only 1T or 1R
6195 if (pAd->Antenna.field.TxPath == 1)
6197 TxPinCfg &= 0xFFFFFFF3;
6199 if (pAd->Antenna.field.RxPath == 1)
6201 TxPinCfg &= 0xFFFFF3FF;
6204 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6208 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6210 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6211 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6212 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6213 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.
6214 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6216 // Rx High power VGA offset for LNA select
6217 if (pAd->NicConfig2.field.ExternalLNAForA)
6219 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6223 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6226 // 5G band selection PIN, bit1 and bit2 are complement
6227 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6230 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6232 // Turn off unused PA or LNA when only 1T or 1R
6233 if (pAd->Antenna.field.TxPath == 1)
6235 TxPinCfg &= 0xFFFFFFF3;
6237 if (pAd->Antenna.field.RxPath == 1)
6239 TxPinCfg &= 0xFFFFF3FF;
6242 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6245 // R66 should be set according to Channel and use 20MHz when scanning
6246 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6248 RTMPSetAGCInitValue(pAd, BW_20);
6250 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6253 // On 11A, We should delay and wait RF/BBP to be stable
6254 // and the appropriate time should be 1000 micro seconds
6255 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6257 RTMPusecDelay(1000);
6259 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",
6262 (R3 & 0x00003e00) >> 9,
6263 (R4 & 0x000007c0) >> 6,
6264 pAd->Antenna.field.TxPath,
6265 pAd->LatchRfRegs.R1,
6266 pAd->LatchRfRegs.R2,
6267 pAd->LatchRfRegs.R3,
6268 pAd->LatchRfRegs.R4));
6272 ==========================================================================
6274 This function is required for 2421 only, and should not be used during
6275 site survey. It's only required after NIC decided to stay at a channel
6276 for a longer period.
6277 When this function is called, it's always after AsicSwitchChannel().
6279 IRQL = PASSIVE_LEVEL
6280 IRQL = DISPATCH_LEVEL
6282 ==========================================================================
6284 VOID AsicLockChannel(
6285 IN PRTMP_ADAPTER pAd,
6291 ==========================================================================
6294 IRQL = PASSIVE_LEVEL
6295 IRQL = DISPATCH_LEVEL
6297 ==========================================================================
6299 VOID AsicAntennaSelect(
6300 IN PRTMP_ADAPTER pAd,
6303 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6305 // patch for AsicSetRxAnt failed
6306 pAd->RxAnt.EvaluatePeriod = 0;
6308 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6309 // valid indication of the distance between this AP and its clients.
6310 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6314 // if no traffic then reset average rssi to trigger evaluation
6315 #ifdef CONFIG_STA_SUPPORT
6316 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6318 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6319 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6320 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6323 pAd->StaCfg.NumOfAvgRssiSample = 0;
6324 #endif // CONFIG_STA_SUPPORT //
6325 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6327 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6329 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6330 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6332 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6333 AsicEvaluateRxAnt(pAd);
6338 // if not connected, always switch antenna to try to connect
6341 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6342 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6343 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6345 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6347 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6353 ========================================================================
6355 Routine Description:
6356 Antenna miscellaneous setting.
6359 pAd Pointer to our adapter
6360 BandState Indicate current Band State.
6365 IRQL <= DISPATCH_LEVEL
6368 1.) Frame End type control
6369 only valid for G only (RF_2527 & RF_2529)
6370 0: means DPDT, set BBP R4 bit 5 to 1
6371 1: means SPDT, set BBP R4 bit 5 to 0
6374 ========================================================================
6376 VOID AsicAntennaSetting(
6377 IN PRTMP_ADAPTER pAd,
6378 IN ABGBAND_STATE BandState)
6382 VOID AsicRfTuningExec(
6383 IN PVOID SystemSpecific1,
6384 IN PVOID FunctionContext,
6385 IN PVOID SystemSpecific2,
6386 IN PVOID SystemSpecific3)
6391 ==========================================================================
6393 Gives CCK TX rate 2 more dB TX power.
6394 This routine works only in LINK UP in INFRASTRUCTURE mode.
6396 calculate desired Tx power in RF R3.Tx0~5, should consider -
6397 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6398 1. TxPowerPercentage
6399 2. auto calibration based on TSSI feedback
6400 3. extra 2 db for CCK
6401 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6403 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6404 it should be called AFTER MlmeDynamicTxRatSwitching()
6405 ==========================================================================
6407 VOID AsicAdjustTxPower(
6408 IN PRTMP_ADAPTER pAd)
6412 BOOLEAN bAutoTxAgc = FALSE;
6413 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6414 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6415 PCHAR pTxAgcCompensate;
6421 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6423 if (pAd->CommonCfg.CentralChannel > 14)
6425 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6426 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6427 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6428 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6429 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6433 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6434 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6435 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6436 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6437 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6442 if (pAd->CommonCfg.Channel > 14)
6444 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6445 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6446 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6447 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6448 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6452 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6453 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6454 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6455 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6456 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6460 // TX power compensation for temperature variation based on TSSI. try every 4 second
6461 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6463 if (pAd->CommonCfg.Channel <= 14)
6466 bAutoTxAgc = pAd->bAutoTxAgcG;
6467 TssiRef = pAd->TssiRefG;
6468 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6469 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6470 TxAgcStep = pAd->TxAgcStepG;
6471 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6476 bAutoTxAgc = pAd->bAutoTxAgcA;
6477 TssiRef = pAd->TssiRefA;
6478 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6479 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6480 TxAgcStep = pAd->TxAgcStepA;
6481 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6486 /* BbpR1 is unsigned char */
6487 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6489 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6490 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6491 /* step value is defined in pAd->TxAgcStepG for tx power value */
6493 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6494 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6495 above value are examined in mass factory production */
6496 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6498 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6499 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6500 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6502 if (BbpR49 > pTssiMinusBoundary[1])
6504 // Reading is larger than the reference value
6505 // check for how large we need to decrease the Tx power
6506 for (idx = 1; idx < 5; idx++)
6508 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6511 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6512 // if (R3 > (ULONG) (TxAgcStep * (idx-1)))
6513 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6515 // *pTxAgcCompensate = -((UCHAR)R3);
6517 DeltaPwr += (*pTxAgcCompensate);
6518 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6519 BbpR49, TssiRef, TxAgcStep, idx-1));
6521 else if (BbpR49 < pTssiPlusBoundary[1])
6523 // Reading is smaller than the reference value
6524 // check for how large we need to increase the Tx power
6525 for (idx = 1; idx < 5; idx++)
6527 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6530 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6531 *pTxAgcCompensate = TxAgcStep * (idx-1);
6532 DeltaPwr += (*pTxAgcCompensate);
6533 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6534 BbpR49, TssiRef, TxAgcStep, idx-1));
6538 *pTxAgcCompensate = 0;
6539 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6540 BbpR49, TssiRef, TxAgcStep, 0));
6546 if (pAd->CommonCfg.Channel <= 14)
6548 bAutoTxAgc = pAd->bAutoTxAgcG;
6549 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6553 bAutoTxAgc = pAd->bAutoTxAgcA;
6554 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6558 DeltaPwr += (*pTxAgcCompensate);
6561 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6565 // Handle regulatory max tx power constrain
6568 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6569 UCHAR AdjustMaxTxPwr[40];
6571 if (pAd->CommonCfg.Channel > 14) // 5G band
6572 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6574 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6575 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6577 // error handling, range check
6578 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6580 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6584 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6586 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6588 // Adjust max tx power according to the relationship of tx power in E2PROM
6591 // CCK will have 4dBm larger than OFDM
6592 // Therefore, we should separate to parse the tx power field
6597 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6601 // CCK will have 4dBm larger than OFDM
6602 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6606 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6608 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6615 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6617 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6618 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6623 // Adjust tx power according to the relationship
6626 if (TxPwr[i] != 0xffffffff)
6630 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6632 // The system tx power is larger than the regulatory, the power should be restrain
6633 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6635 // decrease to zero and don't need to take care BBPR1
6636 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6637 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6641 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6644 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6646 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6651 #endif // SINGLE_SKU //
6653 /* calculate delta power based on the percentage specified from UI */
6654 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6655 // We lower TX power here according to the percentage specified from UI
6656 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6658 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6660 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6664 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6668 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6672 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6677 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6682 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6684 /* reset different new tx power for different TX rate */
6687 if (TxPwr[i] != 0xffffffff)
6691 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6693 if ((Value + DeltaPwr) < 0)
6695 Value = 0; /* min */
6697 else if ((Value + DeltaPwr) > 0xF)
6699 Value = 0xF; /* max */
6703 Value += DeltaPwr; /* temperature compensation */
6706 /* fill new value to CSR offset */
6707 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6710 /* write tx power value to CSR */
6711 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6712 TX power for OFDM 6M/9M
6713 TX power for CCK5.5M/11M
6714 TX power for CCK1M/2M */
6715 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6716 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6723 #ifdef CONFIG_STA_SUPPORT
6725 ==========================================================================
6727 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6728 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6729 the wakeup timer timeout. Driver has to issue a separate command to wake
6732 IRQL = DISPATCH_LEVEL
6734 ==========================================================================
6736 VOID AsicSleepThenAutoWakeup(
6737 IN PRTMP_ADAPTER pAd,
6738 IN USHORT TbttNumToNextWakeUp)
6740 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6744 ==========================================================================
6746 AsicForceWakeup() is used whenever manual wakeup is required
6747 AsicForceSleep() should only be used when not in INFRA BSS. When
6748 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6749 ==========================================================================
6751 VOID AsicForceSleep(
6752 IN PRTMP_ADAPTER pAd)
6758 ==========================================================================
6760 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6763 IRQL = PASSIVE_LEVEL
6764 IRQL = DISPATCH_LEVEL
6765 ==========================================================================
6767 VOID AsicForceWakeup(
6768 IN PRTMP_ADAPTER pAd,
6771 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6772 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6774 #endif // CONFIG_STA_SUPPORT //
6776 ==========================================================================
6780 IRQL = DISPATCH_LEVEL
6782 ==========================================================================
6785 IN PRTMP_ADAPTER pAd,
6789 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6790 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6792 Addr4 = (ULONG)(pBssid[0]) |
6793 (ULONG)(pBssid[1] << 8) |
6794 (ULONG)(pBssid[2] << 16) |
6795 (ULONG)(pBssid[3] << 24);
6796 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6799 // always one BSSID in STA mode
6800 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6802 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6805 VOID AsicSetMcastWC(
6806 IN PRTMP_ADAPTER pAd)
6808 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6811 pEntry->Sst = SST_ASSOC;
6812 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6813 pEntry->PsMode = PWR_ACTIVE;
6814 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6815 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6819 ==========================================================================
6822 IRQL = DISPATCH_LEVEL
6824 ==========================================================================
6826 VOID AsicDelWcidTab(
6827 IN PRTMP_ADAPTER pAd,
6830 ULONG Addr0 = 0x0, Addr1 = 0x0;
6833 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6834 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6835 RTMP_IO_WRITE32(pAd, offset, Addr0);
6837 RTMP_IO_WRITE32(pAd, offset, Addr1);
6841 ==========================================================================
6844 IRQL = DISPATCH_LEVEL
6846 ==========================================================================
6849 IN PRTMP_ADAPTER pAd)
6851 TX_LINK_CFG_STRUC TxLinkCfg;
6854 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6855 TxLinkCfg.field.TxRDGEn = 1;
6856 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6858 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6861 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6863 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6867 ==========================================================================
6870 IRQL = DISPATCH_LEVEL
6872 ==========================================================================
6874 VOID AsicDisableRDG(
6875 IN PRTMP_ADAPTER pAd)
6877 TX_LINK_CFG_STRUC TxLinkCfg;
6881 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6882 TxLinkCfg.field.TxRDGEn = 0;
6883 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6885 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6890 //if ( pAd->CommonCfg.bEnableTxBurst )
6891 // Data |= 0x60; // for performance issue not set the TXOP to 0
6893 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6894 #ifdef DOT11_N_SUPPORT
6895 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6896 #endif // DOT11_N_SUPPORT //
6899 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6900 if (pAd->CommonCfg.bEnableTxBurst)
6903 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6907 ==========================================================================
6910 IRQL = PASSIVE_LEVEL
6911 IRQL = DISPATCH_LEVEL
6913 ==========================================================================
6915 VOID AsicDisableSync(
6916 IN PRTMP_ADAPTER pAd)
6918 BCN_TIME_CFG_STRUC csr;
6920 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6922 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6923 // that NIC will never wakes up because TSF stops and no more
6925 pAd->TbttTickCount = 0;
6926 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6927 csr.field.bBeaconGen = 0;
6928 csr.field.bTBTTEnable = 0;
6929 csr.field.TsfSyncMode = 0;
6930 csr.field.bTsfTicking = 0;
6931 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6936 ==========================================================================
6939 IRQL = DISPATCH_LEVEL
6941 ==========================================================================
6943 VOID AsicEnableBssSync(
6944 IN PRTMP_ADAPTER pAd)
6946 BCN_TIME_CFG_STRUC csr;
6948 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6950 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6951 // RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);
6952 #ifdef CONFIG_STA_SUPPORT
6953 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6955 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6956 csr.field.bTsfTicking = 1;
6957 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6958 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6959 csr.field.bTBTTEnable = 1;
6961 #endif // CONFIG_STA_SUPPORT //
6962 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6966 ==========================================================================
6969 BEACON frame in shared memory should be built ok before this routine
6970 can be called. Otherwise, a garbage frame maybe transmitted out every
6973 IRQL = DISPATCH_LEVEL
6975 ==========================================================================
6977 VOID AsicEnableIbssSync(
6978 IN PRTMP_ADAPTER pAd)
6980 BCN_TIME_CFG_STRUC csr9;
6984 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6986 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6987 csr9.field.bBeaconGen = 0;
6988 csr9.field.bTBTTEnable = 0;
6989 csr9.field.bTsfTicking = 0;
6990 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6994 // move BEACON TXD and frame content to on-chip memory
6995 ptr = (PUCHAR)&pAd->BeaconTxWI;
6996 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6998 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6999 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
7000 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
7004 // start right after the 16-byte TXWI field
7005 ptr = pAd->BeaconBuf;
7006 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
7008 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
7009 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
7010 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
7016 // For Wi-Fi faily generated beacons between participating stations.
7017 // Set TBTT phase adaptive adjustment step to 8us (default 16us)
7018 // don't change settings 2006-5- by Jerry
7019 //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);
7021 // start sending BEACON
7022 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
7023 csr9.field.bTsfTicking = 1;
7024 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
7025 csr9.field.bTBTTEnable = 1;
7026 csr9.field.bBeaconGen = 1;
7027 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
7031 ==========================================================================
7034 IRQL = PASSIVE_LEVEL
7035 IRQL = DISPATCH_LEVEL
7037 ==========================================================================
7039 VOID AsicSetEdcaParm(
7040 IN PRTMP_ADAPTER pAd,
7041 IN PEDCA_PARM pEdcaParm)
7043 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
7044 AC_TXOP_CSR0_STRUC csr0;
7045 AC_TXOP_CSR1_STRUC csr1;
7046 AIFSN_CSR_STRUC AifsnCsr;
7047 CWMIN_CSR_STRUC CwminCsr;
7048 CWMAX_CSR_STRUC CwmaxCsr;
7055 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
7057 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
7058 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
7059 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
7061 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
7062 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
7065 //========================================================
7066 // MAC Register has a copy .
7067 //========================================================
7069 if( pAd->CommonCfg.bEnableTxBurst )
7071 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
7072 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
7075 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
7077 // Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
7079 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
7080 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
7081 Ac0Cfg.field.Aifsn = 2;
7082 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7084 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
7085 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
7086 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
7087 Ac1Cfg.field.Aifsn = 2;
7088 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7090 if (pAd->CommonCfg.PhyMode == PHY_11B)
7092 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
7093 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
7097 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
7098 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
7100 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
7101 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
7102 Ac2Cfg.field.Aifsn = 2;
7103 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7104 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
7105 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
7106 Ac3Cfg.field.Aifsn = 2;
7107 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7109 //========================================================
7110 // DMA Register has a copy too.
7111 //========================================================
7112 csr0.field.Ac0Txop = 0; // QID_AC_BE
7113 csr0.field.Ac1Txop = 0; // QID_AC_BK
7114 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7115 if (pAd->CommonCfg.PhyMode == PHY_11B)
7117 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
7118 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
7122 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
7123 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
7125 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7128 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
7129 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
7130 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
7131 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
7132 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7135 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
7136 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
7137 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
7138 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
7139 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7141 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
7143 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
7147 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
7148 //========================================================
7149 // MAC Register has a copy.
7150 //========================================================
7152 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
7153 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
7155 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
7157 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
7158 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
7159 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
7160 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
7162 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7163 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
7164 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
7165 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
7167 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
7168 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
7169 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
7170 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
7171 #ifdef INF_AMAZON_SE
7172 #endif // INF_AMAZON_SE //
7175 #ifdef CONFIG_STA_SUPPORT
7176 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7178 // Tuning for Wi-Fi WMM S06
7179 if (pAd->CommonCfg.bWiFiTest &&
7180 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7181 Ac2Cfg.field.Aifsn -= 1;
7183 // Tuning for TGn Wi-Fi 5.2.32
7184 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
7185 if (STA_TGN_WIFI_ON(pAd) &&
7186 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7188 Ac0Cfg.field.Aifsn = 3;
7189 Ac2Cfg.field.AcTxop = 5;
7193 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7195 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
7196 Ac2Cfg.field.Aifsn = 5;
7200 #endif // CONFIG_STA_SUPPORT //
7202 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
7203 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
7204 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
7205 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
7208 if (pAd->CommonCfg.bWiFiTest)
7210 if (Ac3Cfg.field.AcTxop == 102)
7212 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
7213 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
7214 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
7215 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
7216 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
7219 //#endif // WIFI_TEST //
7221 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
7222 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
7223 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
7224 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
7227 //========================================================
7228 // DMA Register has a copy too.
7229 //========================================================
7230 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
7231 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
7232 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
7234 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
7235 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
7236 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
7239 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
7240 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
7241 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
7242 #ifdef CONFIG_STA_SUPPORT
7243 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7244 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
7245 #endif // CONFIG_STA_SUPPORT //
7246 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7249 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
7250 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7251 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7252 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7253 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7256 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7257 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7258 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7259 #ifdef INF_AMAZON_SE
7260 #endif // INF_AMAZON_SE //
7263 #ifdef CONFIG_STA_SUPPORT
7264 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7266 // Tuning for Wi-Fi WMM S06
7267 if (pAd->CommonCfg.bWiFiTest &&
7268 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7269 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7271 // Tuning for TGn Wi-Fi 5.2.32
7272 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
7273 if (STA_TGN_WIFI_ON(pAd) &&
7274 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7276 AifsnCsr.field.Aifsn0 = 3;
7277 AifsnCsr.field.Aifsn2 = 7;
7281 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7283 #endif // CONFIG_STA_SUPPORT //
7285 #ifdef CONFIG_STA_SUPPORT
7286 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7287 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7289 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7291 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7292 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7295 #endif // CONFIG_STA_SUPPORT //
7296 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7298 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7301 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7302 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7303 pEdcaParm->Aifsn[0],
7304 pEdcaParm->Cwmin[0],
7305 pEdcaParm->Cwmax[0],
7306 pEdcaParm->Txop[0]<<5,
7307 pEdcaParm->bACM[0]));
7308 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7309 pEdcaParm->Aifsn[1],
7310 pEdcaParm->Cwmin[1],
7311 pEdcaParm->Cwmax[1],
7312 pEdcaParm->Txop[1]<<5,
7313 pEdcaParm->bACM[1]));
7314 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7315 pEdcaParm->Aifsn[2],
7316 pEdcaParm->Cwmin[2],
7317 pEdcaParm->Cwmax[2],
7318 pEdcaParm->Txop[2]<<5,
7319 pEdcaParm->bACM[2]));
7320 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7321 pEdcaParm->Aifsn[3],
7322 pEdcaParm->Cwmin[3],
7323 pEdcaParm->Cwmax[3],
7324 pEdcaParm->Txop[3]<<5,
7325 pEdcaParm->bACM[3]));
7331 ==========================================================================
7334 IRQL = PASSIVE_LEVEL
7335 IRQL = DISPATCH_LEVEL
7337 ==========================================================================
7339 VOID AsicSetSlotTime(
7340 IN PRTMP_ADAPTER pAd,
7341 IN BOOLEAN bUseShortSlotTime)
7344 UINT32 RegValue = 0;
7346 #ifdef CONFIG_STA_SUPPORT
7347 if (pAd->CommonCfg.Channel > 14)
7348 bUseShortSlotTime = TRUE;
7349 #endif // CONFIG_STA_SUPPORT //
7351 if (bUseShortSlotTime)
7352 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7354 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7356 SlotTime = (bUseShortSlotTime)? 9 : 20;
7358 #ifdef CONFIG_STA_SUPPORT
7359 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7361 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7362 if (pAd->CommonCfg.bEnableTxBurst)
7365 #endif // CONFIG_STA_SUPPORT //
7368 // For some reasons, always set it to short slot time.
7370 // ToDo: Should consider capability with 11B
7372 #ifdef CONFIG_STA_SUPPORT
7373 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7375 if (pAd->StaCfg.BssType == BSS_ADHOC)
7378 #endif // CONFIG_STA_SUPPORT //
7380 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7381 RegValue = RegValue & 0xFFFFFF00;
7383 RegValue |= SlotTime;
7385 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7389 ========================================================================
7391 Add Shared key information into ASIC.
7392 Update shared key, TxMic and RxMic to Asic Shared key table
7393 Update its cipherAlg to Asic Shared key Mode.
7396 ========================================================================
7398 VOID AsicAddSharedKeyEntry(
7399 IN PRTMP_ADAPTER pAd,
7407 ULONG offset; //, csr0;
7408 SHAREDKEY_MODE_STRUC csr1;
7410 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7411 //============================================================================================
7413 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7414 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7415 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]));
7418 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7419 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7423 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7424 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7426 //============================================================================================
7428 // fill key material - key + TX MIC + RX MIC
7433 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7434 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7436 offset += MAX_LEN_OF_SHARE_KEY;
7439 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7445 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7451 // Update cipher algorithm. WSTA always use BSS0
7453 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7454 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7455 if ((BssIndex%2) == 0)
7458 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7459 else if (KeyIdx == 1)
7460 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7461 else if (KeyIdx == 2)
7462 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7464 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7469 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7470 else if (KeyIdx == 1)
7471 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7472 else if (KeyIdx == 2)
7473 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7475 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7477 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7478 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7482 // IRQL = DISPATCH_LEVEL
7483 VOID AsicRemoveSharedKeyEntry(
7484 IN PRTMP_ADAPTER pAd,
7489 SHAREDKEY_MODE_STRUC csr1;
7491 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7493 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7494 if ((BssIndex%2) == 0)
7497 csr1.field.Bss0Key0CipherAlg = 0;
7498 else if (KeyIdx == 1)
7499 csr1.field.Bss0Key1CipherAlg = 0;
7500 else if (KeyIdx == 2)
7501 csr1.field.Bss0Key2CipherAlg = 0;
7503 csr1.field.Bss0Key3CipherAlg = 0;
7508 csr1.field.Bss1Key0CipherAlg = 0;
7509 else if (KeyIdx == 1)
7510 csr1.field.Bss1Key1CipherAlg = 0;
7511 else if (KeyIdx == 2)
7512 csr1.field.Bss1Key2CipherAlg = 0;
7514 csr1.field.Bss1Key3CipherAlg = 0;
7516 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7517 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7518 ASSERT(BssIndex < 4);
7524 VOID AsicUpdateWCIDAttribute(
7525 IN PRTMP_ADAPTER pAd,
7529 IN BOOLEAN bUsePairewiseKeyTable)
7531 ULONG WCIDAttri = 0, offset;
7534 // Update WCID attribute.
7535 // Only TxKey could update WCID attribute.
7537 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7538 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7539 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7542 VOID AsicUpdateWCIDIVEIV(
7543 IN PRTMP_ADAPTER pAd,
7550 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7552 RTMP_IO_WRITE32(pAd, offset, uIV);
7553 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7556 VOID AsicUpdateRxWCIDTable(
7557 IN PRTMP_ADAPTER pAd,
7564 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7565 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7566 RTMP_IO_WRITE32(pAd, offset, Addr);
7567 Addr = pAddr[4] + (pAddr[5] << 8);
7568 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7573 ========================================================================
7575 Routine Description:
7576 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7579 pAd Pointer to our adapter
7580 WCID WCID Entry number.
7581 BssIndex BSSID index, station or none multiple BSSID support
7582 this value should be 0.
7583 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7584 pCipherKey Pointer to Cipher Key.
7585 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7586 otherwise PairewiseKey table
7587 bTxKey This is the transmit key if enabled.
7593 This routine will set the relative key stuff to Asic including WCID attribute,
7594 Cipher Key, Cipher algorithm and IV/EIV.
7596 IV/EIV will be update if this CipherKey is the transmission key because
7597 ASIC will base on IV's KeyID value to select Cipher Key.
7599 If bTxKey sets to FALSE, this is not the TX key, but it could be
7602 For AP mode bTxKey must be always set to TRUE.
7603 ========================================================================
7605 VOID AsicAddKeyEntry(
7606 IN PRTMP_ADAPTER pAd,
7610 IN PCIPHER_KEY pCipherKey,
7611 IN BOOLEAN bUsePairewiseKeyTable,
7615 // ULONG WCIDAttri = 0;
7617 PUCHAR pKey = pCipherKey->Key;
7618 // ULONG KeyLen = pCipherKey->KeyLen;
7619 PUCHAR pTxMic = pCipherKey->TxMic;
7620 PUCHAR pRxMic = pCipherKey->RxMic;
7621 PUCHAR pTxtsc = pCipherKey->TxTsc;
7622 UCHAR CipherAlg = pCipherKey->CipherAlg;
7623 SHAREDKEY_MODE_STRUC csr1;
7625 // ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY);
7627 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7629 // 1.) decide key table offset
7631 if (bUsePairewiseKeyTable)
7632 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7634 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7637 // 2.) Set Key to Asic
7639 //for (i = 0; i < KeyLen; i++)
7642 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7643 offset += MAX_LEN_OF_PEER_KEY;
7646 // 3.) Set MIC key if available
7650 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7652 offset += LEN_TKIP_TXMICK;
7656 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7661 // 4.) Modify IV/EIV if needs
7662 // This will force Asic to use this key ID by setting IV.
7673 IV4 = (KeyIdx << 6);
7674 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7675 IV4 |= 0x20; // turn on extension bit means EIV existence
7677 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7678 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7684 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7686 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7689 if (!bUsePairewiseKeyTable)
7692 // Only update the shared key security mode
7694 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7695 if ((BssIndex % 2) == 0)
7698 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7699 else if (KeyIdx == 1)
7700 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7701 else if (KeyIdx == 2)
7702 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7704 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7709 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7710 else if (KeyIdx == 1)
7711 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7712 else if (KeyIdx == 2)
7713 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7715 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7717 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7720 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7725 ========================================================================
7727 Add Pair-wise key material into ASIC.
7728 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7731 ========================================================================
7733 VOID AsicAddPairwiseKeyEntry(
7734 IN PRTMP_ADAPTER pAd,
7737 IN CIPHER_KEY *pCipherKey)
7741 PUCHAR pKey = pCipherKey->Key;
7742 PUCHAR pTxMic = pCipherKey->TxMic;
7743 PUCHAR pRxMic = pCipherKey->RxMic;
7745 UCHAR CipherAlg = pCipherKey->CipherAlg;
7749 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7751 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7753 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7756 RTMP_IO_READ32(pAd, offset + i, &Value);
7759 offset += MAX_LEN_OF_PEER_KEY;
7765 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7772 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7776 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7777 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7778 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]));
7781 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7782 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7786 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7787 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7791 ========================================================================
7793 Remove Pair-wise key material from ASIC.
7796 ========================================================================
7798 VOID AsicRemovePairwiseKeyEntry(
7799 IN PRTMP_ADAPTER pAd,
7806 // re-set the entry's WCID attribute as OPEN-NONE.
7807 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7808 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7809 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7812 BOOLEAN AsicSendCommandToMcu(
7813 IN PRTMP_ADAPTER pAd,
7819 HOST_CMD_CSR_STRUC H2MCmd;
7820 H2M_MAILBOX_STRUC H2MMailbox;
7824 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7825 if (H2MMailbox.field.Owner == 0)
7834 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7840 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7841 H2MMailbox.field.CmdToken = Token;
7842 H2MMailbox.field.HighByte = Arg1;
7843 H2MMailbox.field.LowByte = Arg0;
7844 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7847 H2MCmd.field.HostCommand = Command;
7848 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7850 if (Command != 0x80)
7859 ========================================================================
7861 Routine Description:
7862 Verify the support rate for different PHY type
7865 pAd Pointer to our adapter
7870 IRQL = PASSIVE_LEVEL
7872 ========================================================================
7874 VOID RTMPCheckRates(
7875 IN PRTMP_ADAPTER pAd,
7876 IN OUT UCHAR SupRate[],
7877 IN OUT UCHAR *SupRateLen)
7879 UCHAR RateIdx, i, j;
7880 UCHAR NewRate[12], NewRateLen;
7884 if (pAd->CommonCfg.PhyMode == PHY_11B)
7889 // Check for support rates exclude basic rate bit
7890 for (i = 0; i < *SupRateLen; i++)
7891 for (j = 0; j < RateIdx; j++)
7892 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7893 NewRate[NewRateLen++] = SupRate[i];
7895 *SupRateLen = NewRateLen;
7896 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7899 #ifdef CONFIG_STA_SUPPORT
7900 #ifdef DOT11_N_SUPPORT
7901 BOOLEAN RTMPCheckChannel(
7902 IN PRTMP_ADAPTER pAd,
7903 IN UCHAR CentralChannel,
7907 UCHAR UpperChannel = 0, LowerChannel = 0;
7908 UCHAR NoEffectChannelinList = 0;
7910 // Find upper and lower channel according to 40MHz current operation.
7911 if (CentralChannel < Channel)
7913 UpperChannel = Channel;
7914 if (CentralChannel > 2)
7915 LowerChannel = CentralChannel - 2;
7919 else if (CentralChannel > Channel)
7921 UpperChannel = CentralChannel + 2;
7922 LowerChannel = Channel;
7925 for (k = 0;k < pAd->ChannelListNum;k++)
7927 if (pAd->ChannelList[k].Channel == UpperChannel)
7929 NoEffectChannelinList ++;
7931 if (pAd->ChannelList[k].Channel == LowerChannel)
7933 NoEffectChannelinList ++;
7937 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7938 if (NoEffectChannelinList == 2)
7945 ========================================================================
7947 Routine Description:
7948 Verify the support rate for HT phy type
7951 pAd Pointer to our adapter
7954 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7956 IRQL = PASSIVE_LEVEL
7958 ========================================================================
7960 BOOLEAN RTMPCheckHt(
7961 IN PRTMP_ADAPTER pAd,
7963 IN HT_CAPABILITY_IE *pHtCapability,
7964 IN ADD_HT_INFO_IE *pAddHtInfo)
7966 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7969 // If use AMSDU, set flag.
7970 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7971 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7972 // Save Peer Capability
7973 if (pHtCapability->HtCapInfo.ShortGIfor20)
7974 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7975 if (pHtCapability->HtCapInfo.ShortGIfor40)
7976 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7977 if (pHtCapability->HtCapInfo.TxSTBC)
7978 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7979 if (pHtCapability->HtCapInfo.RxSTBC)
7980 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7981 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7983 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7986 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7988 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7991 // Will check ChannelWidth for MCSSet[4] below
7992 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7993 switch (pAd->CommonCfg.RxStream)
7996 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7997 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7998 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7999 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8002 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8003 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
8004 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
8005 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8008 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
8009 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
8010 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
8011 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
8015 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
8017 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
8018 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
8019 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
8021 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
8023 // Send Assoc Req with my HT capability.
8024 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
8025 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
8026 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
8027 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
8028 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
8029 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
8030 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
8031 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
8032 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8033 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
8034 if (pAd->CommonCfg.bRdg)
8036 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
8037 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
8040 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
8041 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
8043 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
8046 #endif // DOT11_N_SUPPORT //
8047 #endif // CONFIG_STA_SUPPORT //
8050 ========================================================================
8052 Routine Description:
8053 Verify the support rate for different PHY type
8056 pAd Pointer to our adapter
8061 IRQL = PASSIVE_LEVEL
8063 ========================================================================
8065 VOID RTMPUpdateMlmeRate(
8066 IN PRTMP_ADAPTER pAd)
8069 UCHAR ProperMlmeRate; //= RATE_54;
8070 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
8071 BOOLEAN bMatch = FALSE;
8073 switch (pAd->CommonCfg.PhyMode)
8076 ProperMlmeRate = RATE_11;
8077 MinimumRate = RATE_1;
8079 case PHY_11BG_MIXED:
8080 #ifdef DOT11_N_SUPPORT
8081 case PHY_11ABGN_MIXED:
8082 case PHY_11BGN_MIXED:
8083 #endif // DOT11_N_SUPPORT //
8084 if ((pAd->MlmeAux.SupRateLen == 4) &&
8085 (pAd->MlmeAux.ExtRateLen == 0))
8087 ProperMlmeRate = RATE_11;
8089 ProperMlmeRate = RATE_24;
8091 if (pAd->MlmeAux.Channel <= 14)
8092 MinimumRate = RATE_1;
8094 MinimumRate = RATE_6;
8097 #ifdef DOT11_N_SUPPORT
8098 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
8099 case PHY_11GN_MIXED:
8100 case PHY_11AGN_MIXED:
8101 case PHY_11AN_MIXED:
8103 #endif // DOT11_N_SUPPORT //
8104 ProperMlmeRate = RATE_24;
8105 MinimumRate = RATE_6;
8107 case PHY_11ABG_MIXED:
8108 ProperMlmeRate = RATE_24;
8109 if (pAd->MlmeAux.Channel <= 14)
8110 MinimumRate = RATE_1;
8112 MinimumRate = RATE_6;
8115 ProperMlmeRate = RATE_1;
8116 MinimumRate = RATE_1;
8120 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
8122 for (j = 0; j < RateIdx; j++)
8124 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
8126 if (j == ProperMlmeRate)
8138 if (bMatch == FALSE)
8140 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
8142 for (j = 0; j < RateIdx; j++)
8144 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
8146 if (j == ProperMlmeRate)
8159 if (bMatch == FALSE)
8161 ProperMlmeRate = MinimumRate;
8164 pAd->CommonCfg.MlmeRate = MinimumRate;
8165 pAd->CommonCfg.RtsRate = ProperMlmeRate;
8166 if (pAd->CommonCfg.MlmeRate >= RATE_6)
8168 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
8169 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8170 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
8171 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
8175 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
8176 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
8177 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
8178 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
8181 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
8185 IN PRTMP_ADAPTER pAd,
8192 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
8197 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
8199 larger = max(Rssi0, Rssi1);
8202 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
8204 larger = max(larger, Rssi2);
8214 // Antenna divesity use GPIO3 and EESK pin for control
8215 // Antenna and EEPROM access are both using EESK pin,
8216 // Therefor we should avoid accessing EESK at the same time
8217 // Then restore antenna after EEPROM access
8219 IN PRTMP_ADAPTER pAd,
8226 if ((pAd->EepromAccess) ||
8227 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
8228 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
8229 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
8230 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
8235 // the antenna selection is through firmware and MAC register(GPIO3)
8239 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8241 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8243 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8245 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8246 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8251 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8253 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8255 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8258 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8259 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8266 ========================================================================
8267 Routine Description:
8268 Periodic evaluate antenna link status
8271 pAd - Adapter pointer
8276 ========================================================================
8278 VOID AsicEvaluateRxAnt(
8279 IN PRTMP_ADAPTER pAd)
8283 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8284 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8285 fRTMP_ADAPTER_RADIO_OFF |
8286 fRTMP_ADAPTER_NIC_NOT_EXIST |
8287 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
8288 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8290 || (pAd->EepromAccess)
8296 #ifdef CONFIG_STA_SUPPORT
8297 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8299 //if (pAd->StaCfg.Psm == PWR_SAVE)
8302 #endif // CONFIG_STA_SUPPORT //
8304 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8305 // one is antenna diversity:there is only one antenna can rx and tx
8306 // the other is failed antenna remove:two physical antenna can rx and tx
8307 if (pAd->NicConfig2.field.AntDiversity)
8309 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8310 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8312 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8314 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8315 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8316 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8318 // a one-shot timer to end the evalution
8319 // dynamic adjust antenna evaluation period according to the traffic
8320 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8321 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8323 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8328 #ifdef CONFIG_STA_SUPPORT
8329 if (pAd->StaCfg.Psm == PWR_SAVE)
8331 #endif // CONFIG_STA_SUPPORT //
8333 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8335 if(pAd->Antenna.field.RxPath == 3)
8339 else if(pAd->Antenna.field.RxPath == 2)
8343 else if(pAd->Antenna.field.RxPath == 1)
8347 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8348 #ifdef CONFIG_STA_SUPPORT
8349 #endif // CONFIG_STA_SUPPORT //
8350 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8353 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8354 pAd->RalinkCounters.OneSecTxRetryOkCount +
8355 pAd->RalinkCounters.OneSecTxFailCount;
8357 // dynamic adjust antenna evaluation period according to the traffic
8358 if (TxTotalCnt > 50)
8360 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8361 pAd->Mlme.bLowThroughput = FALSE;
8365 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8366 pAd->Mlme.bLowThroughput = TRUE;
8373 ========================================================================
8374 Routine Description:
8375 After evaluation, check antenna link status
8378 pAd - Adapter pointer
8383 ========================================================================
8385 VOID AsicRxAntEvalTimeout(
8386 IN PVOID SystemSpecific1,
8387 IN PVOID FunctionContext,
8388 IN PVOID SystemSpecific2,
8389 IN PVOID SystemSpecific3)
8391 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8392 #ifdef CONFIG_STA_SUPPORT
8394 CHAR larger = -127, rssi0, rssi1, rssi2;
8395 #endif // CONFIG_STA_SUPPORT //
8397 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8398 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8399 fRTMP_ADAPTER_RADIO_OFF |
8400 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
8401 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8403 || (pAd->EepromAccess)
8409 #ifdef CONFIG_STA_SUPPORT
8410 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8412 //if (pAd->StaCfg.Psm == PWR_SAVE)
8415 if (pAd->NicConfig2.field.AntDiversity)
8417 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8422 // select PrimaryRxAntPair
8423 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8424 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8426 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8427 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8428 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8430 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8431 pAd->RxAnt.EvaluateStableCnt = 0;
8435 // if the evaluated antenna is not better than original, switch back to original antenna
8436 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8437 pAd->RxAnt.EvaluateStableCnt ++;
8440 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8442 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8443 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8447 if (pAd->StaCfg.Psm == PWR_SAVE)
8450 // if the traffic is low, use average rssi as the criteria
8451 if (pAd->Mlme.bLowThroughput == TRUE)
8453 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8454 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8455 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8459 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8460 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8461 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8464 if(pAd->Antenna.field.RxPath == 3)
8466 larger = max(rssi0, rssi1);
8468 if (larger > (rssi2 + 20))
8469 pAd->Mlme.RealRxPath = 2;
8471 pAd->Mlme.RealRxPath = 3;
8473 else if(pAd->Antenna.field.RxPath == 2)
8475 if (rssi0 > (rssi1 + 20))
8476 pAd->Mlme.RealRxPath = 1;
8478 pAd->Mlme.RealRxPath = 2;
8481 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8483 if(pAd->Mlme.RealRxPath == 3)
8487 else if(pAd->Mlme.RealRxPath == 2)
8491 else if(pAd->Mlme.RealRxPath == 1)
8495 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8499 #endif // CONFIG_STA_SUPPORT //
8505 VOID APSDPeriodicExec(
8506 IN PVOID SystemSpecific1,
8507 IN PVOID FunctionContext,
8508 IN PVOID SystemSpecific2,
8509 IN PVOID SystemSpecific3)
8511 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8513 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8516 pAd->CommonCfg.TriggerTimerCount++;
8518 // Driver should not send trigger frame, it should be send by application layer
8520 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
8521 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
8522 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
8524 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
8525 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
8526 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
8527 pAd->CommonCfg.TriggerTimerCount = 0;
8528 pAd->CommonCfg.bInServicePeriod = TRUE;
8533 ========================================================================
8534 Routine Description:
8535 Set/reset MAC registers according to bPiggyBack parameter
8538 pAd - Adapter pointer
8539 bPiggyBack - Enable / Disable Piggy-Back
8544 ========================================================================
8546 VOID RTMPSetPiggyBack(
8547 IN PRTMP_ADAPTER pAd,
8548 IN BOOLEAN bPiggyBack)
8550 TX_LINK_CFG_STRUC TxLinkCfg;
8552 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8554 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8555 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8559 ========================================================================
8560 Routine Description:
8561 check if this entry need to switch rate automatically
8571 ========================================================================
8573 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8574 IN PRTMP_ADAPTER pAd,
8575 IN PMAC_TABLE_ENTRY pEntry)
8577 BOOLEAN result = TRUE;
8580 #ifdef CONFIG_STA_SUPPORT
8581 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8583 // only associated STA counts
8584 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8586 result = pAd->StaCfg.bAutoTxRateSwitch;
8591 #endif // CONFIG_STA_SUPPORT //
8599 BOOLEAN RTMPAutoRateSwitchCheck(
8600 IN PRTMP_ADAPTER pAd)
8603 #ifdef CONFIG_STA_SUPPORT
8604 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8606 if (pAd->StaCfg.bAutoTxRateSwitch)
8609 #endif // CONFIG_STA_SUPPORT //
8615 ========================================================================
8616 Routine Description:
8617 check if this entry need to fix tx legacy rate
8627 ========================================================================
8629 UCHAR RTMPStaFixedTxMode(
8630 IN PRTMP_ADAPTER pAd,
8631 IN PMAC_TABLE_ENTRY pEntry)
8633 UCHAR tx_mode = FIXED_TXMODE_HT;
8636 #ifdef CONFIG_STA_SUPPORT
8637 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8639 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8641 #endif // CONFIG_STA_SUPPORT //
8647 ========================================================================
8648 Routine Description:
8649 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8659 ========================================================================
8661 VOID RTMPUpdateLegacyTxSetting(
8662 UCHAR fixed_tx_mode,
8663 PMAC_TABLE_ENTRY pEntry)
8665 HTTRANSMIT_SETTING TransmitSetting;
8667 if (fixed_tx_mode == FIXED_TXMODE_HT)
8670 TransmitSetting.word = 0;
8672 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8673 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8675 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8677 TransmitSetting.field.MODE = MODE_CCK;
8678 // CCK mode allow MCS 0~3
8679 if (TransmitSetting.field.MCS > MCS_3)
8680 TransmitSetting.field.MCS = MCS_3;
8684 TransmitSetting.field.MODE = MODE_OFDM;
8685 // OFDM mode allow MCS 0~7
8686 if (TransmitSetting.field.MCS > MCS_7)
8687 TransmitSetting.field.MCS = MCS_7;
8690 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8692 pEntry->HTPhyMode.word = TransmitSetting.word;
8693 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8694 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8698 #ifdef CONFIG_STA_SUPPORT
8700 ==========================================================================
8702 dynamic tune BBP R66 to find a balance between sensibility and
8705 IRQL = DISPATCH_LEVEL
8707 ==========================================================================
8709 VOID AsicStaBbpTuning(
8710 IN PRTMP_ADAPTER pAd)
8712 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8715 // 2860C did not support Fase CCA, therefore can't tune
8716 if (pAd->MACVersion == 0x28600100)
8722 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8725 if ((pAd->OpMode == OPMODE_STA)
8726 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8728 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8731 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8734 if (pAd->Antenna.field.RxPath > 1)
8735 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8737 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8739 if (pAd->LatchRfRegs.Channel <= 14)
8742 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8743 // Otherwise, it will have some throughput side effect when low RSSI
8746 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8748 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8749 if (OrigR66Value != R66)
8751 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8756 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8757 if (OrigR66Value != R66)
8759 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8766 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8768 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8769 if (OrigR66Value != R66)
8771 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8776 R66 = 0x2E + GET_LNA_GAIN(pAd);
8777 if (OrigR66Value != R66)
8779 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8787 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8789 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8791 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8792 if (OrigR66Value != R66)
8794 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8799 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8800 if (OrigR66Value != R66)
8802 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8808 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8810 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8811 if (OrigR66Value != R66)
8813 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8818 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8819 if (OrigR66Value != R66)
8821 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8830 #endif // CONFIG_STA_SUPPORT //
8832 VOID RTMPSetAGCInitValue(
8833 IN PRTMP_ADAPTER pAd,
8838 if (pAd->LatchRfRegs.Channel <= 14)
8840 R66 = 0x2E + GET_LNA_GAIN(pAd);
8841 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8845 if (BandWidth == BW_20)
8847 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8848 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8850 #ifdef DOT11_N_SUPPORT
8853 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8854 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8856 #endif // DOT11_N_SUPPORT //
8861 VOID AsicTurnOffRFClk(
8862 IN PRTMP_ADAPTER pAd,
8866 UINT32 R1 = 0, R2 = 0, R3 = 0;
8868 RTMP_RF_REGS *RFRegTable;
8871 // The RF programming sequence is difference between 3xxx and 2xxx
8874 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
8879 RFRegTable = RF2850RegTable;
8881 switch (pAd->RfIcType)
8888 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8890 if (Channel == RFRegTable[index].Channel)
8892 R1 = RFRegTable[index].R1 & 0xffffdfff;
8893 R2 = RFRegTable[index].R2 & 0xfffbffff;
8894 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8896 RTMP_RF_IO_WRITE32(pAd, R1);
8897 RTMP_RF_IO_WRITE32(pAd, R2);
8899 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8900 // Set RF R2 bit18=0, R3 bit[18:19]=0
8901 //if (pAd->StaCfg.bRadio == FALSE)
8904 RTMP_RF_IO_WRITE32(pAd, R3);
8906 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8907 Channel, pAd->RfIcType, R2, R3));
8910 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8911 Channel, pAd->RfIcType, R2));
8927 VOID AsicTurnOnRFClk(
8928 IN PRTMP_ADAPTER pAd,
8932 UINT32 R1 = 0, R2 = 0, R3 = 0;
8934 RTMP_RF_REGS *RFRegTable;
8937 // The RF programming sequence is difference between 3xxx and 2xxx
8944 RFRegTable = RF2850RegTable;
8946 switch (pAd->RfIcType)
8953 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8955 if (Channel == RFRegTable[index].Channel)
8957 R3 = pAd->LatchRfRegs.R3;
8960 RTMP_RF_IO_WRITE32(pAd, R3);
8962 R1 = RFRegTable[index].R1;
8963 RTMP_RF_IO_WRITE32(pAd, R1);
8965 R2 = RFRegTable[index].R2;
8966 if (pAd->Antenna.field.TxPath == 1)
8968 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8971 if (pAd->Antenna.field.RxPath == 2)
8973 R2 |= 0x40; // write 1 to off Rxpath.
8975 else if (pAd->Antenna.field.RxPath == 1)
8977 R2 |= 0x20040; // write 1 to off RxPath
8979 RTMP_RF_IO_WRITE32(pAd, R2);