2 *************************************************************************
4 * 5F., No.36, Taiyuan St., Jhubei City,
8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 *************************************************************************
34 -------- ---------- ----------------------------------------------
35 John Chang 2004-08-25 Modify from RT2500 code base
36 John Chang 2004-09-06 modified for RT2600
39 #include "../rt_config.h"
42 UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96};
44 UCHAR WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
45 UCHAR RSN_OUI[] = {0x00, 0x0f, 0xac};
46 UCHAR WAPI_OUI[] = {0x00, 0x14, 0x72};
47 UCHAR WME_INFO_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
48 UCHAR WME_PARM_ELEM[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
49 UCHAR Ccx2QosInfo[] = {0x00, 0x40, 0x96, 0x04};
50 UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43};
51 UCHAR BROADCOM_OUI[] = {0x00, 0x90, 0x4c};
52 UCHAR WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
53 #ifdef CONFIG_STA_SUPPORT
54 #ifdef DOT11_N_SUPPORT
55 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
56 #endif // DOT11_N_SUPPORT //
57 #endif // CONFIG_STA_SUPPORT //
59 UCHAR RateSwitchTable[] = {
60 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
61 0x11, 0x00, 0, 0, 0, // Initial used item after association
62 0x00, 0x00, 0, 40, 101,
63 0x01, 0x00, 1, 40, 50,
64 0x02, 0x00, 2, 35, 45,
65 0x03, 0x00, 3, 20, 45,
66 0x04, 0x21, 0, 30, 50,
67 0x05, 0x21, 1, 20, 50,
68 0x06, 0x21, 2, 20, 50,
69 0x07, 0x21, 3, 15, 50,
70 0x08, 0x21, 4, 15, 30,
71 0x09, 0x21, 5, 10, 25,
74 0x0c, 0x20, 12, 15, 30,
75 0x0d, 0x20, 13, 8, 20,
76 0x0e, 0x20, 14, 8, 20,
77 0x0f, 0x20, 15, 8, 25,
78 0x10, 0x22, 15, 8, 25,
96 UCHAR RateSwitchTable11B[] = {
97 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
98 0x04, 0x03, 0, 0, 0, // Initial used item after association
99 0x00, 0x00, 0, 40, 101,
100 0x01, 0x00, 1, 40, 50,
101 0x02, 0x00, 2, 35, 45,
102 0x03, 0x00, 3, 20, 45,
105 UCHAR RateSwitchTable11BG[] = {
106 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
107 0x0a, 0x00, 0, 0, 0, // Initial used item after association
108 0x00, 0x00, 0, 40, 101,
109 0x01, 0x00, 1, 40, 50,
110 0x02, 0x00, 2, 35, 45,
111 0x03, 0x00, 3, 20, 45,
112 0x04, 0x10, 2, 20, 35,
113 0x05, 0x10, 3, 16, 35,
114 0x06, 0x10, 4, 10, 25,
115 0x07, 0x10, 5, 16, 25,
116 0x08, 0x10, 6, 10, 25,
117 0x09, 0x10, 7, 10, 13,
120 UCHAR RateSwitchTable11G[] = {
121 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
122 0x08, 0x00, 0, 0, 0, // Initial used item after association
123 0x00, 0x10, 0, 20, 101,
124 0x01, 0x10, 1, 20, 35,
125 0x02, 0x10, 2, 20, 35,
126 0x03, 0x10, 3, 16, 35,
127 0x04, 0x10, 4, 10, 25,
128 0x05, 0x10, 5, 16, 25,
129 0x06, 0x10, 6, 10, 25,
130 0x07, 0x10, 7, 10, 13,
133 #ifdef DOT11_N_SUPPORT
134 UCHAR RateSwitchTable11N1S[] = {
135 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
136 0x09, 0x00, 0, 0, 0, // Initial used item after association
137 0x00, 0x21, 0, 30, 101,
138 0x01, 0x21, 1, 20, 50,
139 0x02, 0x21, 2, 20, 50,
140 0x03, 0x21, 3, 15, 50,
141 0x04, 0x21, 4, 15, 30,
142 0x05, 0x21, 5, 10, 25,
143 0x06, 0x21, 6, 8, 14,
144 0x07, 0x21, 7, 8, 14,
145 0x08, 0x23, 7, 8, 14,
148 UCHAR RateSwitchTable11N2S[] = {
149 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
150 0x0a, 0x00, 0, 0, 0, // Initial used item after association
151 0x00, 0x21, 0, 30, 101,
152 0x01, 0x21, 1, 20, 50,
153 0x02, 0x21, 2, 20, 50,
154 0x03, 0x21, 3, 15, 50,
155 0x04, 0x21, 4, 15, 30,
156 0x05, 0x20, 12, 15, 30,
157 0x06, 0x20, 13, 8, 20,
158 0x07, 0x20, 14, 8, 20,
159 0x08, 0x20, 15, 8, 25,
160 0x09, 0x22, 15, 8, 25,
163 UCHAR RateSwitchTable11N3S[] = {
164 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
165 0x0a, 0x00, 0, 0, 0, // Initial used item after association
166 0x00, 0x21, 0, 30, 101,
167 0x01, 0x21, 1, 20, 50,
168 0x02, 0x21, 2, 20, 50,
169 0x03, 0x21, 3, 15, 50,
170 0x04, 0x21, 4, 15, 30,
171 0x05, 0x20, 12, 15, 30,
172 0x06, 0x20, 13, 8, 20,
173 0x07, 0x20, 14, 8, 20,
174 0x08, 0x20, 15, 8, 25,
175 0x09, 0x22, 15, 8, 25,
178 UCHAR RateSwitchTable11N2SForABand[] = {
179 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
180 0x0b, 0x09, 0, 0, 0, // Initial used item after association
181 0x00, 0x21, 0, 30, 101,
182 0x01, 0x21, 1, 20, 50,
183 0x02, 0x21, 2, 20, 50,
184 0x03, 0x21, 3, 15, 50,
185 0x04, 0x21, 4, 15, 30,
186 0x05, 0x21, 5, 15, 30,
187 0x06, 0x20, 12, 15, 30,
188 0x07, 0x20, 13, 8, 20,
189 0x08, 0x20, 14, 8, 20,
190 0x09, 0x20, 15, 8, 25,
191 0x0a, 0x22, 15, 8, 25,
194 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
195 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
196 0x0b, 0x09, 0, 0, 0, // Initial used item after association
197 0x00, 0x21, 0, 30, 101,
198 0x01, 0x21, 1, 20, 50,
199 0x02, 0x21, 2, 20, 50,
200 0x03, 0x21, 3, 15, 50,
201 0x04, 0x21, 4, 15, 30,
202 0x05, 0x21, 5, 15, 30,
203 0x06, 0x20, 12, 15, 30,
204 0x07, 0x20, 13, 8, 20,
205 0x08, 0x20, 14, 8, 20,
206 0x09, 0x20, 15, 8, 25,
207 0x0a, 0x22, 15, 8, 25,
210 UCHAR RateSwitchTable11BGN1S[] = {
211 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
212 0x0d, 0x00, 0, 0, 0, // Initial used item after association
213 0x00, 0x00, 0, 40, 101,
214 0x01, 0x00, 1, 40, 50,
215 0x02, 0x00, 2, 35, 45,
216 0x03, 0x00, 3, 20, 45,
217 0x04, 0x21, 0, 30,101, //50
218 0x05, 0x21, 1, 20, 50,
219 0x06, 0x21, 2, 20, 50,
220 0x07, 0x21, 3, 15, 50,
221 0x08, 0x21, 4, 15, 30,
222 0x09, 0x21, 5, 10, 25,
223 0x0a, 0x21, 6, 8, 14,
224 0x0b, 0x21, 7, 8, 14,
225 0x0c, 0x23, 7, 8, 14,
228 UCHAR RateSwitchTable11BGN2S[] = {
229 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
230 0x0a, 0x00, 0, 0, 0, // Initial used item after association
231 0x00, 0x21, 0, 30,101, //50
232 0x01, 0x21, 1, 20, 50,
233 0x02, 0x21, 2, 20, 50,
234 0x03, 0x21, 3, 15, 50,
235 0x04, 0x21, 4, 15, 30,
236 0x05, 0x20, 12, 15, 30,
237 0x06, 0x20, 13, 8, 20,
238 0x07, 0x20, 14, 8, 20,
239 0x08, 0x20, 15, 8, 25,
240 0x09, 0x22, 15, 8, 25,
243 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
244 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
245 0x0a, 0x00, 0, 0, 0, // Initial used item after association
246 0x00, 0x21, 0, 30,101, //50
247 0x01, 0x21, 1, 20, 50,
248 0x02, 0x21, 2, 20, 50,
249 0x03, 0x21, 3, 20, 50,
250 0x04, 0x21, 4, 15, 50,
252 0x05, 0x20, 20, 15, 30,
253 0x06, 0x20, 21, 8, 20,
254 0x07, 0x20, 22, 8, 20,
255 0x08, 0x20, 23, 8, 25,
256 0x09, 0x22, 23, 8, 25,
257 #else // for RT2860 2*3 test
258 0x05, 0x20, 12, 15, 30,
259 0x06, 0x20, 13, 8, 20,
260 0x07, 0x20, 14, 8, 20,
261 0x08, 0x20, 15, 8, 25,
262 0x09, 0x22, 15, 8, 25,
266 UCHAR RateSwitchTable11BGN2SForABand[] = {
267 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
268 0x0b, 0x09, 0, 0, 0, // Initial used item after association
269 0x00, 0x21, 0, 30,101, //50
270 0x01, 0x21, 1, 20, 50,
271 0x02, 0x21, 2, 20, 50,
272 0x03, 0x21, 3, 15, 50,
273 0x04, 0x21, 4, 15, 30,
274 0x05, 0x21, 5, 15, 30,
275 0x06, 0x20, 12, 15, 30,
276 0x07, 0x20, 13, 8, 20,
277 0x08, 0x20, 14, 8, 20,
278 0x09, 0x20, 15, 8, 25,
279 0x0a, 0x22, 15, 8, 25,
282 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
283 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
284 0x0c, 0x09, 0, 0, 0, // Initial used item after association
285 0x00, 0x21, 0, 30,101, //50
286 0x01, 0x21, 1, 20, 50,
287 0x02, 0x21, 2, 20, 50,
288 0x03, 0x21, 3, 15, 50,
289 0x04, 0x21, 4, 15, 30,
290 0x05, 0x21, 5, 15, 30,
291 0x06, 0x21, 12, 15, 30,
292 0x07, 0x20, 20, 15, 30,
293 0x08, 0x20, 21, 8, 20,
294 0x09, 0x20, 22, 8, 20,
295 0x0a, 0x20, 23, 8, 25,
296 0x0b, 0x22, 23, 8, 25,
298 #endif // DOT11_N_SUPPORT //
300 PUCHAR ReasonString[] = {
302 /* 1 */ "Unspecified Reason",
303 /* 2 */ "Previous Auth no longer valid",
304 /* 3 */ "STA is leaving / has left",
305 /* 4 */ "DIS-ASSOC due to inactivity",
306 /* 5 */ "AP unable to hanle all associations",
307 /* 6 */ "class 2 error",
308 /* 7 */ "class 3 error",
309 /* 8 */ "STA is leaving / has left",
310 /* 9 */ "require auth before assoc/re-assoc",
314 /* 13 */ "invalid IE",
315 /* 14 */ "MIC error",
316 /* 15 */ "4-way handshake timeout",
317 /* 16 */ "2-way (group key) handshake timeout",
318 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
322 extern UCHAR OfdmRateToRxwiMCS[];
323 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
324 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
325 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
326 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
327 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
329 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
330 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
331 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
333 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
334 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
335 // clean environment.
336 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
337 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
339 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
340 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
342 UCHAR SsidIe = IE_SSID;
343 UCHAR SupRateIe = IE_SUPP_RATES;
344 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
345 #ifdef DOT11_N_SUPPORT
346 UCHAR HtCapIe = IE_HT_CAP;
347 UCHAR AddHtInfoIe = IE_ADD_HT;
348 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
350 UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
351 #endif // DOT11N_DRAFT3 //
352 #endif // DOT11_N_SUPPORT //
353 UCHAR ErpIe = IE_ERP;
354 UCHAR DsIe = IE_DS_PARM;
355 UCHAR TimIe = IE_TIM;
356 UCHAR WpaIe = IE_WPA;
357 UCHAR Wpa2Ie = IE_WPA2;
358 UCHAR IbssIe = IE_IBSS_PARM;
359 UCHAR Ccx2Ie = IE_CCX_V2;
360 UCHAR WapiIe = IE_WAPI;
362 extern UCHAR WPA_OUI[];
364 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
366 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
367 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
369 // Reset the RFIC setting to new series
370 RTMP_RF_REGS RF2850RegTable[] = {
371 // ch R1 R2 R3(TX0~4=0) R4
372 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
373 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
374 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
375 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
376 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
377 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
378 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
379 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
380 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
381 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
382 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
383 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
384 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
385 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
387 // 802.11 UNI / HyperLan 2
388 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
389 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
390 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
391 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
392 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
393 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
394 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
395 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
396 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
397 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
398 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
399 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
402 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
404 // 2008.04.30 modified
405 // The system team has AN to improve the EVM value
406 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
407 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
408 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
409 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
411 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
412 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
413 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
414 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
415 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
416 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
417 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
418 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
419 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
420 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
421 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
422 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
425 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
426 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
427 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
428 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
429 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
430 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
431 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
434 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
435 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
436 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
437 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
438 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
439 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
440 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
442 // still lack of MMAC(Japan) ch 34,38,42,46
444 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
446 FREQUENCY_ITEM FreqItems3020[] =
448 /**************************************************/
449 // ISM : 2.4 to 2.483 GHz //
450 /**************************************************/
452 /**************************************************/
453 //-CH---N-------R---K-----------
469 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
472 ==========================================================================
474 initialize the MLME task and its data structure (queue, spinlock,
475 timer, state machines).
480 always return NDIS_STATUS_SUCCESS
482 ==========================================================================
484 NDIS_STATUS MlmeInit(
485 IN PRTMP_ADAPTER pAd)
487 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
489 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
493 Status = MlmeQueueInit(&pAd->Mlme.Queue);
494 if(Status != NDIS_STATUS_SUCCESS)
497 pAd->Mlme.bRunning = FALSE;
498 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
500 #ifdef CONFIG_STA_SUPPORT
501 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
503 BssTableInit(&pAd->ScanTab);
505 // init STA state machines
506 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
507 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
508 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
509 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
510 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
511 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
513 // Since we are using switch/case to implement it, the init is different from the above
514 // state machine init
515 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
517 #endif // CONFIG_STA_SUPPORT //
521 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
523 // Init mlme periodic timer
524 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
526 // Set mlme periodic timer
527 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
529 // software-based RX Antenna diversity
530 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
534 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
540 ==========================================================================
542 main loop of the MLME
544 Mlme has to be initialized, and there are something inside the queue
546 This function is invoked from MPSetInformation and MPReceive;
547 This task guarantee only one MlmeHandler will run.
549 IRQL = DISPATCH_LEVEL
551 ==========================================================================
554 IN PRTMP_ADAPTER pAd)
556 MLME_QUEUE_ELEM *Elem = NULL;
558 // Only accept MLME and Frame from peer side, no other (control/data) frame should
559 // get into this state machine
561 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
562 if(pAd->Mlme.bRunning)
564 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
569 pAd->Mlme.bRunning = TRUE;
571 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
573 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
575 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
576 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
577 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
579 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
583 //From message type, determine which state machine I should drive
584 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
587 if (Elem->MsgType == MT2_RESET_CONF)
589 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
590 MlmeRestartStateMachine(pAd);
591 Elem->Occupied = FALSE;
597 // if dequeue success
598 switch (Elem->Machine)
600 // STA state machines
601 #ifdef CONFIG_STA_SUPPORT
602 case ASSOC_STATE_MACHINE:
603 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
605 case AUTH_STATE_MACHINE:
606 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
608 case AUTH_RSP_STATE_MACHINE:
609 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
611 case SYNC_STATE_MACHINE:
612 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
614 case MLME_CNTL_STATE_MACHINE:
615 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
617 case WPA_PSK_STATE_MACHINE:
618 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
621 case LEAP_STATE_MACHINE:
622 LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
625 case AIRONET_STATE_MACHINE:
626 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
628 #endif // CONFIG_STA_SUPPORT //
630 case ACTION_STATE_MACHINE:
631 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
638 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
643 Elem->Occupied = FALSE;
648 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
652 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
653 pAd->Mlme.bRunning = FALSE;
654 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
658 ==========================================================================
660 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
662 Adapter - NIC Adapter pointer
664 The MLME task will no longer work properly
668 ==========================================================================
671 IN PRTMP_ADAPTER pAd)
675 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
677 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
679 // disable BEACON generation and other BEACON related hardware timers
680 AsicDisableSync(pAd);
683 #ifdef CONFIG_STA_SUPPORT
684 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
686 // Cancel pending timers
687 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
688 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
689 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
690 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
691 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
692 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
694 #endif // CONFIG_STA_SUPPORT //
696 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
697 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
701 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
704 RTMPSetLED(pAd, LED_HALT);
705 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
708 LED_CFG_STRUC LedCfg;
709 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
710 LedCfg.field.LedPolar = 0;
711 LedCfg.field.RLedMode = 0;
712 LedCfg.field.GLedMode = 0;
713 LedCfg.field.YLedMode = 0;
714 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
719 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
721 MlmeQueueDestroy(&pAd->Mlme.Queue);
722 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
724 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
727 VOID MlmeResetRalinkCounters(
728 IN PRTMP_ADAPTER pAd)
730 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
731 // clear all OneSecxxx counters.
732 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
733 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
734 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
735 pAd->RalinkCounters.OneSecRxOkCnt = 0;
736 pAd->RalinkCounters.OneSecTxFailCount = 0;
737 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
738 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
739 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
741 // TODO: for debug only. to be removed
742 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
743 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
744 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
745 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
746 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
747 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
748 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
749 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
750 pAd->RalinkCounters.OneSecTxDoneCount = 0;
751 pAd->RalinkCounters.OneSecRxCount = 0;
752 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
753 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
758 unsigned long rx_AMSDU;
759 unsigned long rx_Total;
762 ==========================================================================
764 This routine is executed periodically to -
765 1. Decide if it's a right time to turn on PwrMgmt bit of all
767 2. Calculate ChannelQuality based on statistics of the last
768 period, so that TX rate won't toggling very frequently between a
769 successful TX and a failed TX.
770 3. If the calculated ChannelQuality indicated current connection not
771 healthy, then a ROAMing attempt is tried here.
773 IRQL = DISPATCH_LEVEL
775 ==========================================================================
777 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
778 VOID MlmePeriodicExec(
779 IN PVOID SystemSpecific1,
780 IN PVOID FunctionContext,
781 IN PVOID SystemSpecific2,
782 IN PVOID SystemSpecific3)
785 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
787 // Do nothing if the driver is starting halt state.
788 // This might happen when timer already been fired before cancel timer with mlmehalt
789 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
790 fRTMP_ADAPTER_RADIO_OFF |
791 fRTMP_ADAPTER_RADIO_MEASUREMENT |
792 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
795 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
797 #ifdef CONFIG_STA_SUPPORT
798 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
800 // Do nothing if monitor mode is on
804 if (pAd->Mlme.PeriodicRound & 0x1)
806 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
807 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
808 (STA_TGN_WIFI_ON(pAd)) &&
809 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
812 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
813 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
815 else if ((STA_TGN_WIFI_ON(pAd)) &&
816 ((pAd->MACVersion & 0xffff) == 0x0101))
818 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
819 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
823 #endif // CONFIG_STA_SUPPORT //
825 pAd->bUpdateBcnCntDone = FALSE;
827 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
828 pAd->Mlme.PeriodicRound ++;
830 // execute every 500ms
831 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
833 #ifdef CONFIG_STA_SUPPORT
834 // perform dynamic tx rate switching based on past TX history
835 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
837 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
839 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
840 MlmeDynamicTxRateSwitching(pAd);
842 #endif // CONFIG_STA_SUPPORT //
845 // Normal 1 second Mlme PeriodicExec.
846 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
848 pAd->Mlme.OneSecPeriodicRound ++;
858 //ORIBATimerTimeout(pAd);
860 // Media status changed, report to NDIS
861 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
863 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
864 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
866 pAd->IndicateMediaState = NdisMediaStateConnected;
867 RTMP_IndicateMediaState(pAd);
872 pAd->IndicateMediaState = NdisMediaStateDisconnected;
873 RTMP_IndicateMediaState(pAd);
877 NdisGetSystemUpTime(&pAd->Mlme.Now32);
879 // add the most up-to-date h/w raw counters into software variable, so that
880 // the dynamic tuning mechanism below are based on most up-to-date information
881 NICUpdateRawCounters(pAd);
884 RT2870_WatchDog(pAd);
887 #ifdef DOT11_N_SUPPORT
888 // Need statistics after read counter. So put after NICUpdateRawCounters
889 ORIBATimerTimeout(pAd);
890 #endif // DOT11_N_SUPPORT //
892 // if MGMT RING is full more than twice within 1 second, we consider there's
893 // a hardware problem stucking the TX path. In this case, try a hardware reset
894 // to recover the system
895 // if (pAd->RalinkCounters.MgmtRingFullCount >= 2)
896 // RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR);
898 // pAd->RalinkCounters.MgmtRingFullCount = 0;
900 // The time period for checking antenna is according to traffic
901 if (pAd->Mlme.bEnableAutoAntennaCheck)
903 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
904 pAd->RalinkCounters.OneSecTxRetryOkCount +
905 pAd->RalinkCounters.OneSecTxFailCount;
909 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
911 AsicEvaluateRxAnt(pAd);
916 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
918 AsicEvaluateRxAnt(pAd);
923 #ifdef CONFIG_STA_SUPPORT
924 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
925 STAMlmePeriodicExec(pAd);
926 #endif // CONFIG_STA_SUPPORT //
928 MlmeResetRalinkCounters(pAd);
930 #ifdef CONFIG_STA_SUPPORT
931 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
934 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
935 // and sending CTS-to-self over and over.
936 // Software Patch Solution:
937 // 1. Polling debug state register 0x10F4 every one second.
938 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
939 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
943 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
944 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
946 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
948 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
950 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
954 #endif // CONFIG_STA_SUPPORT //
956 RT28XX_MLME_HANDLER(pAd);
960 pAd->bUpdateBcnCntDone = FALSE;
963 #ifdef CONFIG_STA_SUPPORT
964 VOID STAMlmePeriodicExec(
970 #ifdef WPA_SUPPLICANT_SUPPORT
971 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
972 #endif // WPA_SUPPLICANT_SUPPORT //
974 // WPA MIC error should block association attempt for 60 seconds
975 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
976 pAd->StaCfg.bBlockAssoc = FALSE;
979 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
981 if (pAd->IndicateMediaState == NdisMediaStateConnected)
983 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
985 pAd->PreMediaState = pAd->IndicateMediaState;
991 AsicStaBbpTuning(pAd);
993 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
994 pAd->RalinkCounters.OneSecTxRetryOkCount +
995 pAd->RalinkCounters.OneSecTxFailCount;
997 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
999 // update channel quality for Roaming and UI LinkQuality display
1000 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1003 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1004 // Radio is currently in noisy environment
1005 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1006 AsicAdjustTxPower(pAd);
1010 // Is PSM bit consistent with user power management policy?
1011 // This is the only place that will set PSM bit ON.
1012 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1013 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1015 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1017 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1018 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1019 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1021 RTMPSetAGCInitValue(pAd, BW_20);
1022 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1025 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1026 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1028 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1030 // When APSD is enabled, the period changes as 20 sec
1031 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1032 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1036 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1037 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1039 if (pAd->CommonCfg.bWmmCapable)
1040 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1042 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1047 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1049 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1050 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1051 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1053 // Lost AP, send disconnect & link down event
1054 LinkDown(pAd, FALSE);
1056 #ifdef WPA_SUPPLICANT_SUPPORT
1057 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1058 if (pAd->StaCfg.WpaSupplicantUP)
1060 union iwreq_data wrqu;
1061 //send disassociate event to wpa_supplicant
1062 memset(&wrqu, 0, sizeof(wrqu));
1063 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1064 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1066 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1067 #endif // WPA_SUPPLICANT_SUPPORT //
1069 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1071 union iwreq_data wrqu;
1072 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1073 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1075 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1077 // RTMPPatchMacBbpBug(pAd);
1078 MlmeAutoReconnectLastSSID(pAd);
1080 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1082 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1083 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1084 MlmeAutoReconnectLastSSID(pAd);
1087 // Add auto seamless roaming
1088 if (pAd->StaCfg.bFastRoaming)
1090 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1092 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));
1094 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1096 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1100 else if (ADHOC_ON(pAd))
1103 if ((pAd->CommonCfg.Channel > 14)
1104 && (pAd->CommonCfg.bIEEE80211H == 1)
1105 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1107 RadarDetectPeriodic(pAd);
1110 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1111 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1113 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1114 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1116 MLME_START_REQ_STRUCT StartReq;
1118 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1119 LinkDown(pAd, FALSE);
1121 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1122 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1123 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1126 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1128 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1130 if (pEntry->ValidAsCLI == FALSE)
1133 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1134 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1137 else // no INFRA nor ADHOC connection
1140 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1141 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1142 goto SKIP_AUTO_SCAN_CONN;
1144 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1146 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1147 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1148 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1150 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1152 MLME_SCAN_REQ_STRUCT ScanReq;
1154 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1156 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1157 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1158 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1159 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1160 // Reset Missed scan number
1161 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1163 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1164 MlmeAutoReconnectLastSSID(pAd);
1166 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1168 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1171 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1175 MlmeAutoReconnectLastSSID(pAd);
1181 SKIP_AUTO_SCAN_CONN:
1183 #ifdef DOT11_N_SUPPORT
1184 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1186 pAd->MacTab.fAnyBASession = TRUE;
1187 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1189 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1191 pAd->MacTab.fAnyBASession = FALSE;
1192 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1194 #endif // DOT11_N_SUPPORT //
1197 #ifdef DOT11_N_SUPPORT
1198 #ifdef DOT11N_DRAFT3
1199 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1200 TriEventCounterMaintenance(pAd);
1201 #endif // DOT11N_DRAFT3 //
1202 #endif // DOT11_N_SUPPORT //
1209 IN PVOID SystemSpecific1,
1210 IN PVOID FunctionContext,
1211 IN PVOID SystemSpecific2,
1212 IN PVOID SystemSpecific3)
1215 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1217 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1218 RTMP_IndicateMediaState(pAd);
1219 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1222 // IRQL = DISPATCH_LEVEL
1224 IN PRTMP_ADAPTER pAd)
1226 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1227 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1229 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1231 MLME_CNTL_STATE_MACHINE,
1232 OID_802_11_BSSID_LIST_SCAN,
1235 RT28XX_MLME_HANDLER(pAd);
1239 // IRQL = DISPATCH_LEVEL
1240 VOID MlmeAutoReconnectLastSSID(
1241 IN PRTMP_ADAPTER pAd)
1245 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1246 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1247 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1249 NDIS_802_11_SSID OidSsid;
1250 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1251 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1253 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1255 MLME_CNTL_STATE_MACHINE,
1257 sizeof(NDIS_802_11_SSID),
1259 RT28XX_MLME_HANDLER(pAd);
1262 #endif // CONFIG_STA_SUPPORT //
1265 ==========================================================================
1266 Validate SSID for connection try and rescan purpose
1267 Valid SSID will have visible chars only.
1268 The valid length is from 0 to 32.
1269 IRQL = DISPATCH_LEVEL
1270 ==========================================================================
1272 BOOLEAN MlmeValidateSSID(
1278 if (SsidLen > MAX_LEN_OF_SSID)
1281 // Check each character value
1282 for (index = 0; index < SsidLen; index++)
1284 if (pSsid[index] < 0x20)
1292 VOID MlmeSelectTxRateTable(
1293 IN PRTMP_ADAPTER pAd,
1294 IN PMAC_TABLE_ENTRY pEntry,
1296 IN PUCHAR pTableSize,
1297 IN PUCHAR pInitTxRateIdx)
1301 // decide the rate table for tuning
1302 if (pAd->CommonCfg.TxRateTableSize > 0)
1304 *ppTable = RateSwitchTable;
1305 *pTableSize = RateSwitchTable[0];
1306 *pInitTxRateIdx = RateSwitchTable[1];
1311 #ifdef CONFIG_STA_SUPPORT
1312 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1314 #ifdef DOT11_N_SUPPORT
1315 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1316 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1317 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1319 *ppTable = RateSwitchTable11N1S;
1320 *pTableSize = RateSwitchTable11N1S[0];
1321 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1324 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1325 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1326 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1327 (pAd->Antenna.field.TxPath == 2))
1329 if (pAd->LatchRfRegs.Channel <= 14)
1331 *ppTable = RateSwitchTable11N2S;
1332 *pTableSize = RateSwitchTable11N2S[0];
1333 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1337 *ppTable = RateSwitchTable11N2SForABand;
1338 *pTableSize = RateSwitchTable11N2SForABand[0];
1339 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1344 #endif // DOT11_N_SUPPORT //
1345 if ((pEntry->RateLen == 4)
1346 #ifdef DOT11_N_SUPPORT
1347 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1348 #endif // DOT11_N_SUPPORT //
1351 *ppTable = RateSwitchTable11B;
1352 *pTableSize = RateSwitchTable11B[0];
1353 *pInitTxRateIdx = RateSwitchTable11B[1];
1356 else if (pAd->LatchRfRegs.Channel <= 14)
1358 *ppTable = RateSwitchTable11BG;
1359 *pTableSize = RateSwitchTable11BG[0];
1360 *pInitTxRateIdx = RateSwitchTable11BG[1];
1365 *ppTable = RateSwitchTable11G;
1366 *pTableSize = RateSwitchTable11G[0];
1367 *pInitTxRateIdx = RateSwitchTable11G[1];
1372 #endif // CONFIG_STA_SUPPORT //
1374 #ifdef DOT11_N_SUPPORT
1375 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1376 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1377 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1378 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1380 *ppTable = RateSwitchTable11BGN1S;
1381 *pTableSize = RateSwitchTable11BGN1S[0];
1382 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1387 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1388 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1389 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1390 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1392 if (pAd->LatchRfRegs.Channel <= 14)
1394 *ppTable = RateSwitchTable11BGN2S;
1395 *pTableSize = RateSwitchTable11BGN2S[0];
1396 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1401 *ppTable = RateSwitchTable11BGN2SForABand;
1402 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1403 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1409 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1410 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1412 *ppTable = RateSwitchTable11N1S;
1413 *pTableSize = RateSwitchTable11N1S[0];
1414 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1419 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1420 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1422 if (pAd->LatchRfRegs.Channel <= 14)
1424 *ppTable = RateSwitchTable11N2S;
1425 *pTableSize = RateSwitchTable11N2S[0];
1426 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1430 *ppTable = RateSwitchTable11N2SForABand;
1431 *pTableSize = RateSwitchTable11N2SForABand[0];
1432 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1437 #endif // DOT11_N_SUPPORT //
1438 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1439 if ((pEntry->RateLen == 4)
1440 #ifdef DOT11_N_SUPPORT
1441 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1442 #endif // DOT11_N_SUPPORT //
1445 *ppTable = RateSwitchTable11B;
1446 *pTableSize = RateSwitchTable11B[0];
1447 *pInitTxRateIdx = RateSwitchTable11B[1];
1452 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1453 if ((pEntry->RateLen > 8)
1454 #ifdef DOT11_N_SUPPORT
1455 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1456 #endif // DOT11_N_SUPPORT //
1459 *ppTable = RateSwitchTable11BG;
1460 *pTableSize = RateSwitchTable11BG[0];
1461 *pInitTxRateIdx = RateSwitchTable11BG[1];
1466 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1467 if ((pEntry->RateLen == 8)
1468 #ifdef DOT11_N_SUPPORT
1469 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1470 #endif // DOT11_N_SUPPORT //
1473 *ppTable = RateSwitchTable11G;
1474 *pTableSize = RateSwitchTable11G[0];
1475 *pInitTxRateIdx = RateSwitchTable11G[1];
1479 #ifdef DOT11_N_SUPPORT
1480 #endif // DOT11_N_SUPPORT //
1482 #ifdef CONFIG_STA_SUPPORT
1483 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1485 #ifdef DOT11_N_SUPPORT
1486 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1487 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1488 #endif // DOT11_N_SUPPORT //
1490 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1492 *ppTable = RateSwitchTable11B;
1493 *pTableSize = RateSwitchTable11B[0];
1494 *pInitTxRateIdx = RateSwitchTable11B[1];
1496 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1498 *ppTable = RateSwitchTable11G;
1499 *pTableSize = RateSwitchTable11G[0];
1500 *pInitTxRateIdx = RateSwitchTable11G[1];
1505 *ppTable = RateSwitchTable11BG;
1506 *pTableSize = RateSwitchTable11BG[0];
1507 *pInitTxRateIdx = RateSwitchTable11BG[1];
1511 #ifdef DOT11_N_SUPPORT
1512 if (pAd->LatchRfRegs.Channel <= 14)
1514 if (pAd->CommonCfg.TxStream == 1)
1516 *ppTable = RateSwitchTable11N1S;
1517 *pTableSize = RateSwitchTable11N1S[0];
1518 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1519 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1523 *ppTable = RateSwitchTable11N2S;
1524 *pTableSize = RateSwitchTable11N2S[0];
1525 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1526 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1531 if (pAd->CommonCfg.TxStream == 1)
1533 *ppTable = RateSwitchTable11N1S;
1534 *pTableSize = RateSwitchTable11N1S[0];
1535 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1536 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1540 *ppTable = RateSwitchTable11N2SForABand;
1541 *pTableSize = RateSwitchTable11N2SForABand[0];
1542 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1543 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1546 #endif // DOT11_N_SUPPORT //
1547 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1548 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1550 #endif // CONFIG_STA_SUPPORT //
1554 #ifdef CONFIG_STA_SUPPORT
1556 ==========================================================================
1558 This routine checks if there're other APs out there capable for
1559 roaming. Caller should call this routine only when Link up in INFRA mode
1560 and channel quality is below CQI_GOOD_THRESHOLD.
1562 IRQL = DISPATCH_LEVEL
1565 ==========================================================================
1567 VOID MlmeCheckForRoaming(
1568 IN PRTMP_ADAPTER pAd,
1572 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1575 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1576 // put all roaming candidates into RoamTab, and sort in RSSI order
1577 BssTableInit(pRoamTab);
1578 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1580 pBss = &pAd->ScanTab.BssEntry[i];
1582 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1583 continue; // AP disappear
1584 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1585 continue; // RSSI too weak. forget it.
1586 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1587 continue; // skip current AP
1588 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1589 continue; // only AP with stronger RSSI is eligible for roaming
1591 // AP passing all above rules is put into roaming candidate table
1592 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1593 pRoamTab->BssNr += 1;
1596 if (pRoamTab->BssNr > 0)
1598 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1599 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1601 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1602 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1603 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1604 RT28XX_MLME_HANDLER(pAd);
1607 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1611 ==========================================================================
1613 This routine checks if there're other APs out there capable for
1614 roaming. Caller should call this routine only when link up in INFRA mode
1615 and channel quality is below CQI_GOOD_THRESHOLD.
1617 IRQL = DISPATCH_LEVEL
1620 ==========================================================================
1622 VOID MlmeCheckForFastRoaming(
1623 IN PRTMP_ADAPTER pAd,
1627 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1630 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1631 // put all roaming candidates into RoamTab, and sort in RSSI order
1632 BssTableInit(pRoamTab);
1633 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1635 pBss = &pAd->ScanTab.BssEntry[i];
1637 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1638 continue; // RSSI too weak. forget it.
1639 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1640 continue; // skip current AP
1641 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1642 continue; // skip different SSID
1643 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1644 continue; // skip AP without better RSSI
1646 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));
1647 // AP passing all above rules is put into roaming candidate table
1648 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1649 pRoamTab->BssNr += 1;
1652 if (pRoamTab->BssNr > 0)
1654 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1655 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1657 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1658 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1659 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1660 RT28XX_MLME_HANDLER(pAd);
1663 // Maybe site survey required
1666 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1668 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1669 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1670 pAd->StaCfg.ScanCnt = 2;
1671 pAd->StaCfg.LastScanTime = Now;
1676 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1680 ==========================================================================
1682 This routine calculates TxPER, RxPER of the past N-sec period. And
1683 according to the calculation result, ChannelQuality is calculated here
1684 to decide if current AP is still doing the job.
1686 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1688 StaCfg.ChannelQuality - 0..100
1690 IRQL = DISPATCH_LEVEL
1692 NOTE: This routine decide channle quality based on RX CRC error ratio.
1693 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1694 is performed right before this routine, so that this routine can decide
1695 channel quality based on the most up-to-date information
1696 ==========================================================================
1698 VOID MlmeCalculateChannelQuality(
1699 IN PRTMP_ADAPTER pAd,
1702 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1706 ULONG BeaconLostTime = BEACON_LOST_TIME;
1708 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1711 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1713 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1714 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1722 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1723 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1727 // calculate RX PER - don't take RxPER into consideration if too few sample
1729 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1733 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1736 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1738 if (INFRA_ON(pAd) &&
1739 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1740 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1742 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1743 pAd->Mlme.ChannelQuality = 0;
1750 else if (MaxRssi < -90)
1753 NorRssi = (MaxRssi + 90) * 2;
1755 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1756 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1757 TX_WEIGHTING * (100 - TxPRR) +
1758 RX_WEIGHTING* (100 - RxPER)) / 100;
1759 if (pAd->Mlme.ChannelQuality >= 100)
1760 pAd->Mlme.ChannelQuality = 100;
1766 IN PRTMP_ADAPTER pAd,
1767 IN PMAC_TABLE_ENTRY pEntry,
1768 IN PRTMP_TX_RATE_SWITCH pTxRate)
1770 UCHAR MaxMode = MODE_OFDM;
1772 #ifdef DOT11_N_SUPPORT
1773 MaxMode = MODE_HTGREENFIELD;
1775 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1776 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1778 #endif // DOT11_N_SUPPORT //
1779 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1781 if (pTxRate->CurrMCS < MCS_AUTO)
1782 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1784 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1785 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1789 // If peer adhoc is b-only mode, we can't send 11g rate.
1790 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1791 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1794 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1796 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1797 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1798 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1800 // Patch speed error in status page
1801 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1805 if (pTxRate->Mode <= MaxMode)
1806 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1808 #ifdef DOT11_N_SUPPORT
1809 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1810 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1812 #endif // DOT11_N_SUPPORT //
1813 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1815 #ifdef DOT11_N_SUPPORT
1816 // Reexam each bandwidth's SGI support.
1817 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1819 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1820 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1821 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1822 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1825 // Turn RTS/CTS rate to 6Mbps.
1826 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1828 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1829 if (pAd->MacTab.fAnyBASession)
1831 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1835 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1838 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1840 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1841 if (pAd->MacTab.fAnyBASession)
1843 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1847 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1850 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1852 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1855 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1857 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1859 #endif // DOT11_N_SUPPORT //
1861 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1862 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1863 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1864 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1865 #ifdef DOT11_N_SUPPORT
1866 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1867 pAd->WIFItestbed.bGreenField)
1868 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1869 #endif // DOT11_N_SUPPORT //
1872 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1876 ==========================================================================
1878 This routine calculates the acumulated TxPER of eaxh TxRate. And
1879 according to the calculation result, change CommonCfg.TxRate which
1880 is the stable TX Rate we expect the Radio situation could sustained.
1882 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1886 IRQL = DISPATCH_LEVEL
1889 call this routine every second
1890 ==========================================================================
1892 VOID MlmeDynamicTxRateSwitching(
1893 IN PRTMP_ADAPTER pAd)
1895 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1896 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1897 ULONG TxErrorRatio = 0;
1898 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1899 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1901 UCHAR TableSize = 0;
1902 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1903 CHAR Rssi, RssiOffset = 0;
1904 TX_STA_CNT1_STRUC StaTx1;
1905 TX_STA_CNT0_STRUC TxStaCnt0;
1906 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1907 MAC_TABLE_ENTRY *pEntry;
1910 // walk through MAC table, see if need to change AP's TX rate toward each entry
1912 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1914 pEntry = &pAd->MacTab.Content[i];
1916 // check if this entry need to switch rate automatically
1917 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1920 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1922 Rssi = RTMPMaxRssi(pAd,
1923 pAd->StaCfg.RssiSample.AvgRssi0,
1924 pAd->StaCfg.RssiSample.AvgRssi1,
1925 pAd->StaCfg.RssiSample.AvgRssi2);
1927 // Update statistic counter
1928 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1929 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1930 pAd->bUpdateBcnCntDone = TRUE;
1931 TxRetransmit = StaTx1.field.TxRetransmit;
1932 TxSuccess = StaTx1.field.TxSuccess;
1933 TxFailCount = TxStaCnt0.field.TxFailCount;
1934 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1936 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1937 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1938 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1939 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1940 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1941 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1943 // if no traffic in the past 1-sec period, don't change TX rate,
1944 // but clear all bad history. because the bad history may affect the next
1945 // Chariot throughput test
1946 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1947 pAd->RalinkCounters.OneSecTxRetryOkCount +
1948 pAd->RalinkCounters.OneSecTxFailCount;
1951 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1955 if (INFRA_ON(pAd) && (i == 1))
1956 Rssi = RTMPMaxRssi(pAd,
1957 pAd->StaCfg.RssiSample.AvgRssi0,
1958 pAd->StaCfg.RssiSample.AvgRssi1,
1959 pAd->StaCfg.RssiSample.AvgRssi2);
1961 Rssi = RTMPMaxRssi(pAd,
1962 pEntry->RssiSample.AvgRssi0,
1963 pEntry->RssiSample.AvgRssi1,
1964 pEntry->RssiSample.AvgRssi2);
1966 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1967 pEntry->OneSecTxRetryOkCount +
1968 pEntry->OneSecTxFailCount;
1971 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1974 CurrRateIdx = pEntry->CurrTxRateIndex;
1976 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1978 if (CurrRateIdx >= TableSize)
1980 CurrRateIdx = TableSize - 1;
1983 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
1984 // So need to sync here.
1985 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1986 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1987 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1991 // Need to sync Real Tx rate and our record.
1992 // Then return for next DRS.
1993 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
1994 pEntry->CurrTxRateIndex = InitTxRateIdx;
1995 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
1997 // reset all OneSecTx counters
1998 RESET_ONE_SEC_TX_CNT(pEntry);
2002 // decide the next upgrade rate and downgrade rate, if any
2003 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2005 UpRateIdx = CurrRateIdx + 1;
2006 DownRateIdx = CurrRateIdx -1;
2008 else if (CurrRateIdx == 0)
2010 UpRateIdx = CurrRateIdx + 1;
2011 DownRateIdx = CurrRateIdx;
2013 else if (CurrRateIdx == (TableSize - 1))
2015 UpRateIdx = CurrRateIdx;
2016 DownRateIdx = CurrRateIdx - 1;
2019 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2021 #ifdef DOT11_N_SUPPORT
2022 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2024 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2025 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2028 #endif // DOT11_N_SUPPORT //
2030 TrainUp = pCurrTxRate->TrainUp;
2031 TrainDown = pCurrTxRate->TrainDown;
2034 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2037 // Keep the last time TxRateChangeAction status.
2039 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2044 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2045 // (criteria copied from RT2500 for Netopia case)
2047 if (TxTotalCnt <= 15)
2051 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2052 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2053 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2054 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2056 // check the existence and index of each needed MCS
2057 while (idx < pTable[0])
2059 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2061 if (pCurrTxRate->CurrMCS == MCS_0)
2065 else if (pCurrTxRate->CurrMCS == MCS_1)
2069 else if (pCurrTxRate->CurrMCS == MCS_2)
2073 else if (pCurrTxRate->CurrMCS == MCS_3)
2077 else if (pCurrTxRate->CurrMCS == MCS_4)
2081 else if (pCurrTxRate->CurrMCS == MCS_5)
2085 else if (pCurrTxRate->CurrMCS == MCS_6)
2089 //else if (pCurrTxRate->CurrMCS == MCS_7)
2090 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2094 else if (pCurrTxRate->CurrMCS == MCS_12)
2098 else if (pCurrTxRate->CurrMCS == MCS_13)
2102 else if (pCurrTxRate->CurrMCS == MCS_14)
2106 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2107 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI
2111 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2115 else if (pCurrTxRate->CurrMCS == MCS_21)
2119 else if (pCurrTxRate->CurrMCS == MCS_22)
2123 else if (pCurrTxRate->CurrMCS == MCS_23)
2130 if (pAd->LatchRfRegs.Channel <= 14)
2132 if (pAd->NicConfig2.field.ExternalLNAForG)
2143 if (pAd->NicConfig2.field.ExternalLNAForA)
2152 #ifdef DOT11_N_SUPPORT
2154 if ((pTable == RateSwitchTable11BGN3S) ||
2155 (pTable == RateSwitchTable11N3S) ||
2156 (pTable == RateSwitchTable))
2157 {// N mode with 3 stream // 3*3
2158 if (MCS23 && (Rssi >= -70))
2160 else if (MCS22 && (Rssi >= -72))
2162 else if (MCS21 && (Rssi >= -76))
2164 else if (MCS20 && (Rssi >= -78))
2166 else if (MCS4 && (Rssi >= -82))
2168 else if (MCS3 && (Rssi >= -84))
2170 else if (MCS2 && (Rssi >= -86))
2172 else if (MCS1 && (Rssi >= -88))
2177 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2178 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2179 {// N mode with 2 stream
2180 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2182 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2184 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2186 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2188 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2190 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2192 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2194 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2199 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2200 {// N mode with 1 stream
2201 if (MCS7 && (Rssi > (-72+RssiOffset)))
2203 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2205 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2207 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2209 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2211 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2213 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2219 #endif // DOT11_N_SUPPORT //
2221 if (MCS7 && (Rssi > -70))
2223 else if (MCS6 && (Rssi > -74))
2225 else if (MCS5 && (Rssi > -78))
2227 else if (MCS4 && (Rssi > -82))
2229 else if (MCS4 == 0) // for B-only mode
2231 else if (MCS3 && (Rssi > -85))
2233 else if (MCS2 && (Rssi > -87))
2235 else if (MCS1 && (Rssi > -90))
2241 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2243 pEntry->CurrTxRateIndex = TxRateIdx;
2244 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2245 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2248 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2249 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2250 pEntry->fLastSecAccordingRSSI = TRUE;
2251 // reset all OneSecTx counters
2252 RESET_ONE_SEC_TX_CNT(pEntry);
2257 if (pEntry->fLastSecAccordingRSSI == TRUE)
2259 pEntry->fLastSecAccordingRSSI = FALSE;
2260 pEntry->LastSecTxRateChangeAction = 0;
2261 // reset all OneSecTx counters
2262 RESET_ONE_SEC_TX_CNT(pEntry);
2269 BOOLEAN bTrainUpDown = FALSE;
2271 pEntry->CurrTxRateStableTime ++;
2273 // downgrade TX quality if PER >= Rate-Down threshold
2274 if (TxErrorRatio >= TrainDown)
2276 bTrainUpDown = TRUE;
2277 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2279 // upgrade TX quality if PER <= Rate-Up threshold
2280 else if (TxErrorRatio <= TrainUp)
2282 bTrainUpDown = TRUE;
2283 bUpgradeQuality = TRUE;
2284 if (pEntry->TxQuality[CurrRateIdx])
2285 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2287 if (pEntry->TxRateUpPenalty)
2288 pEntry->TxRateUpPenalty --;
2289 else if (pEntry->TxQuality[UpRateIdx])
2290 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2293 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2297 // perform DRS - consider TxRate Down first, then rate up.
2298 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2300 pEntry->CurrTxRateIndex = DownRateIdx;
2302 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2304 pEntry->CurrTxRateIndex = UpRateIdx;
2309 // if rate-up happen, clear all bad history of all TX rates
2310 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2312 pEntry->CurrTxRateStableTime = 0;
2313 pEntry->TxRateUpPenalty = 0;
2314 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2315 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2316 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2319 // For TxRate fast train up
2321 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2323 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2325 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2327 bTxRateChanged = TRUE;
2329 // if rate-down happen, only clear DownRate's bad history
2330 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2332 pEntry->CurrTxRateStableTime = 0;
2333 pEntry->TxRateUpPenalty = 0; // no penalty
2334 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2335 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2336 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2339 // For TxRate fast train down
2341 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2343 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2345 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2347 bTxRateChanged = TRUE;
2351 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2352 bTxRateChanged = FALSE;
2355 pEntry->LastTxOkCount = TxSuccess;
2357 // reset all OneSecTx counters
2358 RESET_ONE_SEC_TX_CNT(pEntry);
2360 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2361 if (bTxRateChanged && pNextTxRate)
2363 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2369 ========================================================================
2370 Routine Description:
2371 Station side, Auto TxRate faster train up timer call back function.
2374 SystemSpecific1 - Not used.
2375 FunctionContext - Pointer to our Adapter context.
2376 SystemSpecific2 - Not used.
2377 SystemSpecific3 - Not used.
2382 ========================================================================
2384 VOID StaQuickResponeForRateUpExec(
2385 IN PVOID SystemSpecific1,
2386 IN PVOID FunctionContext,
2387 IN PVOID SystemSpecific2,
2388 IN PVOID SystemSpecific3)
2390 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2391 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2393 ULONG TxErrorRatio = 0;
2394 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2395 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2397 UCHAR TableSize = 0;
2398 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2399 TX_STA_CNT1_STRUC StaTx1;
2400 TX_STA_CNT0_STRUC TxStaCnt0;
2402 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2403 MAC_TABLE_ENTRY *pEntry;
2406 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2409 // walk through MAC table, see if need to change AP's TX rate toward each entry
2411 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2413 pEntry = &pAd->MacTab.Content[i];
2415 // check if this entry need to switch rate automatically
2416 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2419 if (INFRA_ON(pAd) && (i == 1))
2420 Rssi = RTMPMaxRssi(pAd,
2421 pAd->StaCfg.RssiSample.AvgRssi0,
2422 pAd->StaCfg.RssiSample.AvgRssi1,
2423 pAd->StaCfg.RssiSample.AvgRssi2);
2425 Rssi = RTMPMaxRssi(pAd,
2426 pEntry->RssiSample.AvgRssi0,
2427 pEntry->RssiSample.AvgRssi1,
2428 pEntry->RssiSample.AvgRssi2);
2430 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2432 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2434 // decide the next upgrade rate and downgrade rate, if any
2435 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2437 UpRateIdx = CurrRateIdx + 1;
2438 DownRateIdx = CurrRateIdx -1;
2440 else if (CurrRateIdx == 0)
2442 UpRateIdx = CurrRateIdx + 1;
2443 DownRateIdx = CurrRateIdx;
2445 else if (CurrRateIdx == (TableSize - 1))
2447 UpRateIdx = CurrRateIdx;
2448 DownRateIdx = CurrRateIdx - 1;
2451 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2453 #ifdef DOT11_N_SUPPORT
2454 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2456 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2457 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2460 #endif // DOT11_N_SUPPORT //
2462 TrainUp = pCurrTxRate->TrainUp;
2463 TrainDown = pCurrTxRate->TrainDown;
2466 if (pAd->MacTab.Size == 1)
2468 // Update statistic counter
2469 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2470 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2472 TxRetransmit = StaTx1.field.TxRetransmit;
2473 TxSuccess = StaTx1.field.TxSuccess;
2474 TxFailCount = TxStaCnt0.field.TxFailCount;
2475 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2477 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2478 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2479 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2480 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2481 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2482 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2484 #if 0 // test by Gary.
2485 // if no traffic in the past 1-sec period, don't change TX rate,
2486 // but clear all bad history. because the bad history may affect the next
2487 // Chariot throughput test
2488 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2489 pAd->RalinkCounters.OneSecTxRetryOkCount +
2490 pAd->RalinkCounters.OneSecTxFailCount;
2493 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2497 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2498 pEntry->OneSecTxRetryOkCount +
2499 pEntry->OneSecTxFailCount;
2502 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2507 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2508 // (criteria copied from RT2500 for Netopia case)
2510 if (TxTotalCnt <= 12)
2512 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2513 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2515 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2517 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2518 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2520 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2522 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2525 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2531 ULONG OneSecTxNoRetryOKRationCount;
2533 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2538 // downgrade TX quality if PER >= Rate-Down threshold
2539 if (TxErrorRatio >= TrainDown)
2541 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2544 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2546 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2548 // perform DRS - consider TxRate Down first, then rate up.
2549 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2551 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2553 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2554 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2559 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2561 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2565 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2567 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2572 // if rate-up happen, clear all bad history of all TX rates
2573 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2575 pAd->DrsCounters.TxRateUpPenalty = 0;
2576 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2577 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2578 bTxRateChanged = TRUE;
2580 // if rate-down happen, only clear DownRate's bad history
2581 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2583 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2585 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2586 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2587 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2588 bTxRateChanged = TRUE;
2592 bTxRateChanged = FALSE;
2595 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2596 if (bTxRateChanged && pNextTxRate)
2598 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2604 ==========================================================================
2606 This routine is executed periodically inside MlmePeriodicExec() after
2607 association with an AP.
2608 It checks if StaCfg.Psm is consistent with user policy (recorded in
2609 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2610 there're some conditions to consider:
2611 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2612 the time when Mibss==TRUE
2613 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2614 if outgoing traffic available in TxRing or MgmtRing.
2616 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2618 IRQL = DISPATCH_LEVEL
2620 ==========================================================================
2622 VOID MlmeCheckPsmChange(
2623 IN PRTMP_ADAPTER pAd,
2629 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2630 // 2. user wants either MAX_PSP or FAST_PSP
2631 // 3. but current psm is not in PWR_SAVE
2632 // 4. CNTL state machine is not doing SCANning
2633 // 5. no TX SUCCESS event for the past 1-sec period
2634 #ifdef NDIS51_MINIPORT
2635 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2636 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2639 PowerMode = pAd->StaCfg.WindowsPowerMode;
2641 if (INFRA_ON(pAd) &&
2642 (PowerMode != Ndis802_11PowerModeCAM) &&
2643 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2644 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2645 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2646 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2647 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2649 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2650 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2651 MlmeSetPsmBit(pAd, PWR_SAVE);
2652 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2654 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2658 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2663 // IRQL = PASSIVE_LEVEL
2664 // IRQL = DISPATCH_LEVEL
2666 IN PRTMP_ADAPTER pAd,
2669 AUTO_RSP_CFG_STRUC csr4;
2671 pAd->StaCfg.Psm = psm;
2672 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2673 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2674 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2675 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2677 #endif // CONFIG_STA_SUPPORT //
2680 // IRQL = DISPATCH_LEVEL
2681 VOID MlmeSetTxPreamble(
2682 IN PRTMP_ADAPTER pAd,
2683 IN USHORT TxPreamble)
2685 AUTO_RSP_CFG_STRUC csr4;
2688 // Always use Long preamble before verifiation short preamble functionality works well.
2689 // Todo: remove the following line if short preamble functionality works
2691 //TxPreamble = Rt802_11PreambleLong;
2693 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2694 if (TxPreamble == Rt802_11PreambleLong)
2696 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2697 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2698 csr4.field.AutoResponderPreamble = 0;
2702 // NOTE: 1Mbps should always use long preamble
2703 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2704 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2705 csr4.field.AutoResponderPreamble = 1;
2708 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2712 ==========================================================================
2714 Update basic rate bitmap
2715 ==========================================================================
2718 VOID UpdateBasicRateBitmap(
2719 IN PRTMP_ADAPTER pAdapter)
2722 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2723 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2724 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2725 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2726 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2729 /* if A mode, always use fix BasicRateBitMap */
2730 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2731 if (pAdapter->CommonCfg.Channel > 14)
2732 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2735 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2737 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2741 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2747 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2749 if (bitmap & (1 << i))
2751 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2753 if (sup_p[j] == rate[i])
2758 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2760 if (ext_p[j] == rate[i])
2766 } /* End of UpdateBasicRateBitmap */
2768 // IRQL = PASSIVE_LEVEL
2769 // IRQL = DISPATCH_LEVEL
2770 // bLinkUp is to identify the inital link speed.
2771 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2772 VOID MlmeUpdateTxRates(
2773 IN PRTMP_ADAPTER pAd,
2778 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2779 UCHAR MinSupport = RATE_54;
2780 ULONG BasicRateBitmap = 0;
2781 UCHAR CurrBasicRate = RATE_1;
2782 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2783 PHTTRANSMIT_SETTING pHtPhy = NULL;
2784 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2785 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2786 BOOLEAN *auto_rate_cur_p;
2787 UCHAR HtMcs = MCS_AUTO;
2789 // find max desired rate
2790 UpdateBasicRateBitmap(pAd);
2793 auto_rate_cur_p = NULL;
2794 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2796 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2798 case 2: Rate = RATE_1; num++; break;
2799 case 4: Rate = RATE_2; num++; break;
2800 case 11: Rate = RATE_5_5; num++; break;
2801 case 22: Rate = RATE_11; num++; break;
2802 case 12: Rate = RATE_6; num++; break;
2803 case 18: Rate = RATE_9; num++; break;
2804 case 24: Rate = RATE_12; num++; break;
2805 case 36: Rate = RATE_18; num++; break;
2806 case 48: Rate = RATE_24; num++; break;
2807 case 72: Rate = RATE_36; num++; break;
2808 case 96: Rate = RATE_48; num++; break;
2809 case 108: Rate = RATE_54; num++; break;
2810 //default: Rate = RATE_1; break;
2812 if (MaxDesire < Rate) MaxDesire = Rate;
2815 //===========================================================================
2816 //===========================================================================
2818 #ifdef CONFIG_STA_SUPPORT
2819 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2821 pHtPhy = &pAd->StaCfg.HTPhyMode;
2822 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2823 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2825 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2826 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2828 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2829 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2830 (MaxDesire > RATE_11))
2832 MaxDesire = RATE_11;
2835 #endif // CONFIG_STA_SUPPORT //
2837 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2838 pMinHtPhy->word = 0;
2839 pMaxHtPhy->word = 0;
2842 // Auto rate switching is enabled only if more than one DESIRED RATES are
2843 // specified; otherwise disabled
2846 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2847 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2848 *auto_rate_cur_p = FALSE;
2852 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2853 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2854 *auto_rate_cur_p = TRUE;
2858 if (HtMcs != MCS_AUTO)
2860 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2861 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2862 *auto_rate_cur_p = FALSE;
2866 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2867 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2868 *auto_rate_cur_p = TRUE;
2872 #ifdef CONFIG_STA_SUPPORT
2873 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2875 pSupRate = &pAd->StaActive.SupRate[0];
2876 pExtRate = &pAd->StaActive.ExtRate[0];
2877 SupRateLen = pAd->StaActive.SupRateLen;
2878 ExtRateLen = pAd->StaActive.ExtRateLen;
2881 #endif // CONFIG_STA_SUPPORT //
2883 pSupRate = &pAd->CommonCfg.SupRate[0];
2884 pExtRate = &pAd->CommonCfg.ExtRate[0];
2885 SupRateLen = pAd->CommonCfg.SupRateLen;
2886 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2889 // find max supported rate
2890 for (i=0; i<SupRateLen; i++)
2892 switch (pSupRate[i] & 0x7f)
2894 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2895 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2896 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2897 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2898 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2899 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2900 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2901 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2902 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2903 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2904 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2905 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2906 default: Rate = RATE_1; break;
2908 if (MaxSupport < Rate) MaxSupport = Rate;
2910 if (MinSupport > Rate) MinSupport = Rate;
2913 for (i=0; i<ExtRateLen; i++)
2915 switch (pExtRate[i] & 0x7f)
2917 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2918 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2919 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2920 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2921 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2922 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2923 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2924 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2925 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2926 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2927 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2928 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2929 default: Rate = RATE_1; break;
2931 if (MaxSupport < Rate) MaxSupport = Rate;
2933 if (MinSupport > Rate) MinSupport = Rate;
2936 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2939 // pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap;
2941 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2942 // the DURATION field of outgoing uniicast DATA/MGMT frame
2943 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2945 if (BasicRateBitmap & (0x01 << i))
2946 CurrBasicRate = (UCHAR)i;
2947 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2950 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2951 // max tx rate = min {max desire rate, max supported rate}
2952 if (MaxSupport < MaxDesire)
2953 pAd->CommonCfg.MaxTxRate = MaxSupport;
2955 pAd->CommonCfg.MaxTxRate = MaxDesire;
2957 pAd->CommonCfg.MinTxRate = MinSupport;
2958 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
2959 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
2961 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
2962 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
2963 // 3. -75 > RSSI, start at 11 Mbps (long distance)
2964 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
2965 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
2966 if (*auto_rate_cur_p)
2969 #ifdef CONFIG_STA_SUPPORT
2970 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2971 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2972 #endif // CONFIG_STA_SUPPORT //
2973 if (bLinkUp == TRUE)
2974 pAd->CommonCfg.TxRate = RATE_24;
2976 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2979 pAd->CommonCfg.TxRate = RATE_11;
2981 pAd->CommonCfg.TxRate = RATE_24;
2983 // should never exceed MaxTxRate (consider 11B-only mode)
2984 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2985 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2987 pAd->CommonCfg.TxRateIndex = 0;
2991 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2992 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
2993 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
2995 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
2996 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
2997 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
2998 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3001 if (pAd->CommonCfg.TxRate <= RATE_11)
3003 pMaxHtPhy->field.MODE = MODE_CCK;
3004 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3005 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3009 pMaxHtPhy->field.MODE = MODE_OFDM;
3010 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3011 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3012 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3014 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3017 pHtPhy->word = (pMaxHtPhy->word);
3018 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3020 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3021 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3022 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3026 switch (pAd->CommonCfg.PhyMode)
3028 case PHY_11BG_MIXED:
3030 #ifdef DOT11_N_SUPPORT
3031 case PHY_11BGN_MIXED:
3032 #endif // DOT11_N_SUPPORT //
3033 pAd->CommonCfg.MlmeRate = RATE_1;
3034 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3035 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3038 pAd->CommonCfg.RtsRate = RATE_11;
3040 // pAd->CommonCfg.RtsRate = RATE_1;
3045 #ifdef DOT11_N_SUPPORT
3046 case PHY_11AGN_MIXED:
3047 case PHY_11GN_MIXED:
3049 case PHY_11AN_MIXED:
3051 #endif // DOT11_N_SUPPORT //
3052 pAd->CommonCfg.MlmeRate = RATE_6;
3053 pAd->CommonCfg.RtsRate = RATE_6;
3054 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3055 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3057 case PHY_11ABG_MIXED:
3058 #ifdef DOT11_N_SUPPORT
3059 case PHY_11ABGN_MIXED:
3060 #endif // DOT11_N_SUPPORT //
3061 if (pAd->CommonCfg.Channel <= 14)
3063 pAd->CommonCfg.MlmeRate = RATE_1;
3064 pAd->CommonCfg.RtsRate = RATE_1;
3065 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3066 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3070 pAd->CommonCfg.MlmeRate = RATE_6;
3071 pAd->CommonCfg.RtsRate = RATE_6;
3072 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3073 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3077 pAd->CommonCfg.MlmeRate = RATE_6;
3078 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3079 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3080 pAd->CommonCfg.RtsRate = RATE_1;
3084 // Keep Basic Mlme Rate.
3086 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3087 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3088 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3090 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3091 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3094 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3095 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3096 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3097 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3098 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3099 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3100 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 ));
3103 #ifdef DOT11_N_SUPPORT
3105 ==========================================================================
3107 This function update HT Rate setting.
3108 Input Wcid value is valid for 2 case :
3109 1. it's used for Station in infra mode that copy AP rate to Mactable.
3110 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3112 IRQL = DISPATCH_LEVEL
3114 ==========================================================================
3116 VOID MlmeUpdateHtTxRates(
3117 IN PRTMP_ADAPTER pAd,
3120 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3122 RT_HT_CAPABILITY *pRtHtCap = NULL;
3123 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3126 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3127 PHTTRANSMIT_SETTING pHtPhy = NULL;
3128 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3129 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3130 BOOLEAN *auto_rate_cur_p;
3132 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3134 auto_rate_cur_p = NULL;
3136 #ifdef CONFIG_STA_SUPPORT
3137 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3139 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3140 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3141 pHtPhy = &pAd->StaCfg.HTPhyMode;
3142 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3143 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3145 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3147 #endif // CONFIG_STA_SUPPORT //
3149 #ifdef CONFIG_STA_SUPPORT
3150 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3152 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3155 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3156 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3157 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3158 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3159 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3160 pMaxHtPhy->field.STBC = STBC_USE;
3162 pMaxHtPhy->field.STBC = STBC_NONE;
3165 #endif // CONFIG_STA_SUPPORT //
3167 if (pDesireHtPhy->bHtEnable == FALSE)
3170 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3171 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3172 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3173 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3174 pMaxHtPhy->field.STBC = STBC_USE;
3176 pMaxHtPhy->field.STBC = STBC_NONE;
3179 // Decide MAX ht rate.
3180 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3181 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3183 pMaxHtPhy->field.MODE = MODE_HTMIX;
3185 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3186 pMaxHtPhy->field.BW = BW_40;
3188 pMaxHtPhy->field.BW = BW_20;
3190 if (pMaxHtPhy->field.BW == BW_20)
3191 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3193 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3195 for (i=23; i>=0; i--) // 3*3
3198 bitmask = (1<<(i-(j*8)));
3200 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3202 pMaxHtPhy->field.MCS = i;
3210 // Copy MIN ht rate. rt2860???
3211 pMinHtPhy->field.BW = BW_20;
3212 pMinHtPhy->field.MCS = 0;
3213 pMinHtPhy->field.STBC = 0;
3214 pMinHtPhy->field.ShortGI = 0;
3215 //If STA assigns fixed rate. update to fixed here.
3216 #ifdef CONFIG_STA_SUPPORT
3217 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3219 if (pDesireHtPhy->MCSSet[4] != 0)
3221 pMaxHtPhy->field.MCS = 32;
3222 pMinHtPhy->field.MCS = 32;
3223 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3226 for (i=23; (CHAR)i >= 0; i--) // 3*3
3229 bitmask = (1<<(i-(j*8)));
3230 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3232 pMaxHtPhy->field.MCS = i;
3233 pMinHtPhy->field.MCS = i;
3240 #endif // CONFIG_STA_SUPPORT //
3244 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3245 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3246 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3247 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3248 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3250 // use default now. rt2860
3251 if (pDesireHtPhy->MCSSet[0] != 0xff)
3252 *auto_rate_cur_p = FALSE;
3254 *auto_rate_cur_p = TRUE;
3256 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3257 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3258 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3259 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3261 #endif // DOT11_N_SUPPORT //
3263 // IRQL = DISPATCH_LEVEL
3265 IN PRTMP_ADAPTER pAd)
3267 RT28XX_MLME_RADIO_OFF(pAd);
3270 // IRQL = DISPATCH_LEVEL
3272 IN PRTMP_ADAPTER pAd)
3274 RT28XX_MLME_RADIO_ON(pAd);
3277 // ===========================================================================================
3279 // ===========================================================================================
3282 /*! \brief initialize BSS table
3283 * \param p_tab pointer to the table
3288 IRQL = PASSIVE_LEVEL
3289 IRQL = DISPATCH_LEVEL
3298 Tab->BssOverlapNr = 0;
3299 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3301 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3302 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3306 #ifdef DOT11_N_SUPPORT
3308 IN PRTMP_ADAPTER pAd,
3313 Tab->numAsOriginator = 0;
3314 Tab->numAsRecipient = 0;
3315 NdisAllocateSpinLock(&pAd->BATabLock);
3316 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3318 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3319 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3321 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3323 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3326 #endif // DOT11_N_SUPPORT //
3328 /*! \brief search the BSS table by SSID
3329 * \param p_tab pointer to the bss table
3330 * \param ssid SSID string
3331 * \return index of the table, BSS_NOT_FOUND if not in the table
3334 * \note search by sequential search
3336 IRQL = DISPATCH_LEVEL
3339 ULONG BssTableSearch(
3346 for (i = 0; i < Tab->BssNr; i++)
3349 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3350 // We should distinguish this case.
3352 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3353 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3354 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3359 return (ULONG)BSS_NOT_FOUND;
3362 ULONG BssSsidTableSearch(
3371 for (i = 0; i < Tab->BssNr; i++)
3374 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3375 // We should distinguish this case.
3377 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3378 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3379 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3380 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3385 return (ULONG)BSS_NOT_FOUND;
3388 ULONG BssTableSearchWithSSID(
3397 for (i = 0; i < Tab->BssNr; i++)
3399 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3400 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3401 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3402 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3403 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3404 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3409 return (ULONG)BSS_NOT_FOUND;
3412 // IRQL = DISPATCH_LEVEL
3413 VOID BssTableDeleteEntry(
3414 IN OUT BSS_TABLE *Tab,
3420 for (i = 0; i < Tab->BssNr; i++)
3422 if ((Tab->BssEntry[i].Channel == Channel) &&
3423 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3425 for (j = i; j < Tab->BssNr - 1; j++)
3427 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3429 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3436 #ifdef DOT11_N_SUPPORT
3438 ========================================================================
3439 Routine Description:
3440 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3443 // IRQL = DISPATCH_LEVEL
3444 ========================================================================
3446 VOID BATableDeleteORIEntry(
3447 IN OUT PRTMP_ADAPTER pAd,
3448 IN BA_ORI_ENTRY *pBAORIEntry)
3451 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3453 NdisAcquireSpinLock(&pAd->BATabLock);
3454 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3456 pAd->BATable.numAsOriginator -= 1;
3457 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3458 // Erase Bitmap flag.
3460 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3461 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3462 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3463 pBAORIEntry->Token = 1;
3464 // Not clear Sequence here.
3465 NdisReleaseSpinLock(&pAd->BATabLock);
3468 #endif // DOT11_N_SUPPORT //
3476 IRQL = DISPATCH_LEVEL
3480 IN PRTMP_ADAPTER pAd,
3481 OUT BSS_ENTRY *pBss,
3486 IN USHORT BeaconPeriod,
3487 IN PCF_PARM pCfParm,
3489 IN USHORT CapabilityInfo,
3491 IN UCHAR SupRateLen,
3493 IN UCHAR ExtRateLen,
3494 IN HT_CAPABILITY_IE *pHtCapability,
3495 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3496 IN UCHAR HtCapabilityLen,
3497 IN UCHAR AddHtInfoLen,
3498 IN UCHAR NewExtChanOffset,
3501 IN LARGE_INTEGER TimeStamp,
3503 IN PEDCA_PARM pEdcaParm,
3504 IN PQOS_CAPABILITY_PARM pQosCapability,
3505 IN PQBSS_LOAD_PARM pQbssLoad,
3506 IN USHORT LengthVIE,
3507 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3509 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3510 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3514 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3515 // Or send beacon /probe response with SSID len matching real SSID length,
3516 // but SSID is all zero. such as "00-00-00-00" with length 4.
3517 // We have to prevent this case overwrite correct table
3518 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3520 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3521 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3522 pBss->SsidLen = SsidLen;
3528 pBss->BssType = BssType;
3529 pBss->BeaconPeriod = BeaconPeriod;
3530 if (BssType == BSS_INFRA)
3532 if (pCfParm->bValid)
3534 pBss->CfpCount = pCfParm->CfpCount;
3535 pBss->CfpPeriod = pCfParm->CfpPeriod;
3536 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3537 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3542 pBss->AtimWin = AtimWin;
3545 pBss->CapabilityInfo = CapabilityInfo;
3546 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3547 // Combine with AuthMode, they will decide the connection methods.
3548 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3549 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3550 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3551 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3553 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3554 pBss->SupRateLen = SupRateLen;
3555 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3556 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3557 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3558 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3559 pBss->NewExtChanOffset = NewExtChanOffset;
3560 pBss->ExtRateLen = ExtRateLen;
3561 pBss->Channel = Channel;
3562 pBss->CentralChannel = Channel;
3564 // Update CkipFlag. if not exists, the value is 0x0
3565 pBss->CkipFlag = CkipFlag;
3567 // New for microsoft Fixed IEs
3568 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3569 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3570 pBss->FixIEs.Capabilities = CapabilityInfo;
3572 // New for microsoft Variable IEs
3575 pBss->VarIELen = LengthVIE;
3576 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3583 pBss->AddHtInfoLen = 0;
3584 pBss->HtCapabilityLen = 0;
3585 #ifdef DOT11_N_SUPPORT
3586 if (HtCapabilityLen> 0)
3588 pBss->HtCapabilityLen = HtCapabilityLen;
3589 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3590 if (AddHtInfoLen > 0)
3592 pBss->AddHtInfoLen = AddHtInfoLen;
3593 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3595 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3597 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3599 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3601 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3605 #endif // DOT11_N_SUPPORT //
3607 BssCipherParse(pBss);
3611 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3613 pBss->EdcaParm.bValid = FALSE;
3615 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3617 pBss->QosCapability.bValid = FALSE;
3619 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3621 pBss->QbssLoad.bValid = FALSE;
3623 #ifdef CONFIG_STA_SUPPORT
3624 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3630 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3631 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3632 #ifdef EXT_BUILD_CHANNEL_LIST
3633 NdisZeroMemory(&pBss->CountryString[0], 3);
3634 pBss->bHasCountryIE = FALSE;
3635 #endif // EXT_BUILD_CHANNEL_LIST //
3636 pEid = (PEID_STRUCT) pVIE;
3637 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3642 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3644 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3646 pBss->WpaIE.IELen = 0;
3649 pBss->WpaIE.IELen = pEid->Len + 2;
3650 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3654 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3656 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3658 pBss->RsnIE.IELen = 0;
3661 pBss->RsnIE.IELen = pEid->Len + 2;
3662 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3665 #ifdef EXT_BUILD_CHANNEL_LIST
3667 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3668 pBss->bHasCountryIE = TRUE;
3670 #endif // EXT_BUILD_CHANNEL_LIST //
3672 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3673 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3676 #endif // CONFIG_STA_SUPPORT //
3680 * \brief insert an entry into the bss table
3681 * \param p_tab The BSS table
3682 * \param Bssid BSSID
3684 * \param ssid_len Length of SSID
3686 * \param beacon_period
3693 * \param channel_idx
3697 * \note If SSID is identical, the old entry will be replaced by the new one
3699 IRQL = DISPATCH_LEVEL
3702 ULONG BssTableSetEntry(
3703 IN PRTMP_ADAPTER pAd,
3709 IN USHORT BeaconPeriod,
3712 IN USHORT CapabilityInfo,
3714 IN UCHAR SupRateLen,
3716 IN UCHAR ExtRateLen,
3717 IN HT_CAPABILITY_IE *pHtCapability,
3718 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3719 IN UCHAR HtCapabilityLen,
3720 IN UCHAR AddHtInfoLen,
3721 IN UCHAR NewExtChanOffset,
3724 IN LARGE_INTEGER TimeStamp,
3726 IN PEDCA_PARM pEdcaParm,
3727 IN PQOS_CAPABILITY_PARM pQosCapability,
3728 IN PQBSS_LOAD_PARM pQbssLoad,
3729 IN USHORT LengthVIE,
3730 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3734 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3735 if (Idx == BSS_NOT_FOUND)
3737 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3740 // It may happen when BSS Table was full.
3741 // The desired AP will not be added into BSS Table
3742 // In this case, if we found the desired AP then overwrite BSS Table.
3744 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3746 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3747 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3749 Idx = Tab->BssOverlapNr;
3750 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3751 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3752 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3753 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3759 return BSS_NOT_FOUND;
3763 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3764 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3765 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3770 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3771 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3772 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3778 #ifdef CONFIG_STA_SUPPORT
3779 #ifdef DOT11_N_SUPPORT
3780 #ifdef DOT11N_DRAFT3
3782 IN PRTMP_ADAPTER pAd)
3786 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3787 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3789 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3790 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3793 ULONG TriEventTableSetEntry(
3794 IN PRTMP_ADAPTER pAd,
3795 OUT TRIGGER_EVENT_TAB *Tab,
3797 IN HT_CAPABILITY_IE *pHtCapability,
3798 IN UCHAR HtCapabilityLen,
3803 if (HtCapabilityLen == 0)
3805 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3807 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3808 Tab->EventA[Tab->EventANo].bValid = TRUE;
3809 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3810 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3813 // Beacon has Regulatory class IE. So use beacon's
3814 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3818 // Use Station's Regulatory class instead.
3819 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3821 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3823 Tab->EventA[Tab->EventANo].RegClass = 32;
3825 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3826 Tab->EventA[Tab->EventANo].RegClass = 33;
3829 Tab->EventA[Tab->EventANo].RegClass = ??;
3836 else if (pHtCapability->HtCapInfo.Intolerant40)
3838 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3844 ========================================================================
3845 Routine Description:
3846 Trigger Event table Maintainence called once every second.
3849 // IRQL = DISPATCH_LEVEL
3850 ========================================================================
3852 VOID TriEventCounterMaintenance(
3853 IN PRTMP_ADAPTER pAd)
3856 BOOLEAN bNotify = FALSE;
3857 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3859 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3861 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3862 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3864 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3865 pAd->CommonCfg.TriggerEventTab.EventANo --;
3866 // Need to send 20/40 Coexistence Notify frame if has status change.
3871 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
3873 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
3874 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
3878 if (bNotify == TRUE)
3879 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
3881 #endif // DOT11N_DRAFT3 //
3882 #endif // DOT11_N_SUPPORT //
3884 // IRQL = DISPATCH_LEVEL
3885 VOID BssTableSsidSort(
3886 IN PRTMP_ADAPTER pAd,
3887 OUT BSS_TABLE *OutTab,
3892 BssTableInit(OutTab);
3894 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3896 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3897 BOOLEAN bIsHiddenApIncluded = FALSE;
3899 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3900 (pAd->MlmeAux.Channel > 14) &&
3901 RadarChannelCheck(pAd, pInBss->Channel))
3905 bIsHiddenApIncluded = TRUE;
3908 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3909 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3911 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3914 #ifdef EXT_BUILD_CHANNEL_LIST
3915 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
3916 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
3917 (pInBss->bHasCountryIE == FALSE))
3919 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
3922 #endif // EXT_BUILD_CHANNEL_LIST //
3924 #ifdef DOT11_N_SUPPORT
3925 // 2.4G/5G N only mode
3926 if ((pInBss->HtCapabilityLen == 0) &&
3927 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3929 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3932 #endif // DOT11_N_SUPPORT //
3935 // Check the Authmode first
3936 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3938 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3939 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3943 // Check cipher suite, AP must have more secured cipher than station setting
3944 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3946 // If it's not mixed mode, we should only let BSS pass with the same encryption
3947 if (pInBss->WPA.bMixMode == FALSE)
3948 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3951 // check group cipher
3952 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3953 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3954 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3957 // check pairwise cipher, skip if none matched
3958 // If profile set to AES, let it pass without question.
3959 // If profile set to TKIP, we must find one mateched
3960 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3961 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3962 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3965 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3967 // If it's not mixed mode, we should only let BSS pass with the same encryption
3968 if (pInBss->WPA2.bMixMode == FALSE)
3969 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3972 // check group cipher
3973 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3974 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3975 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3978 // check pairwise cipher, skip if none matched
3979 // If profile set to AES, let it pass without question.
3980 // If profile set to TKIP, we must find one mateched
3981 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3982 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3983 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3987 // Bss Type matched, SSID matched.
3988 // We will check wepstatus for qualification Bss
3989 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3991 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3993 // For the SESv2 case, we will not qualify WepStatus.
3999 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4000 // It definitely will fail. So, skip it.
4001 // CCX also require not even try to connect it!!
4005 #ifdef DOT11_N_SUPPORT
4006 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4007 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4008 if ((pInBss->CentralChannel != pInBss->Channel) &&
4009 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4011 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4013 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4015 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4019 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4025 #endif // DOT11_N_SUPPORT //
4027 // copy matching BSS from InTab to OutTab
4028 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4032 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4034 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4037 #ifdef DOT11_N_SUPPORT
4038 // 2.4G/5G N only mode
4039 if ((pInBss->HtCapabilityLen == 0) &&
4040 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4042 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4045 #endif // DOT11_N_SUPPORT //
4048 // Check the Authmode first
4049 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4051 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4052 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4056 // Check cipher suite, AP must have more secured cipher than station setting
4057 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4059 // If it's not mixed mode, we should only let BSS pass with the same encryption
4060 if (pInBss->WPA.bMixMode == FALSE)
4061 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4064 // check group cipher
4065 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4068 // check pairwise cipher, skip if none matched
4069 // If profile set to AES, let it pass without question.
4070 // If profile set to TKIP, we must find one mateched
4071 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4072 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4073 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4076 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4078 // If it's not mixed mode, we should only let BSS pass with the same encryption
4079 if (pInBss->WPA2.bMixMode == FALSE)
4080 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4083 // check group cipher
4084 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4087 // check pairwise cipher, skip if none matched
4088 // If profile set to AES, let it pass without question.
4089 // If profile set to TKIP, we must find one mateched
4090 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4091 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4092 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4096 // Bss Type matched, SSID matched.
4097 // We will check wepstatus for qualification Bss
4098 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4101 #ifdef DOT11_N_SUPPORT
4102 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4103 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4104 if ((pInBss->CentralChannel != pInBss->Channel) &&
4105 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4107 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4109 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4111 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4114 #endif // DOT11_N_SUPPORT //
4116 // copy matching BSS from InTab to OutTab
4117 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4122 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4126 BssTableSortByRssi(OutTab);
4130 // IRQL = DISPATCH_LEVEL
4131 VOID BssTableSortByRssi(
4132 IN OUT BSS_TABLE *OutTab)
4137 for (i = 0; i < OutTab->BssNr - 1; i++)
4139 for (j = i+1; j < OutTab->BssNr; j++)
4141 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4143 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4144 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4145 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4150 #endif // CONFIG_STA_SUPPORT //
4153 VOID BssCipherParse(
4154 IN OUT PBSS_ENTRY pBss)
4158 PRSN_IE_HEADER_STRUCT pRsnHeader;
4159 PCIPHER_SUITE_STRUCT pCipher;
4160 PAKM_SUITE_STRUCT pAKM;
4163 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4166 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4170 pBss->WepStatus = Ndis802_11WEPEnabled;
4174 pBss->WepStatus = Ndis802_11WEPDisabled;
4176 // Set default to disable & open authentication before parsing variable IE
4177 pBss->AuthMode = Ndis802_11AuthModeOpen;
4178 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4181 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4182 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4183 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4184 pBss->WPA.RsnCapability = 0;
4185 pBss->WPA.bMixMode = FALSE;
4187 // Init WPA2 setting
4188 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4189 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4190 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4191 pBss->WPA2.RsnCapability = 0;
4192 pBss->WPA2.bMixMode = FALSE;
4195 Length = (INT) pBss->VarIELen;
4199 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4200 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4201 pEid = (PEID_STRUCT) pTmp;
4205 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4206 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4212 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4213 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4214 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4215 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4218 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4219 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4220 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4223 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4224 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4225 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4231 // if Cisco IE_WPA, break
4234 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4239 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4241 // if unsupported vendor specific IE
4244 // Skip OUI, version, and multicast suite
4245 // This part should be improved in the future when AP supported multiple cipher suite.
4246 // For now, it's OK since almost all APs have fixed cipher suite supported.
4247 // pTmp = (PUCHAR) pEid->Octet;
4250 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4258 // Parse group cipher
4262 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4265 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4268 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4271 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4276 // number of unicast suite
4279 // skip all unicast cipher suites
4280 //Count = *(PUSHORT) pTmp;
4281 Count = (pTmp[1]<<8) + pTmp[0];
4282 pTmp += sizeof(USHORT);
4284 // Parsing all unicast cipher suite
4289 TmpCipher = Ndis802_11WEPDisabled;
4293 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4294 TmpCipher = Ndis802_11Encryption1Enabled;
4297 TmpCipher = Ndis802_11Encryption2Enabled;
4300 TmpCipher = Ndis802_11Encryption3Enabled;
4305 if (TmpCipher > pBss->WPA.PairCipher)
4307 // Move the lower cipher suite to PairCipherAux
4308 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4309 pBss->WPA.PairCipher = TmpCipher;
4313 pBss->WPA.PairCipherAux = TmpCipher;
4319 // 4. get AKM suite counts
4320 //Count = *(PUSHORT) pTmp;
4321 Count = (pTmp[1]<<8) + pTmp[0];
4322 pTmp += sizeof(USHORT);
4328 // Set AP support WPA mode
4329 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4330 pBss->AuthMode = Ndis802_11AuthModeWPA;
4332 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4335 // Set AP support WPA mode
4336 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4337 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4339 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4346 // Fixed for WPA-None
4347 if (pBss->BssType == BSS_ADHOC)
4349 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4350 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4351 pBss->WepStatus = pBss->WPA.GroupCipher;
4352 // Patched bugs for old driver
4353 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4354 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4357 pBss->WepStatus = pBss->WPA.PairCipher;
4359 // Check the Pair & Group, if different, turn on mixed mode flag
4360 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4361 pBss->WPA.bMixMode = TRUE;
4366 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4368 // 0. Version must be 1
4369 if (le2cpu16(pRsnHeader->Version) != 1)
4371 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4373 // 1. Check group cipher
4374 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4375 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4378 // Parse group cipher
4379 switch (pCipher->Type)
4382 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4385 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4388 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4391 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4396 // set to correct offset for next parsing
4397 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4399 // 2. Get pairwise cipher counts
4400 //Count = *(PUSHORT) pTmp;
4401 Count = (pTmp[1]<<8) + pTmp[0];
4402 pTmp += sizeof(USHORT);
4404 // 3. Get pairwise cipher
4405 // Parsing all unicast cipher suite
4409 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4410 TmpCipher = Ndis802_11WEPDisabled;
4411 switch (pCipher->Type)
4414 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4415 TmpCipher = Ndis802_11Encryption1Enabled;
4418 TmpCipher = Ndis802_11Encryption2Enabled;
4421 TmpCipher = Ndis802_11Encryption3Enabled;
4426 if (TmpCipher > pBss->WPA2.PairCipher)
4428 // Move the lower cipher suite to PairCipherAux
4429 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4430 pBss->WPA2.PairCipher = TmpCipher;
4434 pBss->WPA2.PairCipherAux = TmpCipher;
4436 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4440 // 4. get AKM suite counts
4441 //Count = *(PUSHORT) pTmp;
4442 Count = (pTmp[1]<<8) + pTmp[0];
4443 pTmp += sizeof(USHORT);
4445 // 5. Get AKM ciphers
4446 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4447 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4453 // Set AP support WPA mode
4454 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4455 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4457 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4460 // Set AP support WPA mode
4461 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4462 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4464 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4469 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4471 // Fixed for WPA-None
4472 if (pBss->BssType == BSS_ADHOC)
4474 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4475 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4476 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4477 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4478 pBss->WepStatus = pBss->WPA.GroupCipher;
4479 // Patched bugs for old driver
4480 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4481 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4483 pBss->WepStatus = pBss->WPA2.PairCipher;
4485 // 6. Get RSN capability
4486 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4487 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4488 pTmp += sizeof(USHORT);
4490 // Check the Pair & Group, if different, turn on mixed mode flag
4491 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4492 pBss->WPA2.bMixMode = TRUE;
4498 Length -= (pEid->Len + 2);
4502 // ===========================================================================================
4504 // ===========================================================================================
4506 /*! \brief generates a random mac address value for IBSS BSSID
4507 * \param Addr the bssid location
4512 VOID MacAddrRandomBssid(
4513 IN PRTMP_ADAPTER pAd,
4518 for (i = 0; i < MAC_ADDR_LEN; i++)
4520 pAddr[i] = RandomByte(pAd);
4523 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4526 /*! \brief init the management mac frame header
4527 * \param p_hdr mac header
4528 * \param subtype subtype of the frame
4529 * \param p_ds destination address, don't care if it is a broadcast address
4531 * \pre the station has the following information in the pAd->StaCfg
4535 * \note this function initializes the following field
4537 IRQL = PASSIVE_LEVEL
4538 IRQL = DISPATCH_LEVEL
4541 VOID MgtMacHeaderInit(
4542 IN PRTMP_ADAPTER pAd,
4543 IN OUT PHEADER_802_11 pHdr80211,
4549 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4551 pHdr80211->FC.Type = BTYPE_MGMT;
4552 pHdr80211->FC.SubType = SubType;
4553 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4554 // pHdr80211->FC.Type = BTYPE_CNTL;
4555 pHdr80211->FC.ToDs = ToDs;
4556 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4557 #ifdef CONFIG_STA_SUPPORT
4558 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4559 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4560 #endif // CONFIG_STA_SUPPORT //
4561 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4564 // ===========================================================================================
4566 // ===========================================================================================
4568 /*!***************************************************************************
4569 * This routine build an outgoing frame, and fill all information specified
4570 * in argument list to the frame body. The actual frame size is the summation
4573 * Buffer - pointer to a pre-allocated memory segment
4574 * args - a list of <int arg_size, arg> pairs.
4575 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4576 * function will FAIL!!!
4578 * Size of the buffer
4580 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4582 IRQL = PASSIVE_LEVEL
4583 IRQL = DISPATCH_LEVEL
4585 ****************************************************************************/
4586 ULONG MakeOutgoingFrame(
4588 OUT ULONG *FrameLen, ...)
4595 // calculates the total length
4597 va_start(Args, FrameLen);
4600 leng = va_arg(Args, int);
4601 if (leng == END_OF_ARGS)
4605 p = va_arg(Args, PVOID);
4606 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4607 TotLeng = TotLeng + leng;
4610 va_end(Args); /* clean up */
4611 *FrameLen = TotLeng;
4615 // ===========================================================================================
4617 // ===========================================================================================
4619 /*! \brief Initialize The MLME Queue, used by MLME Functions
4620 * \param *Queue The MLME Queue
4621 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4624 * \note Because this is done only once (at the init stage), no need to be locked
4626 IRQL = PASSIVE_LEVEL
4629 NDIS_STATUS MlmeQueueInit(
4630 IN MLME_QUEUE *Queue)
4634 NdisAllocateSpinLock(&Queue->Lock);
4640 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4642 Queue->Entry[i].Occupied = FALSE;
4643 Queue->Entry[i].MsgLen = 0;
4644 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4647 return NDIS_STATUS_SUCCESS;
4650 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4651 * \param *Queue The MLME Queue
4652 * \param Machine The State Machine Id
4653 * \param MsgType The Message Type
4654 * \param MsgLen The Message length
4655 * \param *Msg The message pointer
4656 * \return TRUE if enqueue is successful, FALSE if the queue is full
4659 * \note The message has to be initialized
4661 IRQL = PASSIVE_LEVEL
4662 IRQL = DISPATCH_LEVEL
4665 BOOLEAN MlmeEnqueue(
4666 IN PRTMP_ADAPTER pAd,
4673 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4675 // Do nothing if the driver is starting halt state.
4676 // This might happen when timer already been fired before cancel timer with mlmehalt
4677 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4680 // First check the size, it MUST not exceed the mlme queue size
4681 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4683 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4687 if (MlmeQueueFull(Queue))
4692 NdisAcquireSpinLock(&(Queue->Lock));
4696 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4701 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4702 Queue->Entry[Tail].Occupied = TRUE;
4703 Queue->Entry[Tail].Machine = Machine;
4704 Queue->Entry[Tail].MsgType = MsgType;
4705 Queue->Entry[Tail].MsgLen = MsgLen;
4709 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4712 NdisReleaseSpinLock(&(Queue->Lock));
4716 /*! \brief This function is used when Recv gets a MLME message
4717 * \param *Queue The MLME Queue
4718 * \param TimeStampHigh The upper 32 bit of timestamp
4719 * \param TimeStampLow The lower 32 bit of timestamp
4720 * \param Rssi The receiving RSSI strength
4721 * \param MsgLen The length of the message
4722 * \param *Msg The message pointer
4723 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4727 IRQL = DISPATCH_LEVEL
4730 BOOLEAN MlmeEnqueueForRecv(
4731 IN PRTMP_ADAPTER pAd,
4733 IN ULONG TimeStampHigh,
4734 IN ULONG TimeStampLow,
4743 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4745 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4747 // Do nothing if the driver is starting halt state.
4748 // This might happen when timer already been fired before cancel timer with mlmehalt
4749 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4751 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4755 // First check the size, it MUST not exceed the mlme queue size
4756 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4758 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4762 if (MlmeQueueFull(Queue))
4767 #ifdef CONFIG_STA_SUPPORT
4768 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4770 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4772 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4776 #endif // CONFIG_STA_SUPPORT //
4778 // OK, we got all the informations, it is time to put things into queue
4779 NdisAcquireSpinLock(&(Queue->Lock));
4783 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4787 Queue->Entry[Tail].Occupied = TRUE;
4788 Queue->Entry[Tail].Machine = Machine;
4789 Queue->Entry[Tail].MsgType = MsgType;
4790 Queue->Entry[Tail].MsgLen = MsgLen;
4791 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4792 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4793 Queue->Entry[Tail].Rssi0 = Rssi0;
4794 Queue->Entry[Tail].Rssi1 = Rssi1;
4795 Queue->Entry[Tail].Rssi2 = Rssi2;
4796 Queue->Entry[Tail].Signal = Signal;
4797 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4799 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4803 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4806 NdisReleaseSpinLock(&(Queue->Lock));
4808 RT28XX_MLME_HANDLER(pAd);
4814 /*! \brief Dequeue a message from the MLME Queue
4815 * \param *Queue The MLME Queue
4816 * \param *Elem The message dequeued from MLME Queue
4817 * \return TRUE if the Elem contains something, FALSE otherwise
4821 IRQL = DISPATCH_LEVEL
4824 BOOLEAN MlmeDequeue(
4825 IN MLME_QUEUE *Queue,
4826 OUT MLME_QUEUE_ELEM **Elem)
4828 NdisAcquireSpinLock(&(Queue->Lock));
4829 *Elem = &(Queue->Entry[Queue->Head]);
4832 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4836 NdisReleaseSpinLock(&(Queue->Lock));
4840 // IRQL = DISPATCH_LEVEL
4841 VOID MlmeRestartStateMachine(
4842 IN PRTMP_ADAPTER pAd)
4844 #ifdef CONFIG_STA_SUPPORT
4846 #endif // CONFIG_STA_SUPPORT //
4848 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4851 #ifdef CONFIG_STA_SUPPORT
4852 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4854 // Cancel all timer events
4855 // Be careful to cancel new added timer
4856 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4857 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4858 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4859 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4860 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4861 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4863 #endif // CONFIG_STA_SUPPORT //
4865 // Change back to original channel in case of doing scan
4866 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4867 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4869 // Resume MSDU which is turned off durning scan
4870 RTMPResumeMsduTransmission(pAd);
4872 #ifdef CONFIG_STA_SUPPORT
4873 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4875 // Set all state machines back IDLE
4876 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4877 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4878 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4879 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4880 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4881 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4883 #endif // CONFIG_STA_SUPPORT //
4887 /*! \brief test if the MLME Queue is empty
4888 * \param *Queue The MLME Queue
4889 * \return TRUE if the Queue is empty, FALSE otherwise
4893 IRQL = DISPATCH_LEVEL
4896 BOOLEAN MlmeQueueEmpty(
4897 IN MLME_QUEUE *Queue)
4901 NdisAcquireSpinLock(&(Queue->Lock));
4902 Ans = (Queue->Num == 0);
4903 NdisReleaseSpinLock(&(Queue->Lock));
4908 /*! \brief test if the MLME Queue is full
4909 * \param *Queue The MLME Queue
4910 * \return TRUE if the Queue is empty, FALSE otherwise
4914 IRQL = PASSIVE_LEVEL
4915 IRQL = DISPATCH_LEVEL
4918 BOOLEAN MlmeQueueFull(
4919 IN MLME_QUEUE *Queue)
4923 NdisAcquireSpinLock(&(Queue->Lock));
4924 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4925 NdisReleaseSpinLock(&(Queue->Lock));
4930 /*! \brief The destructor of MLME Queue
4935 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4937 IRQL = PASSIVE_LEVEL
4940 VOID MlmeQueueDestroy(
4941 IN MLME_QUEUE *pQueue)
4943 NdisAcquireSpinLock(&(pQueue->Lock));
4947 NdisReleaseSpinLock(&(pQueue->Lock));
4948 NdisFreeSpinLock(&(pQueue->Lock));
4951 /*! \brief To substitute the message type if the message is coming from external
4952 * \param pFrame The frame received
4953 * \param *Machine The state machine
4954 * \param *MsgType the message type for the state machine
4955 * \return TRUE if the substitution is successful, FALSE otherwise
4959 IRQL = DISPATCH_LEVEL
4962 #ifdef CONFIG_STA_SUPPORT
4963 BOOLEAN MsgTypeSubst(
4964 IN PRTMP_ADAPTER pAd,
4965 IN PFRAME_802_11 pFrame,
4973 // Pointer to start of data frames including SNAP header
4974 pData = (PUCHAR) pFrame + LENGTH_802_11;
4976 // The only data type will pass to this function is EAPOL frame
4977 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4979 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4981 // Cisco Aironet SNAP header
4982 *Machine = AIRONET_STATE_MACHINE;
4983 *MsgType = MT2_AIRONET_MSG;
4987 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
4990 *Machine = LEAP_STATE_MACHINE;
4991 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4992 return (LeapMsgTypeSubst(EAPType, MsgType));
4995 #endif // LEAP_SUPPORT //
4997 *Machine = WPA_PSK_STATE_MACHINE;
4998 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4999 return(WpaMsgTypeSubst(EAPType, MsgType));
5003 switch (pFrame->Hdr.FC.SubType)
5005 case SUBTYPE_ASSOC_REQ:
5006 *Machine = ASSOC_STATE_MACHINE;
5007 *MsgType = MT2_PEER_ASSOC_REQ;
5009 case SUBTYPE_ASSOC_RSP:
5010 *Machine = ASSOC_STATE_MACHINE;
5011 *MsgType = MT2_PEER_ASSOC_RSP;
5013 case SUBTYPE_REASSOC_REQ:
5014 *Machine = ASSOC_STATE_MACHINE;
5015 *MsgType = MT2_PEER_REASSOC_REQ;
5017 case SUBTYPE_REASSOC_RSP:
5018 *Machine = ASSOC_STATE_MACHINE;
5019 *MsgType = MT2_PEER_REASSOC_RSP;
5021 case SUBTYPE_PROBE_REQ:
5022 *Machine = SYNC_STATE_MACHINE;
5023 *MsgType = MT2_PEER_PROBE_REQ;
5025 case SUBTYPE_PROBE_RSP:
5026 *Machine = SYNC_STATE_MACHINE;
5027 *MsgType = MT2_PEER_PROBE_RSP;
5029 case SUBTYPE_BEACON:
5030 *Machine = SYNC_STATE_MACHINE;
5031 *MsgType = MT2_PEER_BEACON;
5034 *Machine = SYNC_STATE_MACHINE;
5035 *MsgType = MT2_PEER_ATIM;
5037 case SUBTYPE_DISASSOC:
5038 *Machine = ASSOC_STATE_MACHINE;
5039 *MsgType = MT2_PEER_DISASSOC_REQ;
5042 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5043 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5044 if (Seq == 1 || Seq == 3)
5046 *Machine = AUTH_RSP_STATE_MACHINE;
5047 *MsgType = MT2_PEER_AUTH_ODD;
5049 else if (Seq == 2 || Seq == 4)
5051 *Machine = AUTH_STATE_MACHINE;
5052 *MsgType = MT2_PEER_AUTH_EVEN;
5059 case SUBTYPE_DEAUTH:
5060 *Machine = AUTH_RSP_STATE_MACHINE;
5061 *MsgType = MT2_PEER_DEAUTH;
5063 case SUBTYPE_ACTION:
5064 *Machine = ACTION_STATE_MACHINE;
5065 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5066 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5068 *MsgType = MT2_ACT_INVALID;
5072 *MsgType = (pFrame->Octet[0]&0x7F);
5082 #endif // CONFIG_STA_SUPPORT //
5084 // ===========================================================================================
5086 // ===========================================================================================
5088 /*! \brief Initialize the state machine.
5089 * \param *S pointer to the state machine
5090 * \param Trans State machine transition function
5091 * \param StNr number of states
5092 * \param MsgNr number of messages
5093 * \param DefFunc default function, when there is invalid state/message combination
5094 * \param InitState initial state of the state machine
5095 * \param Base StateMachine base, internal use only
5096 * \pre p_sm should be a legal pointer
5099 IRQL = PASSIVE_LEVEL
5102 VOID StateMachineInit(
5103 IN STATE_MACHINE *S,
5104 IN STATE_MACHINE_FUNC Trans[],
5107 IN STATE_MACHINE_FUNC DefFunc,
5113 // set number of states and messages
5118 S->TransFunc = Trans;
5120 // init all state transition to default function
5121 for (i = 0; i < StNr; i++)
5123 for (j = 0; j < MsgNr; j++)
5125 S->TransFunc[i * MsgNr + j] = DefFunc;
5129 // set the starting state
5130 S->CurrState = InitState;
5133 /*! \brief This function fills in the function pointer into the cell in the state machine
5134 * \param *S pointer to the state machine
5136 * \param Msg incoming message
5137 * \param f the function to be executed when (state, message) combination occurs at the state machine
5138 * \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
5141 IRQL = PASSIVE_LEVEL
5144 VOID StateMachineSetAction(
5145 IN STATE_MACHINE *S,
5148 IN STATE_MACHINE_FUNC Func)
5152 MsgIdx = Msg - S->Base;
5154 if (St < S->NrState && MsgIdx < S->NrMsg)
5156 // boundary checking before setting the action
5157 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5161 /*! \brief This function does the state transition
5162 * \param *Adapter the NIC adapter pointer
5163 * \param *S the state machine
5164 * \param *Elem the message to be executed
5167 IRQL = DISPATCH_LEVEL
5170 VOID StateMachinePerformAction(
5171 IN PRTMP_ADAPTER pAd,
5172 IN STATE_MACHINE *S,
5173 IN MLME_QUEUE_ELEM *Elem)
5175 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5179 ==========================================================================
5181 The drop function, when machine executes this, the message is simply
5182 ignored. This function does nothing, the message is freed in
5183 StateMachinePerformAction()
5184 ==========================================================================
5187 IN PRTMP_ADAPTER pAd,
5188 IN MLME_QUEUE_ELEM *Elem)
5192 // ===========================================================================================
5194 // ===========================================================================================
5197 ==========================================================================
5200 IRQL = PASSIVE_LEVEL
5202 ==========================================================================
5205 IN PRTMP_ADAPTER pAd,
5209 pAd->Mlme.ShiftReg = 1;
5211 pAd->Mlme.ShiftReg = Seed;
5215 ==========================================================================
5217 ==========================================================================
5220 IN PRTMP_ADAPTER pAd)
5227 if (pAd->Mlme.ShiftReg == 0)
5228 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5230 for (i = 0; i < 8; i++)
5232 if (pAd->Mlme.ShiftReg & 0x00000001)
5234 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5239 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5242 R = (R << 1) | Result;
5248 VOID AsicUpdateAutoFallBackTable(
5249 IN PRTMP_ADAPTER pAd,
5250 IN PUCHAR pRateTable)
5253 HT_FBK_CFG0_STRUC HtCfg0;
5254 HT_FBK_CFG1_STRUC HtCfg1;
5255 LG_FBK_CFG0_STRUC LgCfg0;
5256 LG_FBK_CFG1_STRUC LgCfg1;
5257 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5259 // set to initial value
5260 HtCfg0.word = 0x65432100;
5261 HtCfg1.word = 0xedcba988;
5262 LgCfg0.word = 0xedcba988;
5263 LgCfg1.word = 0x00002100;
5265 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5266 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5268 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5269 switch (pCurrTxRate->Mode)
5275 switch(pCurrTxRate->CurrMCS)
5278 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5281 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5284 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5287 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5290 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5293 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5296 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5299 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5304 #ifdef DOT11_N_SUPPORT
5308 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5310 switch(pCurrTxRate->CurrMCS)
5313 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5316 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5319 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5322 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5325 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5328 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5331 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5334 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5337 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5340 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5343 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5346 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5349 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5352 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5355 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5358 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5361 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5366 #endif // DOT11_N_SUPPORT //
5369 pNextTxRate = pCurrTxRate;
5372 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5373 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5374 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5375 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5379 ========================================================================
5381 Routine Description:
5382 Set MAC register value according operation mode.
5383 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5384 If MM or GF mask is not set, those passing argument doesn't not take effect.
5386 Operation mode meaning:
5387 = 0 : Pure HT, no preotection.
5388 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5389 = 0x10: No Transmission in 40M is protected.
5390 = 0x11: Transmission in both 40M and 20M shall be protected
5392 we should choose not to use GF. But still set correct ASIC registers.
5393 ========================================================================
5395 VOID AsicUpdateProtect(
5396 IN PRTMP_ADAPTER pAd,
5397 IN USHORT OperationMode,
5399 IN BOOLEAN bDisableBGProtect,
5400 IN BOOLEAN bNonGFExist)
5402 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5408 #ifdef DOT11_N_SUPPORT
5409 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5414 if (pAd->BATable.numAsOriginator)
5417 // enable the RTS/CTS to avoid channel collision
5419 SetMask = ALLN_SETPROTECT;
5422 #endif // DOT11_N_SUPPORT //
5424 // Config ASIC RTS threshold register
5425 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5426 MacReg &= 0xFF0000FF;
5428 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5430 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5432 #ifdef DOT11_N_SUPPORT
5433 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5434 #endif // DOT11_N_SUPPORT //
5435 (pAd->CommonCfg.bAggregationCapable == TRUE))
5436 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5438 MacReg |= (0x1000 << 8);
5442 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5446 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5448 // Initial common protection settings
5449 RTMPZeroMemory(Protect, sizeof(Protect));
5452 ProtCfg.field.TxopAllowGF40 = 1;
5453 ProtCfg.field.TxopAllowGF20 = 1;
5454 ProtCfg.field.TxopAllowMM40 = 1;
5455 ProtCfg.field.TxopAllowMM20 = 1;
5456 ProtCfg.field.TxopAllowOfdm = 1;
5457 ProtCfg.field.TxopAllowCck = 1;
5458 ProtCfg.field.RTSThEn = 1;
5459 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5461 // update PHY mode and rate
5462 if (pAd->CommonCfg.Channel > 14)
5463 ProtCfg.field.ProtectRate = 0x4000;
5464 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5466 // Handle legacy(B/G) protection
5467 if (bDisableBGProtect)
5469 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5470 ProtCfg.field.ProtectCtrl = 0;
5471 Protect[0] = ProtCfg.word;
5472 Protect[1] = ProtCfg.word;
5476 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5477 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5478 Protect[0] = ProtCfg.word;
5479 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5480 Protect[1] = ProtCfg.word;
5483 #ifdef DOT11_N_SUPPORT
5484 // Decide HT frame protection.
5485 if ((SetMask & ALLN_SETPROTECT) != 0)
5487 switch(OperationMode)
5491 // 1.All STAs in the BSS are 20/40 MHz HT
5492 // 2. in ai 20/40MHz BSS
5493 // 3. all STAs are 20MHz in a 20MHz BSS
5494 // Pure HT. no protection.
5498 // PROT_TXOP(25:20) -- 010111
5499 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5500 // PROT_CTRL(17:16) -- 00 (None)
5501 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5502 Protect[2] = 0x01744004;
5506 // PROT_TXOP(25:20) -- 111111
5507 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5508 // PROT_CTRL(17:16) -- 00 (None)
5509 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5510 Protect[3] = 0x03f44084;
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[4] = 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[5] = 0x03f44084;
5530 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5531 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5532 Protect[4] = 0x01754004;
5533 Protect[5] = 0x03f54084;
5535 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5539 // This is "HT non-member protection mode."
5540 // If there may be non-HT STAs my BSS
5541 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5542 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5543 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5545 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5546 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5548 //Assign Protection method for 20&40 MHz packets
5549 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5550 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5551 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5552 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5553 Protect[2] = ProtCfg.word;
5554 Protect[3] = ProtCfg4.word;
5555 Protect[4] = ProtCfg.word;
5556 Protect[5] = ProtCfg4.word;
5557 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5561 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5562 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5563 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5565 //Assign Protection method for 40MHz packets
5566 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5567 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5568 Protect[2] = ProtCfg.word;
5569 Protect[3] = ProtCfg4.word;
5572 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5573 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5575 Protect[4] = ProtCfg.word;
5576 Protect[5] = ProtCfg4.word;
5578 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5582 // HT mixed mode. PROTECT ALL!
5584 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5585 ProtCfg4.word = 0x03f44084;
5586 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5587 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5589 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5590 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5592 //Assign Protection method for 20&40 MHz packets
5593 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5594 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5595 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5596 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5597 Protect[2] = ProtCfg.word;
5598 Protect[3] = ProtCfg4.word;
5599 Protect[4] = ProtCfg.word;
5600 Protect[5] = ProtCfg4.word;
5601 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5605 // Special on for Atheros problem n chip.
5606 Protect[2] = 0x01754004;
5607 Protect[3] = 0x03f54084;
5608 Protect[4] = 0x01754004;
5609 Protect[5] = 0x03f54084;
5610 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5614 #endif // DOT11_N_SUPPORT //
5616 offset = CCK_PROT_CFG;
5617 for (i = 0;i < 6;i++)
5619 if ((SetMask & (1<< i)))
5621 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5627 ==========================================================================
5630 IRQL = PASSIVE_LEVEL
5631 IRQL = DISPATCH_LEVEL
5633 ==========================================================================
5635 VOID AsicSwitchChannel(
5636 IN PRTMP_ADAPTER pAd,
5640 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5641 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5643 UINT32 Value = 0; //BbpReg, Value;
5644 RTMP_RF_REGS *RFRegTable;
5646 // Search Tx power value
5647 for (index = 0; index < pAd->ChannelListNum; index++)
5649 if (Channel == pAd->ChannelList[index].Channel)
5651 TxPwer = pAd->ChannelList[index].Power;
5652 TxPwer2 = pAd->ChannelList[index].Power2;
5657 if (index == MAX_NUM_OF_CHANNELS)
5659 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5663 // The RF programming sequence is difference between 3xxx and 2xxx
5664 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5666 /* modify by WY for Read RF Reg. error */
5669 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5671 if (Channel == FreqItems3020[index].Channel)
5673 // Programming channel parameters
5674 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5675 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5677 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5678 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5679 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5682 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5683 RFValue = (RFValue & 0xE0) | TxPwer;
5684 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5687 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5688 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5689 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5692 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5694 RFValue = pAd->Mlme.CaliBW40RfR24;
5695 //DISABLE_11N_CHECK(pAd);
5699 RFValue = pAd->Mlme.CaliBW20RfR24;
5701 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5704 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5705 RFValue = RFValue | 0x1;
5706 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5708 // latch channel for future usage.
5709 pAd->LatchRfRegs.Channel = Channel;
5715 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5720 pAd->Antenna.field.TxPath,
5721 FreqItems3020[index].N,
5722 FreqItems3020[index].K,
5723 FreqItems3020[index].R));
5728 RFRegTable = RF2850RegTable;
5730 switch (pAd->RfIcType)
5737 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5739 if (Channel == RFRegTable[index].Channel)
5741 R2 = RFRegTable[index].R2;
5742 if (pAd->Antenna.field.TxPath == 1)
5744 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5747 if (pAd->Antenna.field.RxPath == 2)
5749 R2 |= 0x40; // write 1 to off Rxpath.
5751 else if (pAd->Antenna.field.RxPath == 1)
5753 R2 |= 0x20040; // write 1 to off RxPath
5758 // initialize R3, R4
5759 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5760 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5762 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5764 if ((TxPwer >= -7) && (TxPwer < 0))
5766 TxPwer = (7+TxPwer);
5767 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5768 R3 |= (TxPwer << 10);
5769 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5773 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5774 R3 |= (TxPwer << 10) | (1 << 9);
5778 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5780 TxPwer2 = (7+TxPwer2);
5781 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5782 R4 |= (TxPwer2 << 7);
5783 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5787 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5788 R4 |= (TxPwer2 << 7) | (1 << 6);
5793 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5794 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5797 // Based on BBP current mode before changing RF channel.
5798 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5804 pAd->LatchRfRegs.Channel = Channel;
5805 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5806 pAd->LatchRfRegs.R2 = R2;
5807 pAd->LatchRfRegs.R3 = R3;
5808 pAd->LatchRfRegs.R4 = R4;
5810 // Set RF value 1's set R3[bit2] = [0]
5811 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5812 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5813 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5814 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5818 // Set RF value 2's set R3[bit2] = [1]
5819 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5820 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5821 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5822 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5826 // Set RF value 3's set R3[bit2] = [0]
5827 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5828 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5829 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5830 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5842 // Change BBP setting during siwtch from a->g, g->a
5845 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5847 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5848 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5849 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5850 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.
5851 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5853 // Rx High power VGA offset for LNA select
5854 if (pAd->NicConfig2.field.ExternalLNAForG)
5856 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5857 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5861 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5862 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5865 // 5G band selection PIN, bit1 and bit2 are complement
5866 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5869 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5871 // Turn off unused PA or LNA when only 1T or 1R
5872 if (pAd->Antenna.field.TxPath == 1)
5874 TxPinCfg &= 0xFFFFFFF3;
5876 if (pAd->Antenna.field.RxPath == 1)
5878 TxPinCfg &= 0xFFFFF3FF;
5881 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5885 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5887 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5888 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5889 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5890 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.
5891 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5893 // Rx High power VGA offset for LNA select
5894 if (pAd->NicConfig2.field.ExternalLNAForA)
5896 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5900 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5903 // 5G band selection PIN, bit1 and bit2 are complement
5904 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5907 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5909 // Turn off unused PA or LNA when only 1T or 1R
5910 if (pAd->Antenna.field.TxPath == 1)
5912 TxPinCfg &= 0xFFFFFFF3;
5914 if (pAd->Antenna.field.RxPath == 1)
5916 TxPinCfg &= 0xFFFFF3FF;
5919 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5922 // R66 should be set according to Channel and use 20MHz when scanning
5923 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5925 RTMPSetAGCInitValue(pAd, BW_20);
5927 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5930 // On 11A, We should delay and wait RF/BBP to be stable
5931 // and the appropriate time should be 1000 micro seconds
5932 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5934 RTMPusecDelay(1000);
5936 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",
5939 (R3 & 0x00003e00) >> 9,
5940 (R4 & 0x000007c0) >> 6,
5941 pAd->Antenna.field.TxPath,
5942 pAd->LatchRfRegs.R1,
5943 pAd->LatchRfRegs.R2,
5944 pAd->LatchRfRegs.R3,
5945 pAd->LatchRfRegs.R4));
5949 ==========================================================================
5951 This function is required for 2421 only, and should not be used during
5952 site survey. It's only required after NIC decided to stay at a channel
5953 for a longer period.
5954 When this function is called, it's always after AsicSwitchChannel().
5956 IRQL = PASSIVE_LEVEL
5957 IRQL = DISPATCH_LEVEL
5959 ==========================================================================
5961 VOID AsicLockChannel(
5962 IN PRTMP_ADAPTER pAd,
5968 ==========================================================================
5971 IRQL = PASSIVE_LEVEL
5972 IRQL = DISPATCH_LEVEL
5974 ==========================================================================
5976 VOID AsicAntennaSelect(
5977 IN PRTMP_ADAPTER pAd,
5983 ========================================================================
5985 Routine Description:
5986 Antenna miscellaneous setting.
5989 pAd Pointer to our adapter
5990 BandState Indicate current Band State.
5995 IRQL <= DISPATCH_LEVEL
5998 1.) Frame End type control
5999 only valid for G only (RF_2527 & RF_2529)
6000 0: means DPDT, set BBP R4 bit 5 to 1
6001 1: means SPDT, set BBP R4 bit 5 to 0
6004 ========================================================================
6006 VOID AsicAntennaSetting(
6007 IN PRTMP_ADAPTER pAd,
6008 IN ABGBAND_STATE BandState)
6012 VOID AsicRfTuningExec(
6013 IN PVOID SystemSpecific1,
6014 IN PVOID FunctionContext,
6015 IN PVOID SystemSpecific2,
6016 IN PVOID SystemSpecific3)
6021 ==========================================================================
6023 Gives CCK TX rate 2 more dB TX power.
6024 This routine works only in LINK UP in INFRASTRUCTURE mode.
6026 calculate desired Tx power in RF R3.Tx0~5, should consider -
6027 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6028 1. TxPowerPercentage
6029 2. auto calibration based on TSSI feedback
6030 3. extra 2 db for CCK
6031 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6033 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6034 it should be called AFTER MlmeDynamicTxRatSwitching()
6035 ==========================================================================
6037 VOID AsicAdjustTxPower(
6038 IN PRTMP_ADAPTER pAd)
6042 BOOLEAN bAutoTxAgc = FALSE;
6043 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6044 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6045 PCHAR pTxAgcCompensate;
6049 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6051 if (pAd->CommonCfg.CentralChannel > 14)
6053 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6054 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6055 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6056 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6057 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6061 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6062 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6063 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6064 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6065 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6070 if (pAd->CommonCfg.Channel > 14)
6072 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6073 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6074 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6075 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6076 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6080 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6081 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6082 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6083 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6084 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6088 // TX power compensation for temperature variation based on TSSI. try every 4 second
6089 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6091 if (pAd->CommonCfg.Channel <= 14)
6094 bAutoTxAgc = pAd->bAutoTxAgcG;
6095 TssiRef = pAd->TssiRefG;
6096 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6097 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6098 TxAgcStep = pAd->TxAgcStepG;
6099 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6104 bAutoTxAgc = pAd->bAutoTxAgcA;
6105 TssiRef = pAd->TssiRefA;
6106 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6107 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6108 TxAgcStep = pAd->TxAgcStepA;
6109 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6114 /* BbpR1 is unsigned char */
6115 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6117 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6118 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6119 /* step value is defined in pAd->TxAgcStepG for tx power value */
6121 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6122 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6123 above value are examined in mass factory production */
6124 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6126 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6127 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6128 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6130 if (BbpR49 > pTssiMinusBoundary[1])
6132 // Reading is larger than the reference value
6133 // check for how large we need to decrease the Tx power
6134 for (idx = 1; idx < 5; idx++)
6136 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6139 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6140 // if (R3 > (ULONG) (TxAgcStep * (idx-1)))
6141 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6143 // *pTxAgcCompensate = -((UCHAR)R3);
6145 DeltaPwr += (*pTxAgcCompensate);
6146 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6147 BbpR49, TssiRef, TxAgcStep, idx-1));
6149 else if (BbpR49 < pTssiPlusBoundary[1])
6151 // Reading is smaller than the reference value
6152 // check for how large we need to increase the Tx power
6153 for (idx = 1; idx < 5; idx++)
6155 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6158 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6159 *pTxAgcCompensate = TxAgcStep * (idx-1);
6160 DeltaPwr += (*pTxAgcCompensate);
6161 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6162 BbpR49, TssiRef, TxAgcStep, idx-1));
6166 *pTxAgcCompensate = 0;
6167 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6168 BbpR49, TssiRef, TxAgcStep, 0));
6174 if (pAd->CommonCfg.Channel <= 14)
6176 bAutoTxAgc = pAd->bAutoTxAgcG;
6177 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6181 bAutoTxAgc = pAd->bAutoTxAgcA;
6182 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6186 DeltaPwr += (*pTxAgcCompensate);
6189 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6193 // Handle regulatory max tx power constrain
6196 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6197 UCHAR AdjustMaxTxPwr[40];
6199 if (pAd->CommonCfg.Channel > 14) // 5G band
6200 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6202 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6203 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6205 // error handling, range check
6206 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6208 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6212 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6214 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6216 // Adjust max tx power according to the relationship of tx power in E2PROM
6219 // CCK will have 4dBm larger than OFDM
6220 // Therefore, we should separate to parse the tx power field
6225 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6229 // CCK will have 4dBm larger than OFDM
6230 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6234 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6236 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6243 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6245 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6246 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6251 // Adjust tx power according to the relationship
6254 if (TxPwr[i] != 0xffffffff)
6258 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6260 // The system tx power is larger than the regulatory, the power should be restrain
6261 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6263 // decrease to zero and don't need to take care BBPR1
6264 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6265 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6269 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6272 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6274 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6279 #endif // SINGLE_SKU //
6281 /* calculate delta power based on the percentage specified from UI */
6282 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6283 // We lower TX power here according to the percentage specified from UI
6284 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6286 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6288 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6292 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6296 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6300 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6305 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6310 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6312 /* reset different new tx power for different TX rate */
6315 if (TxPwr[i] != 0xffffffff)
6319 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6321 if ((Value + DeltaPwr) < 0)
6323 Value = 0; /* min */
6325 else if ((Value + DeltaPwr) > 0xF)
6327 Value = 0xF; /* max */
6331 Value += DeltaPwr; /* temperature compensation */
6334 /* fill new value to CSR offset */
6335 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6338 /* write tx power value to CSR */
6339 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6340 TX power for OFDM 6M/9M
6341 TX power for CCK5.5M/11M
6342 TX power for CCK1M/2M */
6343 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6344 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6350 #ifdef CONFIG_STA_SUPPORT
6352 ==========================================================================
6354 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6355 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6356 the wakeup timer timeout. Driver has to issue a separate command to wake
6359 IRQL = DISPATCH_LEVEL
6361 ==========================================================================
6363 VOID AsicSleepThenAutoWakeup(
6364 IN PRTMP_ADAPTER pAd,
6365 IN USHORT TbttNumToNextWakeUp)
6367 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6371 ==========================================================================
6373 AsicForceWakeup() is used whenever manual wakeup is required
6374 AsicForceSleep() should only be used when not in INFRA BSS. When
6375 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6376 ==========================================================================
6378 VOID AsicForceSleep(
6379 IN PRTMP_ADAPTER pAd)
6385 ==========================================================================
6387 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6390 IRQL = PASSIVE_LEVEL
6391 IRQL = DISPATCH_LEVEL
6392 ==========================================================================
6394 VOID AsicForceWakeup(
6395 IN PRTMP_ADAPTER pAd,
6398 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6399 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6401 #endif // CONFIG_STA_SUPPORT //
6403 ==========================================================================
6407 IRQL = DISPATCH_LEVEL
6409 ==========================================================================
6412 IN PRTMP_ADAPTER pAd,
6416 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6417 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6419 Addr4 = (ULONG)(pBssid[0]) |
6420 (ULONG)(pBssid[1] << 8) |
6421 (ULONG)(pBssid[2] << 16) |
6422 (ULONG)(pBssid[3] << 24);
6423 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6426 // always one BSSID in STA mode
6427 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6429 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6432 VOID AsicSetMcastWC(
6433 IN PRTMP_ADAPTER pAd)
6435 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6438 pEntry->Sst = SST_ASSOC;
6439 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6440 pEntry->PsMode = PWR_ACTIVE;
6441 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6442 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6446 ==========================================================================
6449 IRQL = DISPATCH_LEVEL
6451 ==========================================================================
6453 VOID AsicDelWcidTab(
6454 IN PRTMP_ADAPTER pAd,
6457 ULONG Addr0 = 0x0, Addr1 = 0x0;
6460 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6461 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6462 RTMP_IO_WRITE32(pAd, offset, Addr0);
6464 RTMP_IO_WRITE32(pAd, offset, Addr1);
6468 ==========================================================================
6471 IRQL = DISPATCH_LEVEL
6473 ==========================================================================
6476 IN PRTMP_ADAPTER pAd)
6478 TX_LINK_CFG_STRUC TxLinkCfg;
6481 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6482 TxLinkCfg.field.TxRDGEn = 1;
6483 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6485 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6488 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6490 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6494 ==========================================================================
6497 IRQL = DISPATCH_LEVEL
6499 ==========================================================================
6501 VOID AsicDisableRDG(
6502 IN PRTMP_ADAPTER pAd)
6504 TX_LINK_CFG_STRUC TxLinkCfg;
6508 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6509 TxLinkCfg.field.TxRDGEn = 0;
6510 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6512 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6517 //if ( pAd->CommonCfg.bEnableTxBurst )
6518 // Data |= 0x60; // for performance issue not set the TXOP to 0
6520 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6521 #ifdef DOT11_N_SUPPORT
6522 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6523 #endif // DOT11_N_SUPPORT //
6526 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6527 if (pAd->CommonCfg.bEnableTxBurst)
6530 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6534 ==========================================================================
6537 IRQL = PASSIVE_LEVEL
6538 IRQL = DISPATCH_LEVEL
6540 ==========================================================================
6542 VOID AsicDisableSync(
6543 IN PRTMP_ADAPTER pAd)
6545 BCN_TIME_CFG_STRUC csr;
6547 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6549 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6550 // that NIC will never wakes up because TSF stops and no more
6552 pAd->TbttTickCount = 0;
6553 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6554 csr.field.bBeaconGen = 0;
6555 csr.field.bTBTTEnable = 0;
6556 csr.field.TsfSyncMode = 0;
6557 csr.field.bTsfTicking = 0;
6558 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6563 ==========================================================================
6566 IRQL = DISPATCH_LEVEL
6568 ==========================================================================
6570 VOID AsicEnableBssSync(
6571 IN PRTMP_ADAPTER pAd)
6573 BCN_TIME_CFG_STRUC csr;
6575 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6577 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6578 // RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);
6579 #ifdef CONFIG_STA_SUPPORT
6580 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6582 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6583 csr.field.bTsfTicking = 1;
6584 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6585 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6586 csr.field.bTBTTEnable = 1;
6588 #endif // CONFIG_STA_SUPPORT //
6589 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6593 ==========================================================================
6596 BEACON frame in shared memory should be built ok before this routine
6597 can be called. Otherwise, a garbage frame maybe transmitted out every
6600 IRQL = DISPATCH_LEVEL
6602 ==========================================================================
6604 VOID AsicEnableIbssSync(
6605 IN PRTMP_ADAPTER pAd)
6607 BCN_TIME_CFG_STRUC csr9;
6611 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6613 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6614 csr9.field.bBeaconGen = 0;
6615 csr9.field.bTBTTEnable = 0;
6616 csr9.field.bTsfTicking = 0;
6617 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6621 // move BEACON TXD and frame content to on-chip memory
6622 ptr = (PUCHAR)&pAd->BeaconTxWI;
6623 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6625 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6626 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6627 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6631 // start right after the 16-byte TXWI field
6632 ptr = pAd->BeaconBuf;
6633 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6635 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6636 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6637 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6643 // For Wi-Fi faily generated beacons between participating stations.
6644 // Set TBTT phase adaptive adjustment step to 8us (default 16us)
6645 // don't change settings 2006-5- by Jerry
6646 //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);
6648 // start sending BEACON
6649 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6650 csr9.field.bTsfTicking = 1;
6651 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6652 csr9.field.bTBTTEnable = 1;
6653 csr9.field.bBeaconGen = 1;
6654 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6658 ==========================================================================
6661 IRQL = PASSIVE_LEVEL
6662 IRQL = DISPATCH_LEVEL
6664 ==========================================================================
6666 VOID AsicSetEdcaParm(
6667 IN PRTMP_ADAPTER pAd,
6668 IN PEDCA_PARM pEdcaParm)
6670 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6671 AC_TXOP_CSR0_STRUC csr0;
6672 AC_TXOP_CSR1_STRUC csr1;
6673 AIFSN_CSR_STRUC AifsnCsr;
6674 CWMIN_CSR_STRUC CwminCsr;
6675 CWMAX_CSR_STRUC CwmaxCsr;
6682 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6684 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6685 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6686 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6688 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6689 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6692 //========================================================
6693 // MAC Register has a copy .
6694 //========================================================
6696 if( pAd->CommonCfg.bEnableTxBurst )
6698 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6699 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6702 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6704 // Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6706 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6707 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6708 Ac0Cfg.field.Aifsn = 2;
6709 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6711 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6712 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6713 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6714 Ac1Cfg.field.Aifsn = 2;
6715 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6717 if (pAd->CommonCfg.PhyMode == PHY_11B)
6719 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6720 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6724 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6725 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6727 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6728 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6729 Ac2Cfg.field.Aifsn = 2;
6730 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6731 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6732 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6733 Ac3Cfg.field.Aifsn = 2;
6734 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6736 //========================================================
6737 // DMA Register has a copy too.
6738 //========================================================
6739 csr0.field.Ac0Txop = 0; // QID_AC_BE
6740 csr0.field.Ac1Txop = 0; // QID_AC_BK
6741 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6742 if (pAd->CommonCfg.PhyMode == PHY_11B)
6744 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6745 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6749 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6750 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6752 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6755 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6756 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6757 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6758 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6759 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6762 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6763 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6764 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6765 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6766 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6768 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6770 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6774 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6775 //========================================================
6776 // MAC Register has a copy.
6777 //========================================================
6779 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6780 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6782 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6784 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6785 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6786 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6787 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6789 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6790 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6791 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6792 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6794 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6795 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6796 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6797 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6798 #ifdef CONFIG_STA_SUPPORT
6799 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6801 // Tuning for Wi-Fi WMM S06
6802 if (pAd->CommonCfg.bWiFiTest &&
6803 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6804 Ac2Cfg.field.Aifsn -= 1;
6806 // Tuning for TGn Wi-Fi 5.2.32
6807 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6808 if (STA_TGN_WIFI_ON(pAd) &&
6809 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6811 Ac0Cfg.field.Aifsn = 3;
6812 Ac2Cfg.field.AcTxop = 5;
6815 #endif // CONFIG_STA_SUPPORT //
6817 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6818 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6819 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6820 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6823 if (pAd->CommonCfg.bWiFiTest)
6825 if (Ac3Cfg.field.AcTxop == 102)
6827 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6828 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6829 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6830 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6831 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6834 //#endif // WIFI_TEST //
6836 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6837 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6838 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6839 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6842 //========================================================
6843 // DMA Register has a copy too.
6844 //========================================================
6845 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6846 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6847 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6849 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6850 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6851 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6854 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6855 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6856 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6857 #ifdef CONFIG_STA_SUPPORT
6858 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6859 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6860 #endif // CONFIG_STA_SUPPORT //
6861 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6864 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6865 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6866 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6867 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6868 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6871 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6872 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6873 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6874 #ifdef CONFIG_STA_SUPPORT
6875 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6877 // Tuning for Wi-Fi WMM S06
6878 if (pAd->CommonCfg.bWiFiTest &&
6879 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6880 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6882 // Tuning for TGn Wi-Fi 5.2.32
6883 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6884 if (STA_TGN_WIFI_ON(pAd) &&
6885 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6887 AifsnCsr.field.Aifsn0 = 3;
6888 AifsnCsr.field.Aifsn2 = 7;
6892 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
6894 #endif // CONFIG_STA_SUPPORT //
6896 #ifdef CONFIG_STA_SUPPORT
6897 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6898 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6899 #endif // CONFIG_STA_SUPPORT //
6900 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6902 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6905 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6906 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6907 pEdcaParm->Aifsn[0],
6908 pEdcaParm->Cwmin[0],
6909 pEdcaParm->Cwmax[0],
6910 pEdcaParm->Txop[0]<<5,
6911 pEdcaParm->bACM[0]));
6912 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6913 pEdcaParm->Aifsn[1],
6914 pEdcaParm->Cwmin[1],
6915 pEdcaParm->Cwmax[1],
6916 pEdcaParm->Txop[1]<<5,
6917 pEdcaParm->bACM[1]));
6918 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6919 pEdcaParm->Aifsn[2],
6920 pEdcaParm->Cwmin[2],
6921 pEdcaParm->Cwmax[2],
6922 pEdcaParm->Txop[2]<<5,
6923 pEdcaParm->bACM[2]));
6924 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6925 pEdcaParm->Aifsn[3],
6926 pEdcaParm->Cwmin[3],
6927 pEdcaParm->Cwmax[3],
6928 pEdcaParm->Txop[3]<<5,
6929 pEdcaParm->bACM[3]));
6935 ==========================================================================
6938 IRQL = PASSIVE_LEVEL
6939 IRQL = DISPATCH_LEVEL
6941 ==========================================================================
6943 VOID AsicSetSlotTime(
6944 IN PRTMP_ADAPTER pAd,
6945 IN BOOLEAN bUseShortSlotTime)
6948 UINT32 RegValue = 0;
6950 #ifdef CONFIG_STA_SUPPORT
6951 if (pAd->CommonCfg.Channel > 14)
6952 bUseShortSlotTime = TRUE;
6953 #endif // CONFIG_STA_SUPPORT //
6955 if (bUseShortSlotTime)
6956 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6958 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6960 SlotTime = (bUseShortSlotTime)? 9 : 20;
6962 #ifdef CONFIG_STA_SUPPORT
6963 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6965 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6966 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6967 #ifdef DOT11_N_SUPPORT
6968 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6969 #endif // DOT11_N_SUPPORT //
6972 // In this case, we will think it is doing Wi-Fi test
6973 // And we will not set to short slot when bEnableTxBurst is TRUE.
6975 else if (pAd->CommonCfg.bEnableTxBurst)
6978 #endif // CONFIG_STA_SUPPORT //
6981 // For some reasons, always set it to short slot time.
6983 // ToDo: Should consider capability with 11B
6985 #ifdef CONFIG_STA_SUPPORT
6986 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6988 if (pAd->StaCfg.BssType == BSS_ADHOC)
6991 #endif // CONFIG_STA_SUPPORT //
6993 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6994 RegValue = RegValue & 0xFFFFFF00;
6996 RegValue |= SlotTime;
6998 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7002 ========================================================================
7004 Add Shared key information into ASIC.
7005 Update shared key, TxMic and RxMic to Asic Shared key table
7006 Update its cipherAlg to Asic Shared key Mode.
7009 ========================================================================
7011 VOID AsicAddSharedKeyEntry(
7012 IN PRTMP_ADAPTER pAd,
7020 ULONG offset; //, csr0;
7021 SHAREDKEY_MODE_STRUC csr1;
7023 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7024 //============================================================================================
7026 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7027 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7028 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]));
7031 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7032 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7036 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7037 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7039 //============================================================================================
7041 // fill key material - key + TX MIC + RX MIC
7046 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7047 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7049 offset += MAX_LEN_OF_SHARE_KEY;
7052 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7058 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7064 // Update cipher algorithm. WSTA always use BSS0
7066 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7067 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7068 if ((BssIndex%2) == 0)
7071 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7072 else if (KeyIdx == 1)
7073 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7074 else if (KeyIdx == 2)
7075 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7077 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7082 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7083 else if (KeyIdx == 1)
7084 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7085 else if (KeyIdx == 2)
7086 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7088 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7090 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7091 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7095 // IRQL = DISPATCH_LEVEL
7096 VOID AsicRemoveSharedKeyEntry(
7097 IN PRTMP_ADAPTER pAd,
7102 SHAREDKEY_MODE_STRUC csr1;
7104 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7106 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7107 if ((BssIndex%2) == 0)
7110 csr1.field.Bss0Key0CipherAlg = 0;
7111 else if (KeyIdx == 1)
7112 csr1.field.Bss0Key1CipherAlg = 0;
7113 else if (KeyIdx == 2)
7114 csr1.field.Bss0Key2CipherAlg = 0;
7116 csr1.field.Bss0Key3CipherAlg = 0;
7121 csr1.field.Bss1Key0CipherAlg = 0;
7122 else if (KeyIdx == 1)
7123 csr1.field.Bss1Key1CipherAlg = 0;
7124 else if (KeyIdx == 2)
7125 csr1.field.Bss1Key2CipherAlg = 0;
7127 csr1.field.Bss1Key3CipherAlg = 0;
7129 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7130 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7131 ASSERT(BssIndex < 4);
7137 VOID AsicUpdateWCIDAttribute(
7138 IN PRTMP_ADAPTER pAd,
7142 IN BOOLEAN bUsePairewiseKeyTable)
7144 ULONG WCIDAttri = 0, offset;
7147 // Update WCID attribute.
7148 // Only TxKey could update WCID attribute.
7150 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7151 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7152 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7155 VOID AsicUpdateWCIDIVEIV(
7156 IN PRTMP_ADAPTER pAd,
7163 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7165 RTMP_IO_WRITE32(pAd, offset, uIV);
7166 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7169 VOID AsicUpdateRxWCIDTable(
7170 IN PRTMP_ADAPTER pAd,
7177 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7178 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7179 RTMP_IO_WRITE32(pAd, offset, Addr);
7180 Addr = pAddr[4] + (pAddr[5] << 8);
7181 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7186 ========================================================================
7188 Routine Description:
7189 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7192 pAd Pointer to our adapter
7193 WCID WCID Entry number.
7194 BssIndex BSSID index, station or none multiple BSSID support
7195 this value should be 0.
7196 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7197 pCipherKey Pointer to Cipher Key.
7198 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7199 otherwise PairewiseKey table
7200 bTxKey This is the transmit key if enabled.
7206 This routine will set the relative key stuff to Asic including WCID attribute,
7207 Cipher Key, Cipher algorithm and IV/EIV.
7209 IV/EIV will be update if this CipherKey is the transmission key because
7210 ASIC will base on IV's KeyID value to select Cipher Key.
7212 If bTxKey sets to FALSE, this is not the TX key, but it could be
7215 For AP mode bTxKey must be always set to TRUE.
7216 ========================================================================
7218 VOID AsicAddKeyEntry(
7219 IN PRTMP_ADAPTER pAd,
7223 IN PCIPHER_KEY pCipherKey,
7224 IN BOOLEAN bUsePairewiseKeyTable,
7228 // ULONG WCIDAttri = 0;
7230 PUCHAR pKey = pCipherKey->Key;
7231 // ULONG KeyLen = pCipherKey->KeyLen;
7232 PUCHAR pTxMic = pCipherKey->TxMic;
7233 PUCHAR pRxMic = pCipherKey->RxMic;
7234 PUCHAR pTxtsc = pCipherKey->TxTsc;
7235 UCHAR CipherAlg = pCipherKey->CipherAlg;
7236 SHAREDKEY_MODE_STRUC csr1;
7238 // ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY);
7240 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7242 // 1.) decide key table offset
7244 if (bUsePairewiseKeyTable)
7245 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7247 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7250 // 2.) Set Key to Asic
7252 //for (i = 0; i < KeyLen; i++)
7255 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7256 offset += MAX_LEN_OF_PEER_KEY;
7259 // 3.) Set MIC key if available
7263 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7265 offset += LEN_TKIP_TXMICK;
7269 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7274 // 4.) Modify IV/EIV if needs
7275 // This will force Asic to use this key ID by setting IV.
7286 IV4 = (KeyIdx << 6);
7287 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7288 IV4 |= 0x20; // turn on extension bit means EIV existence
7290 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7291 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7297 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7299 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7302 if (!bUsePairewiseKeyTable)
7305 // Only update the shared key security mode
7307 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7308 if ((BssIndex % 2) == 0)
7311 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7312 else if (KeyIdx == 1)
7313 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7314 else if (KeyIdx == 2)
7315 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7317 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7322 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7323 else if (KeyIdx == 1)
7324 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7325 else if (KeyIdx == 2)
7326 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7328 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7330 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7333 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7338 ========================================================================
7340 Add Pair-wise key material into ASIC.
7341 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7344 ========================================================================
7346 VOID AsicAddPairwiseKeyEntry(
7347 IN PRTMP_ADAPTER pAd,
7350 IN CIPHER_KEY *pCipherKey)
7354 PUCHAR pKey = pCipherKey->Key;
7355 PUCHAR pTxMic = pCipherKey->TxMic;
7356 PUCHAR pRxMic = pCipherKey->RxMic;
7358 UCHAR CipherAlg = pCipherKey->CipherAlg;
7362 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7364 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7366 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7369 RTMP_IO_READ32(pAd, offset + i, &Value);
7372 offset += MAX_LEN_OF_PEER_KEY;
7378 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7385 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7389 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7390 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7391 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]));
7394 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7395 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7399 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7400 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7404 ========================================================================
7406 Remove Pair-wise key material from ASIC.
7409 ========================================================================
7411 VOID AsicRemovePairwiseKeyEntry(
7412 IN PRTMP_ADAPTER pAd,
7419 // re-set the entry's WCID attribute as OPEN-NONE.
7420 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7421 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7422 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7425 BOOLEAN AsicSendCommandToMcu(
7426 IN PRTMP_ADAPTER pAd,
7432 HOST_CMD_CSR_STRUC H2MCmd;
7433 H2M_MAILBOX_STRUC H2MMailbox;
7437 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7438 if (H2MMailbox.field.Owner == 0)
7447 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7453 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7454 H2MMailbox.field.CmdToken = Token;
7455 H2MMailbox.field.HighByte = Arg1;
7456 H2MMailbox.field.LowByte = Arg0;
7457 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7460 H2MCmd.field.HostCommand = Command;
7461 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7463 if (Command != 0x80)
7472 ========================================================================
7474 Routine Description:
7475 Verify the support rate for different PHY type
7478 pAd Pointer to our adapter
7483 IRQL = PASSIVE_LEVEL
7485 ========================================================================
7487 VOID RTMPCheckRates(
7488 IN PRTMP_ADAPTER pAd,
7489 IN OUT UCHAR SupRate[],
7490 IN OUT UCHAR *SupRateLen)
7492 UCHAR RateIdx, i, j;
7493 UCHAR NewRate[12], NewRateLen;
7497 if (pAd->CommonCfg.PhyMode == PHY_11B)
7502 // Check for support rates exclude basic rate bit
7503 for (i = 0; i < *SupRateLen; i++)
7504 for (j = 0; j < RateIdx; j++)
7505 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7506 NewRate[NewRateLen++] = SupRate[i];
7508 *SupRateLen = NewRateLen;
7509 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7512 #ifdef CONFIG_STA_SUPPORT
7513 #ifdef DOT11_N_SUPPORT
7514 BOOLEAN RTMPCheckChannel(
7515 IN PRTMP_ADAPTER pAd,
7516 IN UCHAR CentralChannel,
7520 UCHAR UpperChannel = 0, LowerChannel = 0;
7521 UCHAR NoEffectChannelinList = 0;
7523 // Find upper and lower channel according to 40MHz current operation.
7524 if (CentralChannel < Channel)
7526 UpperChannel = Channel;
7527 if (CentralChannel > 2)
7528 LowerChannel = CentralChannel - 2;
7532 else if (CentralChannel > Channel)
7534 UpperChannel = CentralChannel + 2;
7535 LowerChannel = Channel;
7538 for (k = 0;k < pAd->ChannelListNum;k++)
7540 if (pAd->ChannelList[k].Channel == UpperChannel)
7542 NoEffectChannelinList ++;
7544 if (pAd->ChannelList[k].Channel == LowerChannel)
7546 NoEffectChannelinList ++;
7550 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7551 if (NoEffectChannelinList == 2)
7558 ========================================================================
7560 Routine Description:
7561 Verify the support rate for HT phy type
7564 pAd Pointer to our adapter
7567 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7569 IRQL = PASSIVE_LEVEL
7571 ========================================================================
7573 BOOLEAN RTMPCheckHt(
7574 IN PRTMP_ADAPTER pAd,
7576 IN HT_CAPABILITY_IE *pHtCapability,
7577 IN ADD_HT_INFO_IE *pAddHtInfo)
7579 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7582 // If use AMSDU, set flag.
7583 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7584 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7585 // Save Peer Capability
7586 if (pHtCapability->HtCapInfo.ShortGIfor20)
7587 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7588 if (pHtCapability->HtCapInfo.ShortGIfor40)
7589 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7590 if (pHtCapability->HtCapInfo.TxSTBC)
7591 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7592 if (pHtCapability->HtCapInfo.RxSTBC)
7593 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7594 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7596 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7599 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7601 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7604 // Will check ChannelWidth for MCSSet[4] below
7605 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7606 switch (pAd->CommonCfg.RxStream)
7609 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7610 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7611 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7612 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7615 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7616 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7617 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7618 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7621 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7622 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7623 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7624 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7628 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7630 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7631 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7632 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7634 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7636 // Send Assoc Req with my HT capability.
7637 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7638 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7639 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7640 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7641 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7642 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7643 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7644 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7645 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7646 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7647 if (pAd->CommonCfg.bRdg)
7649 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7650 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7653 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7654 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7656 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7659 #endif // DOT11_N_SUPPORT //
7660 #endif // CONFIG_STA_SUPPORT //
7663 ========================================================================
7665 Routine Description:
7666 Verify the support rate for different PHY type
7669 pAd Pointer to our adapter
7674 IRQL = PASSIVE_LEVEL
7676 ========================================================================
7678 VOID RTMPUpdateMlmeRate(
7679 IN PRTMP_ADAPTER pAd)
7682 UCHAR ProperMlmeRate; //= RATE_54;
7683 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7684 BOOLEAN bMatch = FALSE;
7686 switch (pAd->CommonCfg.PhyMode)
7689 ProperMlmeRate = RATE_11;
7690 MinimumRate = RATE_1;
7692 case PHY_11BG_MIXED:
7693 #ifdef DOT11_N_SUPPORT
7694 case PHY_11ABGN_MIXED:
7695 case PHY_11BGN_MIXED:
7696 #endif // DOT11_N_SUPPORT //
7697 if ((pAd->MlmeAux.SupRateLen == 4) &&
7698 (pAd->MlmeAux.ExtRateLen == 0))
7700 ProperMlmeRate = RATE_11;
7702 ProperMlmeRate = RATE_24;
7704 if (pAd->MlmeAux.Channel <= 14)
7705 MinimumRate = RATE_1;
7707 MinimumRate = RATE_6;
7710 #ifdef DOT11_N_SUPPORT
7711 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7712 case PHY_11GN_MIXED:
7713 case PHY_11AGN_MIXED:
7714 case PHY_11AN_MIXED:
7716 #endif // DOT11_N_SUPPORT //
7717 ProperMlmeRate = RATE_24;
7718 MinimumRate = RATE_6;
7720 case PHY_11ABG_MIXED:
7721 ProperMlmeRate = RATE_24;
7722 if (pAd->MlmeAux.Channel <= 14)
7723 MinimumRate = RATE_1;
7725 MinimumRate = RATE_6;
7728 ProperMlmeRate = RATE_1;
7729 MinimumRate = RATE_1;
7733 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7735 for (j = 0; j < RateIdx; j++)
7737 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7739 if (j == ProperMlmeRate)
7751 if (bMatch == FALSE)
7753 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7755 for (j = 0; j < RateIdx; j++)
7757 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7759 if (j == ProperMlmeRate)
7772 if (bMatch == FALSE)
7774 ProperMlmeRate = MinimumRate;
7777 pAd->CommonCfg.MlmeRate = MinimumRate;
7778 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7779 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7781 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7782 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7783 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7784 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7788 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7789 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7790 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7791 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7794 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7798 IN PRTMP_ADAPTER pAd,
7805 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7810 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7812 larger = max(Rssi0, Rssi1);
7815 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7817 larger = max(larger, Rssi2);
7827 ========================================================================
7828 Routine Description:
7829 Periodic evaluate antenna link status
7832 pAd - Adapter pointer
7837 ========================================================================
7839 VOID AsicEvaluateRxAnt(
7840 IN PRTMP_ADAPTER pAd)
7844 #ifdef CONFIG_STA_SUPPORT
7845 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7847 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7848 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7849 fRTMP_ADAPTER_RADIO_OFF |
7850 fRTMP_ADAPTER_NIC_NOT_EXIST |
7851 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7854 if (pAd->StaCfg.Psm == PWR_SAVE)
7857 #endif // CONFIG_STA_SUPPORT //
7859 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7861 if(pAd->Antenna.field.RxPath == 3)
7865 else if(pAd->Antenna.field.RxPath == 2)
7869 else if(pAd->Antenna.field.RxPath == 1)
7873 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7874 #ifdef CONFIG_STA_SUPPORT
7875 #endif // CONFIG_STA_SUPPORT //
7876 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7879 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7880 pAd->RalinkCounters.OneSecTxRetryOkCount +
7881 pAd->RalinkCounters.OneSecTxFailCount;
7883 if (TxTotalCnt > 50)
7885 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7886 pAd->Mlme.bLowThroughput = FALSE;
7890 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7891 pAd->Mlme.bLowThroughput = TRUE;
7897 ========================================================================
7898 Routine Description:
7899 After evaluation, check antenna link status
7902 pAd - Adapter pointer
7907 ========================================================================
7909 VOID AsicRxAntEvalTimeout(
7910 IN PVOID SystemSpecific1,
7911 IN PVOID FunctionContext,
7912 IN PVOID SystemSpecific2,
7913 IN PVOID SystemSpecific3)
7915 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7916 #ifdef CONFIG_STA_SUPPORT
7918 CHAR larger = -127, rssi0, rssi1, rssi2;
7919 #endif // CONFIG_STA_SUPPORT //
7921 #ifdef CONFIG_STA_SUPPORT
7922 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7924 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7925 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7926 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7927 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7930 if (pAd->StaCfg.Psm == PWR_SAVE)
7934 // if the traffic is low, use average rssi as the criteria
7935 if (pAd->Mlme.bLowThroughput == TRUE)
7937 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7938 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7939 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7943 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7944 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7945 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7948 if(pAd->Antenna.field.RxPath == 3)
7950 larger = max(rssi0, rssi1);
7952 if (larger > (rssi2 + 20))
7953 pAd->Mlme.RealRxPath = 2;
7955 pAd->Mlme.RealRxPath = 3;
7957 else if(pAd->Antenna.field.RxPath == 2)
7959 if (rssi0 > (rssi1 + 20))
7960 pAd->Mlme.RealRxPath = 1;
7962 pAd->Mlme.RealRxPath = 2;
7965 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7967 if(pAd->Mlme.RealRxPath == 3)
7971 else if(pAd->Mlme.RealRxPath == 2)
7975 else if(pAd->Mlme.RealRxPath == 1)
7979 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7982 #endif // CONFIG_STA_SUPPORT //
7988 VOID APSDPeriodicExec(
7989 IN PVOID SystemSpecific1,
7990 IN PVOID FunctionContext,
7991 IN PVOID SystemSpecific2,
7992 IN PVOID SystemSpecific3)
7994 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7996 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7999 pAd->CommonCfg.TriggerTimerCount++;
8001 // Driver should not send trigger frame, it should be send by application layer
8003 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
8004 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
8005 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
8007 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
8008 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
8009 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
8010 pAd->CommonCfg.TriggerTimerCount = 0;
8011 pAd->CommonCfg.bInServicePeriod = TRUE;
8016 ========================================================================
8017 Routine Description:
8018 Set/reset MAC registers according to bPiggyBack parameter
8021 pAd - Adapter pointer
8022 bPiggyBack - Enable / Disable Piggy-Back
8027 ========================================================================
8029 VOID RTMPSetPiggyBack(
8030 IN PRTMP_ADAPTER pAd,
8031 IN BOOLEAN bPiggyBack)
8033 TX_LINK_CFG_STRUC TxLinkCfg;
8035 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8037 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8038 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8042 ========================================================================
8043 Routine Description:
8044 check if this entry need to switch rate automatically
8054 ========================================================================
8056 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8057 IN PRTMP_ADAPTER pAd,
8058 IN PMAC_TABLE_ENTRY pEntry)
8060 BOOLEAN result = TRUE;
8063 #ifdef CONFIG_STA_SUPPORT
8064 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8066 // only associated STA counts
8067 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8069 result = pAd->StaCfg.bAutoTxRateSwitch;
8074 #endif // CONFIG_STA_SUPPORT //
8082 BOOLEAN RTMPAutoRateSwitchCheck(
8083 IN PRTMP_ADAPTER pAd)
8086 #ifdef CONFIG_STA_SUPPORT
8087 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8089 if (pAd->StaCfg.bAutoTxRateSwitch)
8092 #endif // CONFIG_STA_SUPPORT //
8098 ========================================================================
8099 Routine Description:
8100 check if this entry need to fix tx legacy rate
8110 ========================================================================
8112 UCHAR RTMPStaFixedTxMode(
8113 IN PRTMP_ADAPTER pAd,
8114 IN PMAC_TABLE_ENTRY pEntry)
8116 UCHAR tx_mode = FIXED_TXMODE_HT;
8119 #ifdef CONFIG_STA_SUPPORT
8120 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8122 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8124 #endif // CONFIG_STA_SUPPORT //
8130 ========================================================================
8131 Routine Description:
8132 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8142 ========================================================================
8144 VOID RTMPUpdateLegacyTxSetting(
8145 UCHAR fixed_tx_mode,
8146 PMAC_TABLE_ENTRY pEntry)
8148 HTTRANSMIT_SETTING TransmitSetting;
8150 if (fixed_tx_mode == FIXED_TXMODE_HT)
8153 TransmitSetting.word = 0;
8155 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8156 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8158 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8160 TransmitSetting.field.MODE = MODE_CCK;
8161 // CCK mode allow MCS 0~3
8162 if (TransmitSetting.field.MCS > MCS_3)
8163 TransmitSetting.field.MCS = MCS_3;
8167 TransmitSetting.field.MODE = MODE_OFDM;
8168 // OFDM mode allow MCS 0~7
8169 if (TransmitSetting.field.MCS > MCS_7)
8170 TransmitSetting.field.MCS = MCS_7;
8173 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8175 pEntry->HTPhyMode.word = TransmitSetting.word;
8176 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8177 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8181 #ifdef CONFIG_STA_SUPPORT
8183 ==========================================================================
8185 dynamic tune BBP R66 to find a balance between sensibility and
8188 IRQL = DISPATCH_LEVEL
8190 ==========================================================================
8192 VOID AsicStaBbpTuning(
8193 IN PRTMP_ADAPTER pAd)
8195 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8198 // 2860C did not support Fase CCA, therefore can't tune
8199 if (pAd->MACVersion == 0x28600100)
8205 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8208 if ((pAd->OpMode == OPMODE_STA)
8209 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8211 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8214 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8217 if (pAd->Antenna.field.RxPath > 1)
8218 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8220 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8222 if (pAd->LatchRfRegs.Channel <= 14)
8225 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8226 // Otherwise, it will have some throughput side effect when low RSSI
8229 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8231 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8232 if (OrigR66Value != R66)
8234 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8239 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8240 if (OrigR66Value != R66)
8242 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8249 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8251 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8252 if (OrigR66Value != R66)
8254 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8259 R66 = 0x2E + GET_LNA_GAIN(pAd);
8260 if (OrigR66Value != R66)
8262 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8269 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8271 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8273 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8274 if (OrigR66Value != R66)
8276 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8281 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8282 if (OrigR66Value != R66)
8284 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8290 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8292 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8293 if (OrigR66Value != R66)
8295 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8300 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8301 if (OrigR66Value != R66)
8303 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8312 #endif // CONFIG_STA_SUPPORT //
8314 VOID RTMPSetAGCInitValue(
8315 IN PRTMP_ADAPTER pAd,
8320 if (pAd->LatchRfRegs.Channel <= 14)
8322 R66 = 0x2E + GET_LNA_GAIN(pAd);
8323 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8327 if (BandWidth == BW_20)
8329 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8330 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8332 #ifdef DOT11_N_SUPPORT
8335 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8336 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8338 #endif // DOT11_N_SUPPORT //
8343 VOID AsicTurnOffRFClk(
8344 IN PRTMP_ADAPTER pAd,
8349 UINT32 R1 = 0, R2 = 0, R3 = 0;
8351 RTMP_RF_REGS *RFRegTable;
8353 RFRegTable = RF2850RegTable;
8355 switch (pAd->RfIcType)
8362 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8364 if (Channel == RFRegTable[index].Channel)
8366 R1 = RFRegTable[index].R1 & 0xffffdfff;
8367 R2 = RFRegTable[index].R2 & 0xfffbffff;
8368 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8370 RTMP_RF_IO_WRITE32(pAd, R1);
8371 RTMP_RF_IO_WRITE32(pAd, R2);
8373 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8374 // Set RF R2 bit18=0, R3 bit[18:19]=0
8375 //if (pAd->StaCfg.bRadio == FALSE)
8378 RTMP_RF_IO_WRITE32(pAd, R3);
8380 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8381 Channel, pAd->RfIcType, R2, R3));
8384 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8385 Channel, pAd->RfIcType, R2));
8397 VOID AsicTurnOnRFClk(
8398 IN PRTMP_ADAPTER pAd,
8403 UINT32 R1 = 0, R2 = 0, R3 = 0;
8405 RTMP_RF_REGS *RFRegTable;
8407 RFRegTable = RF2850RegTable;
8409 switch (pAd->RfIcType)
8416 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8418 if (Channel == RFRegTable[index].Channel)
8420 R3 = pAd->LatchRfRegs.R3;
8423 RTMP_RF_IO_WRITE32(pAd, R3);
8425 R1 = RFRegTable[index].R1;
8426 RTMP_RF_IO_WRITE32(pAd, R1);
8428 R2 = RFRegTable[index].R2;
8429 if (pAd->Antenna.field.TxPath == 1)
8431 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8434 if (pAd->Antenna.field.RxPath == 2)
8436 R2 |= 0x40; // write 1 to off Rxpath.
8438 else if (pAd->Antenna.field.RxPath == 1)
8440 R2 |= 0x20040; // write 1 to off RxPath
8442 RTMP_RF_IO_WRITE32(pAd, R2);
8453 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",