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;
349 #endif // DOT11_N_SUPPORT //
350 UCHAR ErpIe = IE_ERP;
351 UCHAR DsIe = IE_DS_PARM;
352 UCHAR TimIe = IE_TIM;
353 UCHAR WpaIe = IE_WPA;
354 UCHAR Wpa2Ie = IE_WPA2;
355 UCHAR IbssIe = IE_IBSS_PARM;
356 UCHAR Ccx2Ie = IE_CCX_V2;
357 UCHAR WapiIe = IE_WAPI;
359 extern UCHAR WPA_OUI[];
361 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
363 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
364 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
366 // Reset the RFIC setting to new series
367 RTMP_RF_REGS RF2850RegTable[] = {
368 // ch R1 R2 R3(TX0~4=0) R4
369 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
370 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
371 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
372 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
373 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
374 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
375 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
376 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
377 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
378 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
379 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
380 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
381 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
382 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
384 // 802.11 UNI / HyperLan 2
385 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
386 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
387 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
388 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
389 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
390 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
391 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
392 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
393 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
394 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
395 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
396 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
399 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
401 // 2008.04.30 modified
402 // The system team has AN to improve the EVM value
403 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
404 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
405 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
406 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
408 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
409 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
410 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
411 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
412 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
413 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
414 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
415 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
416 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
417 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
418 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
419 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
422 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
423 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
424 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
425 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
426 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
427 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
428 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
431 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
432 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
433 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
434 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
435 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
436 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
437 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
439 // still lack of MMAC(Japan) ch 34,38,42,46
441 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
443 FREQUENCY_ITEM FreqItems3020[] =
445 /**************************************************/
446 // ISM : 2.4 to 2.483 GHz //
447 /**************************************************/
449 /**************************************************/
450 //-CH---N-------R---K-----------
466 //2008/07/10:KH Modified to share this variable
467 UCHAR NUM_OF_3020_CHNL=(sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM));
470 ==========================================================================
472 initialize the MLME task and its data structure (queue, spinlock,
473 timer, state machines).
478 always return NDIS_STATUS_SUCCESS
480 ==========================================================================
482 NDIS_STATUS MlmeInit(
483 IN PRTMP_ADAPTER pAd)
485 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
487 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
491 Status = MlmeQueueInit(&pAd->Mlme.Queue);
492 if(Status != NDIS_STATUS_SUCCESS)
495 pAd->Mlme.bRunning = FALSE;
496 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
498 #ifdef CONFIG_STA_SUPPORT
499 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
501 BssTableInit(&pAd->ScanTab);
503 // init STA state machines
504 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
505 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
506 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
507 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
508 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
509 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
511 // Since we are using switch/case to implement it, the init is different from the above
512 // state machine init
513 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
515 #endif // CONFIG_STA_SUPPORT //
519 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
521 // Init mlme periodic timer
522 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
524 // Set mlme periodic timer
525 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
527 // software-based RX Antenna diversity
528 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
531 #ifdef CONFIG_STA_SUPPORT
532 #endif // CONFIG_STA_SUPPORT //
536 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
542 ==========================================================================
544 main loop of the MLME
546 Mlme has to be initialized, and there are something inside the queue
548 This function is invoked from MPSetInformation and MPReceive;
549 This task guarantee only one MlmeHandler will run.
551 IRQL = DISPATCH_LEVEL
553 ==========================================================================
556 IN PRTMP_ADAPTER pAd)
558 MLME_QUEUE_ELEM *Elem = NULL;
560 // Only accept MLME and Frame from peer side, no other (control/data) frame should
561 // get into this state machine
563 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
564 if(pAd->Mlme.bRunning)
566 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
571 pAd->Mlme.bRunning = TRUE;
573 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
575 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
577 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
578 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
579 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
581 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
585 //From message type, determine which state machine I should drive
586 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
589 if (Elem->MsgType == MT2_RESET_CONF)
591 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
592 MlmeRestartStateMachine(pAd);
593 Elem->Occupied = FALSE;
599 // if dequeue success
600 switch (Elem->Machine)
602 // STA state machines
603 #ifdef CONFIG_STA_SUPPORT
604 case ASSOC_STATE_MACHINE:
605 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
607 case AUTH_STATE_MACHINE:
608 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
610 case AUTH_RSP_STATE_MACHINE:
611 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
613 case SYNC_STATE_MACHINE:
614 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
616 case MLME_CNTL_STATE_MACHINE:
617 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
619 case WPA_PSK_STATE_MACHINE:
620 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
622 case AIRONET_STATE_MACHINE:
623 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
625 #endif // CONFIG_STA_SUPPORT //
627 case ACTION_STATE_MACHINE:
628 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
635 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
640 Elem->Occupied = FALSE;
645 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
649 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
650 pAd->Mlme.bRunning = FALSE;
651 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
655 ==========================================================================
657 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
659 Adapter - NIC Adapter pointer
661 The MLME task will no longer work properly
665 ==========================================================================
668 IN PRTMP_ADAPTER pAd)
672 UINT32 TxPinCfg = 0x00050F0F;
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);
721 if (IS_RT3070(pAd) || IS_RT3071(pAd))
723 TxPinCfg &= 0xFFFFF0F0;
724 RTUSBWriteMACRegister(pAd, TX_PIN_CFG, TxPinCfg);
729 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
731 MlmeQueueDestroy(&pAd->Mlme.Queue);
732 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
734 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
737 VOID MlmeResetRalinkCounters(
738 IN PRTMP_ADAPTER pAd)
740 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
741 // clear all OneSecxxx counters.
742 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
743 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
744 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
745 pAd->RalinkCounters.OneSecRxOkCnt = 0;
746 pAd->RalinkCounters.OneSecTxFailCount = 0;
747 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
748 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
749 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
751 // TODO: for debug only. to be removed
752 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
753 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
754 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
755 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
756 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
757 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
758 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
759 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
760 pAd->RalinkCounters.OneSecTxDoneCount = 0;
761 pAd->RalinkCounters.OneSecRxCount = 0;
762 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
763 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
768 unsigned long rx_AMSDU;
769 unsigned long rx_Total;
772 ==========================================================================
774 This routine is executed periodically to -
775 1. Decide if it's a right time to turn on PwrMgmt bit of all
777 2. Calculate ChannelQuality based on statistics of the last
778 period, so that TX rate won't toggling very frequently between a
779 successful TX and a failed TX.
780 3. If the calculated ChannelQuality indicated current connection not
781 healthy, then a ROAMing attempt is tried here.
783 IRQL = DISPATCH_LEVEL
785 ==========================================================================
787 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
788 VOID MlmePeriodicExec(
789 IN PVOID SystemSpecific1,
790 IN PVOID FunctionContext,
791 IN PVOID SystemSpecific2,
792 IN PVOID SystemSpecific3)
795 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
797 #ifdef CONFIG_STA_SUPPORT
798 #endif // CONFIG_STA_SUPPORT //
800 // Do nothing if the driver is starting halt state.
801 // This might happen when timer already been fired before cancel timer with mlmehalt
802 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
803 fRTMP_ADAPTER_RADIO_OFF |
804 fRTMP_ADAPTER_RADIO_MEASUREMENT |
805 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
808 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
810 #ifdef CONFIG_STA_SUPPORT
811 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
813 // Do nothing if monitor mode is on
817 if (pAd->Mlme.PeriodicRound & 0x1)
819 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
820 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
821 (STA_TGN_WIFI_ON(pAd)) &&
822 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
825 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
826 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
828 else if ((STA_TGN_WIFI_ON(pAd)) &&
829 ((pAd->MACVersion & 0xffff) == 0x0101))
831 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
832 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
836 #endif // CONFIG_STA_SUPPORT //
838 pAd->bUpdateBcnCntDone = FALSE;
840 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
841 pAd->Mlme.PeriodicRound ++;
844 // execute every 100ms, update the Tx FIFO Cnt for update Tx Rate.
845 NICUpdateFifoStaCounters(pAd);
847 // execute every 500ms
848 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
850 #ifdef CONFIG_STA_SUPPORT
851 // perform dynamic tx rate switching based on past TX history
852 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
854 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
856 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
857 MlmeDynamicTxRateSwitching(pAd);
859 #endif // CONFIG_STA_SUPPORT //
862 // Normal 1 second Mlme PeriodicExec.
863 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
865 pAd->Mlme.OneSecPeriodicRound ++;
875 //ORIBATimerTimeout(pAd);
877 // Media status changed, report to NDIS
878 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
880 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
881 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
883 pAd->IndicateMediaState = NdisMediaStateConnected;
884 RTMP_IndicateMediaState(pAd);
889 pAd->IndicateMediaState = NdisMediaStateDisconnected;
890 RTMP_IndicateMediaState(pAd);
894 NdisGetSystemUpTime(&pAd->Mlme.Now32);
896 // add the most up-to-date h/w raw counters into software variable, so that
897 // the dynamic tuning mechanism below are based on most up-to-date information
898 NICUpdateRawCounters(pAd);
901 RT2870_WatchDog(pAd);
904 #ifdef DOT11_N_SUPPORT
905 // Need statistics after read counter. So put after NICUpdateRawCounters
906 ORIBATimerTimeout(pAd);
907 #endif // DOT11_N_SUPPORT //
909 // The time period for checking antenna is according to traffic
911 if (pAd->Mlme.bEnableAutoAntennaCheck)
913 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
914 pAd->RalinkCounters.OneSecTxRetryOkCount +
915 pAd->RalinkCounters.OneSecTxFailCount;
917 // dynamic adjust antenna evaluation period according to the traffic
920 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
922 AsicEvaluateRxAnt(pAd);
927 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
929 AsicEvaluateRxAnt(pAd);
935 #ifdef CONFIG_STA_SUPPORT
936 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
937 STAMlmePeriodicExec(pAd);
938 #endif // CONFIG_STA_SUPPORT //
940 MlmeResetRalinkCounters(pAd);
942 #ifdef CONFIG_STA_SUPPORT
943 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
946 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
947 // and sending CTS-to-self over and over.
948 // Software Patch Solution:
949 // 1. Polling debug state register 0x10F4 every one second.
950 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
951 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
955 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
956 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
958 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
960 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
962 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
966 #endif // CONFIG_STA_SUPPORT //
968 RT28XX_MLME_HANDLER(pAd);
972 pAd->bUpdateBcnCntDone = FALSE;
975 #ifdef CONFIG_STA_SUPPORT
976 VOID STAMlmePeriodicExec(
982 #ifdef WPA_SUPPLICANT_SUPPORT
983 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
984 #endif // WPA_SUPPLICANT_SUPPORT //
986 // WPA MIC error should block association attempt for 60 seconds
987 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
988 pAd->StaCfg.bBlockAssoc = FALSE;
991 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
993 if (pAd->IndicateMediaState == NdisMediaStateConnected)
995 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
997 pAd->PreMediaState = pAd->IndicateMediaState;
1003 AsicStaBbpTuning(pAd);
1005 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1006 pAd->RalinkCounters.OneSecTxRetryOkCount +
1007 pAd->RalinkCounters.OneSecTxFailCount;
1009 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1011 // update channel quality for Roaming and UI LinkQuality display
1012 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1015 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1016 // Radio is currently in noisy environment
1017 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1018 AsicAdjustTxPower(pAd);
1022 // Is PSM bit consistent with user power management policy?
1023 // This is the only place that will set PSM bit ON.
1024 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1025 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1027 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1029 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1030 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1031 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1033 RTMPSetAGCInitValue(pAd, BW_20);
1034 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1037 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1038 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1040 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1042 // When APSD is enabled, the period changes as 20 sec
1043 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1044 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1048 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1049 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1051 if (pAd->CommonCfg.bWmmCapable)
1052 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1054 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1059 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1061 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1062 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1063 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1065 // Lost AP, send disconnect & link down event
1066 LinkDown(pAd, FALSE);
1068 #ifdef WPA_SUPPLICANT_SUPPORT
1069 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1070 if (pAd->StaCfg.WpaSupplicantUP)
1072 union iwreq_data wrqu;
1073 //send disassociate event to wpa_supplicant
1074 memset(&wrqu, 0, sizeof(wrqu));
1075 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1076 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1078 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1079 #endif // WPA_SUPPLICANT_SUPPORT //
1081 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1083 union iwreq_data wrqu;
1084 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1085 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1087 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1089 // RTMPPatchMacBbpBug(pAd);
1090 MlmeAutoReconnectLastSSID(pAd);
1092 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1094 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1095 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1096 MlmeAutoReconnectLastSSID(pAd);
1099 // Add auto seamless roaming
1100 if (pAd->StaCfg.bFastRoaming)
1102 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1104 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));
1106 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1108 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1112 else if (ADHOC_ON(pAd))
1115 if ((pAd->CommonCfg.Channel > 14)
1116 && (pAd->CommonCfg.bIEEE80211H == 1)
1117 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1119 RadarDetectPeriodic(pAd);
1122 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1123 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1125 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1126 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1128 MLME_START_REQ_STRUCT StartReq;
1130 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1131 LinkDown(pAd, FALSE);
1133 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1134 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1135 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1138 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1140 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1142 if (pEntry->ValidAsCLI == FALSE)
1145 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1146 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1149 else // no INFRA nor ADHOC connection
1152 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1153 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1154 goto SKIP_AUTO_SCAN_CONN;
1156 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1158 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1159 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1160 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1162 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1164 MLME_SCAN_REQ_STRUCT ScanReq;
1166 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1168 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1169 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1170 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1171 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1172 // Reset Missed scan number
1173 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1175 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1176 MlmeAutoReconnectLastSSID(pAd);
1178 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1180 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1183 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1187 MlmeAutoReconnectLastSSID(pAd);
1193 SKIP_AUTO_SCAN_CONN:
1195 #ifdef DOT11_N_SUPPORT
1196 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1198 pAd->MacTab.fAnyBASession = TRUE;
1199 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1201 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1203 pAd->MacTab.fAnyBASession = FALSE;
1204 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1206 #endif // DOT11_N_SUPPORT //
1213 IN PVOID SystemSpecific1,
1214 IN PVOID FunctionContext,
1215 IN PVOID SystemSpecific2,
1216 IN PVOID SystemSpecific3)
1219 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1221 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1222 RTMP_IndicateMediaState(pAd);
1223 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1226 // IRQL = DISPATCH_LEVEL
1228 IN PRTMP_ADAPTER pAd)
1230 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1231 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1233 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1235 MLME_CNTL_STATE_MACHINE,
1236 OID_802_11_BSSID_LIST_SCAN,
1239 RT28XX_MLME_HANDLER(pAd);
1243 // IRQL = DISPATCH_LEVEL
1244 VOID MlmeAutoReconnectLastSSID(
1245 IN PRTMP_ADAPTER pAd)
1249 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1250 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1251 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1253 NDIS_802_11_SSID OidSsid;
1254 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1255 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1257 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1259 MLME_CNTL_STATE_MACHINE,
1261 sizeof(NDIS_802_11_SSID),
1263 RT28XX_MLME_HANDLER(pAd);
1266 #endif // CONFIG_STA_SUPPORT //
1269 ==========================================================================
1270 Validate SSID for connection try and rescan purpose
1271 Valid SSID will have visible chars only.
1272 The valid length is from 0 to 32.
1273 IRQL = DISPATCH_LEVEL
1274 ==========================================================================
1276 BOOLEAN MlmeValidateSSID(
1282 if (SsidLen > MAX_LEN_OF_SSID)
1285 // Check each character value
1286 for (index = 0; index < SsidLen; index++)
1288 if (pSsid[index] < 0x20)
1296 VOID MlmeSelectTxRateTable(
1297 IN PRTMP_ADAPTER pAd,
1298 IN PMAC_TABLE_ENTRY pEntry,
1300 IN PUCHAR pTableSize,
1301 IN PUCHAR pInitTxRateIdx)
1305 // decide the rate table for tuning
1306 if (pAd->CommonCfg.TxRateTableSize > 0)
1308 *ppTable = RateSwitchTable;
1309 *pTableSize = RateSwitchTable[0];
1310 *pInitTxRateIdx = RateSwitchTable[1];
1315 #ifdef CONFIG_STA_SUPPORT
1316 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1318 #ifdef DOT11_N_SUPPORT
1319 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1320 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1321 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1323 *ppTable = RateSwitchTable11N1S;
1324 *pTableSize = RateSwitchTable11N1S[0];
1325 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1328 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1329 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1330 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1331 (pAd->Antenna.field.TxPath == 2))
1333 if (pAd->LatchRfRegs.Channel <= 14)
1335 *ppTable = RateSwitchTable11N2S;
1336 *pTableSize = RateSwitchTable11N2S[0];
1337 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1341 *ppTable = RateSwitchTable11N2SForABand;
1342 *pTableSize = RateSwitchTable11N2SForABand[0];
1343 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1348 #endif // DOT11_N_SUPPORT //
1349 if ((pEntry->RateLen == 4)
1350 #ifdef DOT11_N_SUPPORT
1351 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1352 #endif // DOT11_N_SUPPORT //
1355 *ppTable = RateSwitchTable11B;
1356 *pTableSize = RateSwitchTable11B[0];
1357 *pInitTxRateIdx = RateSwitchTable11B[1];
1360 else if (pAd->LatchRfRegs.Channel <= 14)
1362 *ppTable = RateSwitchTable11BG;
1363 *pTableSize = RateSwitchTable11BG[0];
1364 *pInitTxRateIdx = RateSwitchTable11BG[1];
1369 *ppTable = RateSwitchTable11G;
1370 *pTableSize = RateSwitchTable11G[0];
1371 *pInitTxRateIdx = RateSwitchTable11G[1];
1376 #endif // CONFIG_STA_SUPPORT //
1378 #ifdef DOT11_N_SUPPORT
1379 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1380 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1381 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1382 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1384 *ppTable = RateSwitchTable11BGN1S;
1385 *pTableSize = RateSwitchTable11BGN1S[0];
1386 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1391 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1392 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1393 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1394 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1396 if (pAd->LatchRfRegs.Channel <= 14)
1398 *ppTable = RateSwitchTable11BGN2S;
1399 *pTableSize = RateSwitchTable11BGN2S[0];
1400 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1405 *ppTable = RateSwitchTable11BGN2SForABand;
1406 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1407 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1413 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1414 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1416 *ppTable = RateSwitchTable11N1S;
1417 *pTableSize = RateSwitchTable11N1S[0];
1418 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1423 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1424 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1426 if (pAd->LatchRfRegs.Channel <= 14)
1428 *ppTable = RateSwitchTable11N2S;
1429 *pTableSize = RateSwitchTable11N2S[0];
1430 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1434 *ppTable = RateSwitchTable11N2SForABand;
1435 *pTableSize = RateSwitchTable11N2SForABand[0];
1436 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1441 #endif // DOT11_N_SUPPORT //
1442 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1443 if ((pEntry->RateLen == 4)
1444 #ifdef DOT11_N_SUPPORT
1445 //Iverson mark for Adhoc b mode,sta will use rate 54 Mbps when connect with sta b/g/n mode
1446 // && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1447 #endif // DOT11_N_SUPPORT //
1450 *ppTable = RateSwitchTable11B;
1451 *pTableSize = RateSwitchTable11B[0];
1452 *pInitTxRateIdx = RateSwitchTable11B[1];
1457 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1458 if ((pEntry->RateLen > 8)
1459 #ifdef DOT11_N_SUPPORT
1460 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1461 #endif // DOT11_N_SUPPORT //
1464 *ppTable = RateSwitchTable11BG;
1465 *pTableSize = RateSwitchTable11BG[0];
1466 *pInitTxRateIdx = RateSwitchTable11BG[1];
1471 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1472 if ((pEntry->RateLen == 8)
1473 #ifdef DOT11_N_SUPPORT
1474 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1475 #endif // DOT11_N_SUPPORT //
1478 *ppTable = RateSwitchTable11G;
1479 *pTableSize = RateSwitchTable11G[0];
1480 *pInitTxRateIdx = RateSwitchTable11G[1];
1484 #ifdef DOT11_N_SUPPORT
1485 #endif // DOT11_N_SUPPORT //
1487 #ifdef CONFIG_STA_SUPPORT
1488 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1490 #ifdef DOT11_N_SUPPORT
1491 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1492 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1493 #endif // DOT11_N_SUPPORT //
1495 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1497 *ppTable = RateSwitchTable11B;
1498 *pTableSize = RateSwitchTable11B[0];
1499 *pInitTxRateIdx = RateSwitchTable11B[1];
1501 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1503 *ppTable = RateSwitchTable11G;
1504 *pTableSize = RateSwitchTable11G[0];
1505 *pInitTxRateIdx = RateSwitchTable11G[1];
1510 *ppTable = RateSwitchTable11BG;
1511 *pTableSize = RateSwitchTable11BG[0];
1512 *pInitTxRateIdx = RateSwitchTable11BG[1];
1516 #ifdef DOT11_N_SUPPORT
1517 if (pAd->LatchRfRegs.Channel <= 14)
1519 if (pAd->CommonCfg.TxStream == 1)
1521 *ppTable = RateSwitchTable11N1S;
1522 *pTableSize = RateSwitchTable11N1S[0];
1523 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1524 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1528 *ppTable = RateSwitchTable11N2S;
1529 *pTableSize = RateSwitchTable11N2S[0];
1530 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1531 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1536 if (pAd->CommonCfg.TxStream == 1)
1538 *ppTable = RateSwitchTable11N1S;
1539 *pTableSize = RateSwitchTable11N1S[0];
1540 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1541 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1545 *ppTable = RateSwitchTable11N2SForABand;
1546 *pTableSize = RateSwitchTable11N2SForABand[0];
1547 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1548 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1551 #endif // DOT11_N_SUPPORT //
1552 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1553 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1555 #endif // CONFIG_STA_SUPPORT //
1559 #ifdef CONFIG_STA_SUPPORT
1561 ==========================================================================
1563 This routine checks if there're other APs out there capable for
1564 roaming. Caller should call this routine only when Link up in INFRA mode
1565 and channel quality is below CQI_GOOD_THRESHOLD.
1567 IRQL = DISPATCH_LEVEL
1570 ==========================================================================
1572 VOID MlmeCheckForRoaming(
1573 IN PRTMP_ADAPTER pAd,
1577 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1580 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1581 // put all roaming candidates into RoamTab, and sort in RSSI order
1582 BssTableInit(pRoamTab);
1583 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1585 pBss = &pAd->ScanTab.BssEntry[i];
1587 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1588 continue; // AP disappear
1589 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1590 continue; // RSSI too weak. forget it.
1591 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1592 continue; // skip current AP
1593 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1594 continue; // only AP with stronger RSSI is eligible for roaming
1596 // AP passing all above rules is put into roaming candidate table
1597 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1598 pRoamTab->BssNr += 1;
1601 if (pRoamTab->BssNr > 0)
1603 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1604 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1606 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1607 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1608 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1609 RT28XX_MLME_HANDLER(pAd);
1612 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1616 ==========================================================================
1618 This routine checks if there're other APs out there capable for
1619 roaming. Caller should call this routine only when link up in INFRA mode
1620 and channel quality is below CQI_GOOD_THRESHOLD.
1622 IRQL = DISPATCH_LEVEL
1625 ==========================================================================
1627 VOID MlmeCheckForFastRoaming(
1628 IN PRTMP_ADAPTER pAd,
1632 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1635 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1636 // put all roaming candidates into RoamTab, and sort in RSSI order
1637 BssTableInit(pRoamTab);
1638 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1640 pBss = &pAd->ScanTab.BssEntry[i];
1642 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1643 continue; // RSSI too weak. forget it.
1644 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1645 continue; // skip current AP
1646 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1647 continue; // skip different SSID
1648 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1649 continue; // skip AP without better RSSI
1651 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));
1652 // AP passing all above rules is put into roaming candidate table
1653 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1654 pRoamTab->BssNr += 1;
1657 if (pRoamTab->BssNr > 0)
1659 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1660 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1662 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1663 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1664 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1665 RT28XX_MLME_HANDLER(pAd);
1668 // Maybe site survey required
1671 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1673 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1674 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1675 pAd->StaCfg.ScanCnt = 2;
1676 pAd->StaCfg.LastScanTime = Now;
1681 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1685 ==========================================================================
1687 This routine calculates TxPER, RxPER of the past N-sec period. And
1688 according to the calculation result, ChannelQuality is calculated here
1689 to decide if current AP is still doing the job.
1691 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1693 StaCfg.ChannelQuality - 0..100
1695 IRQL = DISPATCH_LEVEL
1697 NOTE: This routine decide channle quality based on RX CRC error ratio.
1698 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1699 is performed right before this routine, so that this routine can decide
1700 channel quality based on the most up-to-date information
1701 ==========================================================================
1703 VOID MlmeCalculateChannelQuality(
1704 IN PRTMP_ADAPTER pAd,
1707 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1711 ULONG BeaconLostTime = BEACON_LOST_TIME;
1713 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1716 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1718 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1719 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1727 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1728 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1732 // calculate RX PER - don't take RxPER into consideration if too few sample
1734 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1738 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1741 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1743 if (INFRA_ON(pAd) &&
1744 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1745 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1747 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1748 pAd->Mlme.ChannelQuality = 0;
1755 else if (MaxRssi < -90)
1758 NorRssi = (MaxRssi + 90) * 2;
1760 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1761 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1762 TX_WEIGHTING * (100 - TxPRR) +
1763 RX_WEIGHTING* (100 - RxPER)) / 100;
1764 if (pAd->Mlme.ChannelQuality >= 100)
1765 pAd->Mlme.ChannelQuality = 100;
1771 IN PRTMP_ADAPTER pAd,
1772 IN PMAC_TABLE_ENTRY pEntry,
1773 IN PRTMP_TX_RATE_SWITCH pTxRate)
1775 UCHAR MaxMode = MODE_OFDM;
1777 #ifdef DOT11_N_SUPPORT
1778 MaxMode = MODE_HTGREENFIELD;
1780 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1781 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1783 #endif // DOT11_N_SUPPORT //
1784 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1786 if (pTxRate->CurrMCS < MCS_AUTO)
1787 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1789 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1790 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1794 // If peer adhoc is b-only mode, we can't send 11g rate.
1795 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1796 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1799 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1801 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1802 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1803 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1805 // Patch speed error in status page
1806 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1810 if (pTxRate->Mode <= MaxMode)
1811 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1813 #ifdef DOT11_N_SUPPORT
1814 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1815 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1817 #endif // DOT11_N_SUPPORT //
1818 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1820 #ifdef DOT11_N_SUPPORT
1821 // Reexam each bandwidth's SGI support.
1822 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1824 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1825 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1826 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1827 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1830 // Turn RTS/CTS rate to 6Mbps.
1831 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1833 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1834 if (pAd->MacTab.fAnyBASession)
1836 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1840 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1843 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1845 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1846 if (pAd->MacTab.fAnyBASession)
1848 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1852 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1855 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1857 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1860 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1862 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1864 #endif // DOT11_N_SUPPORT //
1866 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1867 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1868 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1869 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1870 #ifdef DOT11_N_SUPPORT
1871 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1872 pAd->WIFItestbed.bGreenField)
1873 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1874 #endif // DOT11_N_SUPPORT //
1877 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1881 ==========================================================================
1883 This routine calculates the acumulated TxPER of eaxh TxRate. And
1884 according to the calculation result, change CommonCfg.TxRate which
1885 is the stable TX Rate we expect the Radio situation could sustained.
1887 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1891 IRQL = DISPATCH_LEVEL
1894 call this routine every second
1895 ==========================================================================
1897 VOID MlmeDynamicTxRateSwitching(
1898 IN PRTMP_ADAPTER pAd)
1900 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1901 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1902 ULONG TxErrorRatio = 0;
1903 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1904 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1906 UCHAR TableSize = 0;
1907 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1908 CHAR Rssi, RssiOffset = 0;
1909 TX_STA_CNT1_STRUC StaTx1;
1910 TX_STA_CNT0_STRUC TxStaCnt0;
1911 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1912 MAC_TABLE_ENTRY *pEntry;
1915 // walk through MAC table, see if need to change AP's TX rate toward each entry
1917 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1919 pEntry = &pAd->MacTab.Content[i];
1921 // check if this entry need to switch rate automatically
1922 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1925 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1927 Rssi = RTMPMaxRssi(pAd,
1928 pAd->StaCfg.RssiSample.AvgRssi0,
1929 pAd->StaCfg.RssiSample.AvgRssi1,
1930 pAd->StaCfg.RssiSample.AvgRssi2);
1932 // Update statistic counter
1933 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1934 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1935 pAd->bUpdateBcnCntDone = TRUE;
1936 TxRetransmit = StaTx1.field.TxRetransmit;
1937 TxSuccess = StaTx1.field.TxSuccess;
1938 TxFailCount = TxStaCnt0.field.TxFailCount;
1939 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1941 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
1942 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
1943 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
1944 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
1945 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
1946 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
1948 // if no traffic in the past 1-sec period, don't change TX rate,
1949 // but clear all bad history. because the bad history may affect the next
1950 // Chariot throughput test
1951 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1952 pAd->RalinkCounters.OneSecTxRetryOkCount +
1953 pAd->RalinkCounters.OneSecTxFailCount;
1956 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
1960 if (INFRA_ON(pAd) && (i == 1))
1961 Rssi = RTMPMaxRssi(pAd,
1962 pAd->StaCfg.RssiSample.AvgRssi0,
1963 pAd->StaCfg.RssiSample.AvgRssi1,
1964 pAd->StaCfg.RssiSample.AvgRssi2);
1966 Rssi = RTMPMaxRssi(pAd,
1967 pEntry->RssiSample.AvgRssi0,
1968 pEntry->RssiSample.AvgRssi1,
1969 pEntry->RssiSample.AvgRssi2);
1971 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
1972 pEntry->OneSecTxRetryOkCount +
1973 pEntry->OneSecTxFailCount;
1976 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
1979 CurrRateIdx = pEntry->CurrTxRateIndex;
1981 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
1983 if (CurrRateIdx >= TableSize)
1985 CurrRateIdx = TableSize - 1;
1988 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
1989 // So need to sync here.
1990 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
1991 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
1992 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
1996 // Need to sync Real Tx rate and our record.
1997 // Then return for next DRS.
1998 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
1999 pEntry->CurrTxRateIndex = InitTxRateIdx;
2000 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2002 // reset all OneSecTx counters
2003 RESET_ONE_SEC_TX_CNT(pEntry);
2007 // decide the next upgrade rate and downgrade rate, if any
2008 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2010 UpRateIdx = CurrRateIdx + 1;
2011 DownRateIdx = CurrRateIdx -1;
2013 else if (CurrRateIdx == 0)
2015 UpRateIdx = CurrRateIdx + 1;
2016 DownRateIdx = CurrRateIdx;
2018 else if (CurrRateIdx == (TableSize - 1))
2020 UpRateIdx = CurrRateIdx;
2021 DownRateIdx = CurrRateIdx - 1;
2024 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2026 #ifdef DOT11_N_SUPPORT
2027 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2029 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2030 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2033 #endif // DOT11_N_SUPPORT //
2035 TrainUp = pCurrTxRate->TrainUp;
2036 TrainDown = pCurrTxRate->TrainDown;
2039 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2042 // Keep the last time TxRateChangeAction status.
2044 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2049 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2050 // (criteria copied from RT2500 for Netopia case)
2052 if (TxTotalCnt <= 15)
2056 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2057 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2058 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2059 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2061 // check the existence and index of each needed MCS
2062 while (idx < pTable[0])
2064 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2066 if (pCurrTxRate->CurrMCS == MCS_0)
2070 else if (pCurrTxRate->CurrMCS == MCS_1)
2074 else if (pCurrTxRate->CurrMCS == MCS_2)
2078 else if (pCurrTxRate->CurrMCS == MCS_3)
2082 else if (pCurrTxRate->CurrMCS == MCS_4)
2086 else if (pCurrTxRate->CurrMCS == MCS_5)
2090 else if (pCurrTxRate->CurrMCS == MCS_6)
2094 //else if (pCurrTxRate->CurrMCS == MCS_7)
2095 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2099 else if (pCurrTxRate->CurrMCS == MCS_12)
2103 else if (pCurrTxRate->CurrMCS == MCS_13)
2107 else if (pCurrTxRate->CurrMCS == MCS_14)
2111 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800))
2115 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2119 else if (pCurrTxRate->CurrMCS == MCS_21)
2123 else if (pCurrTxRate->CurrMCS == MCS_22)
2127 else if (pCurrTxRate->CurrMCS == MCS_23)
2134 if (pAd->LatchRfRegs.Channel <= 14)
2136 if (pAd->NicConfig2.field.ExternalLNAForG)
2147 if (pAd->NicConfig2.field.ExternalLNAForA)
2156 #ifdef DOT11_N_SUPPORT
2158 if ((pTable == RateSwitchTable11BGN3S) ||
2159 (pTable == RateSwitchTable11N3S) ||
2160 (pTable == RateSwitchTable))
2161 {// N mode with 3 stream // 3*3
2162 if (MCS23 && (Rssi >= -70))
2164 else if (MCS22 && (Rssi >= -72))
2166 else if (MCS21 && (Rssi >= -76))
2168 else if (MCS20 && (Rssi >= -78))
2170 else if (MCS4 && (Rssi >= -82))
2172 else if (MCS3 && (Rssi >= -84))
2174 else if (MCS2 && (Rssi >= -86))
2176 else if (MCS1 && (Rssi >= -88))
2181 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2182 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2183 {// N mode with 2 stream
2184 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2186 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2188 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2190 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2192 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2194 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2196 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2198 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2203 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2204 {// N mode with 1 stream
2205 if (MCS7 && (Rssi > (-72+RssiOffset)))
2207 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2209 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2211 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2213 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2215 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2217 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2223 #endif // DOT11_N_SUPPORT //
2225 if (MCS7 && (Rssi > -70))
2227 else if (MCS6 && (Rssi > -74))
2229 else if (MCS5 && (Rssi > -78))
2231 else if (MCS4 && (Rssi > -82))
2233 else if (MCS4 == 0) // for B-only mode
2235 else if (MCS3 && (Rssi > -85))
2237 else if (MCS2 && (Rssi > -87))
2239 else if (MCS1 && (Rssi > -90))
2245 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2247 pEntry->CurrTxRateIndex = TxRateIdx;
2248 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2249 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2252 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2253 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2254 pEntry->fLastSecAccordingRSSI = TRUE;
2255 // reset all OneSecTx counters
2256 RESET_ONE_SEC_TX_CNT(pEntry);
2261 if (pEntry->fLastSecAccordingRSSI == TRUE)
2263 pEntry->fLastSecAccordingRSSI = FALSE;
2264 pEntry->LastSecTxRateChangeAction = 0;
2265 // reset all OneSecTx counters
2266 RESET_ONE_SEC_TX_CNT(pEntry);
2273 BOOLEAN bTrainUpDown = FALSE;
2275 pEntry->CurrTxRateStableTime ++;
2277 // downgrade TX quality if PER >= Rate-Down threshold
2278 if (TxErrorRatio >= TrainDown)
2280 bTrainUpDown = TRUE;
2281 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2283 // upgrade TX quality if PER <= Rate-Up threshold
2284 else if (TxErrorRatio <= TrainUp)
2286 bTrainUpDown = TRUE;
2287 bUpgradeQuality = TRUE;
2288 if (pEntry->TxQuality[CurrRateIdx])
2289 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2291 if (pEntry->TxRateUpPenalty)
2292 pEntry->TxRateUpPenalty --;
2293 else if (pEntry->TxQuality[UpRateIdx])
2294 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2297 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2301 // perform DRS - consider TxRate Down first, then rate up.
2302 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2304 pEntry->CurrTxRateIndex = DownRateIdx;
2306 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2308 pEntry->CurrTxRateIndex = UpRateIdx;
2313 // if rate-up happen, clear all bad history of all TX rates
2314 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2316 pEntry->CurrTxRateStableTime = 0;
2317 pEntry->TxRateUpPenalty = 0;
2318 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2319 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2320 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2323 // For TxRate fast train up
2325 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2327 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2329 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2331 bTxRateChanged = TRUE;
2333 // if rate-down happen, only clear DownRate's bad history
2334 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2336 pEntry->CurrTxRateStableTime = 0;
2337 pEntry->TxRateUpPenalty = 0; // no penalty
2338 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2339 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2340 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2343 // For TxRate fast train down
2345 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2347 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2349 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2351 bTxRateChanged = TRUE;
2355 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2356 bTxRateChanged = FALSE;
2359 pEntry->LastTxOkCount = TxSuccess;
2361 // reset all OneSecTx counters
2362 RESET_ONE_SEC_TX_CNT(pEntry);
2364 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2365 if (bTxRateChanged && pNextTxRate)
2367 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2373 ========================================================================
2374 Routine Description:
2375 Station side, Auto TxRate faster train up timer call back function.
2378 SystemSpecific1 - Not used.
2379 FunctionContext - Pointer to our Adapter context.
2380 SystemSpecific2 - Not used.
2381 SystemSpecific3 - Not used.
2386 ========================================================================
2388 VOID StaQuickResponeForRateUpExec(
2389 IN PVOID SystemSpecific1,
2390 IN PVOID FunctionContext,
2391 IN PVOID SystemSpecific2,
2392 IN PVOID SystemSpecific3)
2394 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2395 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2397 ULONG TxErrorRatio = 0;
2398 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2399 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2401 UCHAR TableSize = 0;
2402 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2403 TX_STA_CNT1_STRUC StaTx1;
2404 TX_STA_CNT0_STRUC TxStaCnt0;
2406 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2407 MAC_TABLE_ENTRY *pEntry;
2410 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2413 // walk through MAC table, see if need to change AP's TX rate toward each entry
2415 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2417 pEntry = &pAd->MacTab.Content[i];
2419 // check if this entry need to switch rate automatically
2420 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2423 if (INFRA_ON(pAd) && (i == 1))
2424 Rssi = RTMPMaxRssi(pAd,
2425 pAd->StaCfg.RssiSample.AvgRssi0,
2426 pAd->StaCfg.RssiSample.AvgRssi1,
2427 pAd->StaCfg.RssiSample.AvgRssi2);
2429 Rssi = RTMPMaxRssi(pAd,
2430 pEntry->RssiSample.AvgRssi0,
2431 pEntry->RssiSample.AvgRssi1,
2432 pEntry->RssiSample.AvgRssi2);
2434 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2436 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2438 // decide the next upgrade rate and downgrade rate, if any
2439 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2441 UpRateIdx = CurrRateIdx + 1;
2442 DownRateIdx = CurrRateIdx -1;
2444 else if (CurrRateIdx == 0)
2446 UpRateIdx = CurrRateIdx + 1;
2447 DownRateIdx = CurrRateIdx;
2449 else if (CurrRateIdx == (TableSize - 1))
2451 UpRateIdx = CurrRateIdx;
2452 DownRateIdx = CurrRateIdx - 1;
2455 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2457 #ifdef DOT11_N_SUPPORT
2458 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2460 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2461 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2464 #endif // DOT11_N_SUPPORT //
2466 TrainUp = pCurrTxRate->TrainUp;
2467 TrainDown = pCurrTxRate->TrainDown;
2470 if (pAd->MacTab.Size == 1)
2472 // Update statistic counter
2473 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2474 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2476 TxRetransmit = StaTx1.field.TxRetransmit;
2477 TxSuccess = StaTx1.field.TxSuccess;
2478 TxFailCount = TxStaCnt0.field.TxFailCount;
2479 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2481 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2482 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2483 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2484 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2485 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2486 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2489 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2493 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2494 pEntry->OneSecTxRetryOkCount +
2495 pEntry->OneSecTxFailCount;
2498 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2503 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2504 // (criteria copied from RT2500 for Netopia case)
2506 if (TxTotalCnt <= 12)
2508 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2509 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2511 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2513 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2514 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2516 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2518 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2521 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2527 ULONG OneSecTxNoRetryOKRationCount;
2529 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2534 // downgrade TX quality if PER >= Rate-Down threshold
2535 if (TxErrorRatio >= TrainDown)
2537 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2540 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2542 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2544 // perform DRS - consider TxRate Down first, then rate up.
2545 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2547 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2549 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2550 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2555 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2557 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2561 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2563 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2568 // if rate-up happen, clear all bad history of all TX rates
2569 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2571 pAd->DrsCounters.TxRateUpPenalty = 0;
2572 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2573 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2574 bTxRateChanged = TRUE;
2576 // if rate-down happen, only clear DownRate's bad history
2577 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2579 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2581 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2582 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2583 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2584 bTxRateChanged = TRUE;
2588 bTxRateChanged = FALSE;
2591 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2592 if (bTxRateChanged && pNextTxRate)
2594 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2600 ==========================================================================
2602 This routine is executed periodically inside MlmePeriodicExec() after
2603 association with an AP.
2604 It checks if StaCfg.Psm is consistent with user policy (recorded in
2605 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2606 there're some conditions to consider:
2607 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2608 the time when Mibss==TRUE
2609 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2610 if outgoing traffic available in TxRing or MgmtRing.
2612 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2614 IRQL = DISPATCH_LEVEL
2616 ==========================================================================
2618 VOID MlmeCheckPsmChange(
2619 IN PRTMP_ADAPTER pAd,
2625 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2626 // 2. user wants either MAX_PSP or FAST_PSP
2627 // 3. but current psm is not in PWR_SAVE
2628 // 4. CNTL state machine is not doing SCANning
2629 // 5. no TX SUCCESS event for the past 1-sec period
2630 #ifdef NDIS51_MINIPORT
2631 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2632 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2635 PowerMode = pAd->StaCfg.WindowsPowerMode;
2637 if (INFRA_ON(pAd) &&
2638 (PowerMode != Ndis802_11PowerModeCAM) &&
2639 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2640 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2641 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2642 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2643 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2645 // add by johnli, use Rx OK data count per second to calculate throughput
2646 // If Ttraffic is too high ( > 400 Rx per second), don't go to sleep mode. If tx rate is low, use low criteria
2647 // Mode=CCK/MCS=3 => 11 Mbps, Mode=OFDM/MCS=3 => 18 Mbps
2648 if (((pAd->StaCfg.HTPhyMode.field.MCS <= 3) &&
2650 (pAd->StaCfg.HTPhyMode.field.MODE <= MODE_OFDM) &&
2652 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)100)) ||
2653 ((pAd->StaCfg.HTPhyMode.field.MCS > 3) &&
2655 (pAd->StaCfg.HTPhyMode.field.MODE > MODE_OFDM) &&
2657 (pAd->RalinkCounters.OneSecRxOkDataCnt < (ULONG)400)))
2660 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2661 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2662 MlmeSetPsmBit(pAd, PWR_SAVE);
2663 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2665 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2669 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2675 // IRQL = PASSIVE_LEVEL
2676 // IRQL = DISPATCH_LEVEL
2678 IN PRTMP_ADAPTER pAd,
2681 AUTO_RSP_CFG_STRUC csr4;
2683 pAd->StaCfg.Psm = psm;
2684 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2685 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2686 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2688 #endif // CONFIG_STA_SUPPORT //
2691 // IRQL = DISPATCH_LEVEL
2692 VOID MlmeSetTxPreamble(
2693 IN PRTMP_ADAPTER pAd,
2694 IN USHORT TxPreamble)
2696 AUTO_RSP_CFG_STRUC csr4;
2699 // Always use Long preamble before verifiation short preamble functionality works well.
2700 // Todo: remove the following line if short preamble functionality works
2702 //TxPreamble = Rt802_11PreambleLong;
2704 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2705 if (TxPreamble == Rt802_11PreambleLong)
2707 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2708 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2709 csr4.field.AutoResponderPreamble = 0;
2713 // NOTE: 1Mbps should always use long preamble
2714 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2715 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2716 csr4.field.AutoResponderPreamble = 1;
2719 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2723 ==========================================================================
2725 Update basic rate bitmap
2726 ==========================================================================
2729 VOID UpdateBasicRateBitmap(
2730 IN PRTMP_ADAPTER pAdapter)
2733 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2734 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2735 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2736 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2737 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2740 /* if A mode, always use fix BasicRateBitMap */
2741 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2742 if (pAdapter->CommonCfg.Channel > 14)
2743 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2746 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2748 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2752 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2758 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2760 if (bitmap & (1 << i))
2762 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2764 if (sup_p[j] == rate[i])
2769 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2771 if (ext_p[j] == rate[i])
2777 } /* End of UpdateBasicRateBitmap */
2779 // IRQL = PASSIVE_LEVEL
2780 // IRQL = DISPATCH_LEVEL
2781 // bLinkUp is to identify the inital link speed.
2782 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2783 VOID MlmeUpdateTxRates(
2784 IN PRTMP_ADAPTER pAd,
2789 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2790 UCHAR MinSupport = RATE_54;
2791 ULONG BasicRateBitmap = 0;
2792 UCHAR CurrBasicRate = RATE_1;
2793 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2794 PHTTRANSMIT_SETTING pHtPhy = NULL;
2795 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2796 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2797 BOOLEAN *auto_rate_cur_p;
2798 UCHAR HtMcs = MCS_AUTO;
2800 // find max desired rate
2801 UpdateBasicRateBitmap(pAd);
2804 auto_rate_cur_p = NULL;
2805 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2807 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2809 case 2: Rate = RATE_1; num++; break;
2810 case 4: Rate = RATE_2; num++; break;
2811 case 11: Rate = RATE_5_5; num++; break;
2812 case 22: Rate = RATE_11; num++; break;
2813 case 12: Rate = RATE_6; num++; break;
2814 case 18: Rate = RATE_9; num++; break;
2815 case 24: Rate = RATE_12; num++; break;
2816 case 36: Rate = RATE_18; num++; break;
2817 case 48: Rate = RATE_24; num++; break;
2818 case 72: Rate = RATE_36; num++; break;
2819 case 96: Rate = RATE_48; num++; break;
2820 case 108: Rate = RATE_54; num++; break;
2821 //default: Rate = RATE_1; break;
2823 if (MaxDesire < Rate) MaxDesire = Rate;
2826 //===========================================================================
2827 //===========================================================================
2829 #ifdef CONFIG_STA_SUPPORT
2830 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2832 pHtPhy = &pAd->StaCfg.HTPhyMode;
2833 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2834 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2836 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2837 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2839 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2840 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2841 (MaxDesire > RATE_11))
2843 MaxDesire = RATE_11;
2846 #endif // CONFIG_STA_SUPPORT //
2848 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2849 pMinHtPhy->word = 0;
2850 pMaxHtPhy->word = 0;
2853 // Auto rate switching is enabled only if more than one DESIRED RATES are
2854 // specified; otherwise disabled
2857 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2858 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2859 *auto_rate_cur_p = FALSE;
2863 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2864 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2865 *auto_rate_cur_p = TRUE;
2869 if (HtMcs != MCS_AUTO)
2871 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2872 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2873 *auto_rate_cur_p = FALSE;
2877 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2878 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2879 *auto_rate_cur_p = TRUE;
2883 #ifdef CONFIG_STA_SUPPORT
2884 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2886 pSupRate = &pAd->StaActive.SupRate[0];
2887 pExtRate = &pAd->StaActive.ExtRate[0];
2888 SupRateLen = pAd->StaActive.SupRateLen;
2889 ExtRateLen = pAd->StaActive.ExtRateLen;
2892 #endif // CONFIG_STA_SUPPORT //
2894 pSupRate = &pAd->CommonCfg.SupRate[0];
2895 pExtRate = &pAd->CommonCfg.ExtRate[0];
2896 SupRateLen = pAd->CommonCfg.SupRateLen;
2897 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2900 // find max supported rate
2901 for (i=0; i<SupRateLen; i++)
2903 switch (pSupRate[i] & 0x7f)
2905 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2906 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2907 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2908 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2909 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2910 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2911 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2912 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2913 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2914 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2915 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2916 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2917 default: Rate = RATE_1; break;
2919 if (MaxSupport < Rate) MaxSupport = Rate;
2921 if (MinSupport > Rate) MinSupport = Rate;
2924 for (i=0; i<ExtRateLen; i++)
2926 switch (pExtRate[i] & 0x7f)
2928 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2929 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2930 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2931 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2932 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2933 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2934 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2935 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2936 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2937 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2938 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2939 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2940 default: Rate = RATE_1; break;
2942 if (MaxSupport < Rate) MaxSupport = Rate;
2944 if (MinSupport > Rate) MinSupport = Rate;
2947 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2949 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2950 // the DURATION field of outgoing uniicast DATA/MGMT frame
2951 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2953 if (BasicRateBitmap & (0x01 << i))
2954 CurrBasicRate = (UCHAR)i;
2955 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2958 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2959 // max tx rate = min {max desire rate, max supported rate}
2960 if (MaxSupport < MaxDesire)
2961 pAd->CommonCfg.MaxTxRate = MaxSupport;
2963 pAd->CommonCfg.MaxTxRate = MaxDesire;
2965 pAd->CommonCfg.MinTxRate = MinSupport;
2966 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
2967 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
2969 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
2970 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
2971 // 3. -75 > RSSI, start at 11 Mbps (long distance)
2972 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
2973 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
2974 if (*auto_rate_cur_p)
2977 #ifdef CONFIG_STA_SUPPORT
2978 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2979 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2980 #endif // CONFIG_STA_SUPPORT //
2981 if (bLinkUp == TRUE)
2982 pAd->CommonCfg.TxRate = RATE_24;
2984 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2987 pAd->CommonCfg.TxRate = RATE_11;
2989 pAd->CommonCfg.TxRate = RATE_24;
2991 // should never exceed MaxTxRate (consider 11B-only mode)
2992 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2993 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2995 pAd->CommonCfg.TxRateIndex = 0;
2999 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3000 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3001 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3003 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3004 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3005 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3006 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3009 if (pAd->CommonCfg.TxRate <= RATE_11)
3011 pMaxHtPhy->field.MODE = MODE_CCK;
3012 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3013 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3017 pMaxHtPhy->field.MODE = MODE_OFDM;
3018 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3019 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3020 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3022 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3025 pHtPhy->word = (pMaxHtPhy->word);
3026 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3028 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3029 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3030 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3034 switch (pAd->CommonCfg.PhyMode)
3036 case PHY_11BG_MIXED:
3038 #ifdef DOT11_N_SUPPORT
3039 case PHY_11BGN_MIXED:
3040 #endif // DOT11_N_SUPPORT //
3041 pAd->CommonCfg.MlmeRate = RATE_1;
3042 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3043 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3046 pAd->CommonCfg.RtsRate = RATE_11;
3048 // pAd->CommonCfg.RtsRate = RATE_1;
3053 #ifdef DOT11_N_SUPPORT
3054 case PHY_11AGN_MIXED:
3055 case PHY_11GN_MIXED:
3057 case PHY_11AN_MIXED:
3059 #endif // DOT11_N_SUPPORT //
3060 pAd->CommonCfg.MlmeRate = RATE_6;
3061 pAd->CommonCfg.RtsRate = RATE_6;
3062 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3063 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3065 case PHY_11ABG_MIXED:
3066 #ifdef DOT11_N_SUPPORT
3067 case PHY_11ABGN_MIXED:
3068 #endif // DOT11_N_SUPPORT //
3069 if (pAd->CommonCfg.Channel <= 14)
3071 pAd->CommonCfg.MlmeRate = RATE_1;
3072 pAd->CommonCfg.RtsRate = RATE_1;
3073 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3074 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3078 pAd->CommonCfg.MlmeRate = RATE_6;
3079 pAd->CommonCfg.RtsRate = RATE_6;
3080 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3081 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3085 pAd->CommonCfg.MlmeRate = RATE_6;
3086 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3087 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3088 pAd->CommonCfg.RtsRate = RATE_1;
3092 // Keep Basic Mlme Rate.
3094 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3095 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3096 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3098 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3099 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3102 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3103 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3104 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3105 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3106 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3107 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3108 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 ));
3111 #ifdef DOT11_N_SUPPORT
3113 ==========================================================================
3115 This function update HT Rate setting.
3116 Input Wcid value is valid for 2 case :
3117 1. it's used for Station in infra mode that copy AP rate to Mactable.
3118 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3120 IRQL = DISPATCH_LEVEL
3122 ==========================================================================
3124 VOID MlmeUpdateHtTxRates(
3125 IN PRTMP_ADAPTER pAd,
3128 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3130 RT_HT_CAPABILITY *pRtHtCap = NULL;
3131 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3134 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3135 PHTTRANSMIT_SETTING pHtPhy = NULL;
3136 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3137 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3138 BOOLEAN *auto_rate_cur_p;
3140 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3142 auto_rate_cur_p = NULL;
3144 #ifdef CONFIG_STA_SUPPORT
3145 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3147 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3148 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3149 pHtPhy = &pAd->StaCfg.HTPhyMode;
3150 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3151 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3153 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3155 #endif // CONFIG_STA_SUPPORT //
3157 #ifdef CONFIG_STA_SUPPORT
3158 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3160 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3163 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3164 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3165 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3166 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3167 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3168 pMaxHtPhy->field.STBC = STBC_USE;
3170 pMaxHtPhy->field.STBC = STBC_NONE;
3173 #endif // CONFIG_STA_SUPPORT //
3175 if (pDesireHtPhy->bHtEnable == FALSE)
3178 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3179 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3180 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3181 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3182 pMaxHtPhy->field.STBC = STBC_USE;
3184 pMaxHtPhy->field.STBC = STBC_NONE;
3187 // Decide MAX ht rate.
3188 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3189 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3191 pMaxHtPhy->field.MODE = MODE_HTMIX;
3193 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3194 pMaxHtPhy->field.BW = BW_40;
3196 pMaxHtPhy->field.BW = BW_20;
3198 if (pMaxHtPhy->field.BW == BW_20)
3199 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3201 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3203 for (i=23; i>=0; i--) // 3*3
3206 bitmask = (1<<(i-(j*8)));
3208 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3210 pMaxHtPhy->field.MCS = i;
3218 // Copy MIN ht rate. rt2860???
3219 pMinHtPhy->field.BW = BW_20;
3220 pMinHtPhy->field.MCS = 0;
3221 pMinHtPhy->field.STBC = 0;
3222 pMinHtPhy->field.ShortGI = 0;
3223 //If STA assigns fixed rate. update to fixed here.
3224 #ifdef CONFIG_STA_SUPPORT
3225 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3227 if (pDesireHtPhy->MCSSet[4] != 0)
3229 pMaxHtPhy->field.MCS = 32;
3230 pMinHtPhy->field.MCS = 32;
3231 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3234 for (i=23; (CHAR)i >= 0; i--) // 3*3
3237 bitmask = (1<<(i-(j*8)));
3238 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3240 pMaxHtPhy->field.MCS = i;
3241 pMinHtPhy->field.MCS = i;
3248 #endif // CONFIG_STA_SUPPORT //
3252 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3253 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3254 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3255 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3256 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3258 // use default now. rt2860
3259 if (pDesireHtPhy->MCSSet[0] != 0xff)
3260 *auto_rate_cur_p = FALSE;
3262 *auto_rate_cur_p = TRUE;
3264 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3265 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3266 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3267 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3269 #endif // DOT11_N_SUPPORT //
3271 // IRQL = DISPATCH_LEVEL
3273 IN PRTMP_ADAPTER pAd)
3275 RT28XX_MLME_RADIO_OFF(pAd);
3278 // IRQL = DISPATCH_LEVEL
3280 IN PRTMP_ADAPTER pAd)
3282 RT28XX_MLME_RADIO_ON(pAd);
3285 // ===========================================================================================
3287 // ===========================================================================================
3290 /*! \brief initialize BSS table
3291 * \param p_tab pointer to the table
3296 IRQL = PASSIVE_LEVEL
3297 IRQL = DISPATCH_LEVEL
3306 Tab->BssOverlapNr = 0;
3307 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3309 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3310 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3314 #ifdef DOT11_N_SUPPORT
3316 IN PRTMP_ADAPTER pAd,
3321 Tab->numAsOriginator = 0;
3322 Tab->numAsRecipient = 0;
3323 NdisAllocateSpinLock(&pAd->BATabLock);
3324 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3326 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3327 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3329 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3331 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3334 #endif // DOT11_N_SUPPORT //
3336 /*! \brief search the BSS table by SSID
3337 * \param p_tab pointer to the bss table
3338 * \param ssid SSID string
3339 * \return index of the table, BSS_NOT_FOUND if not in the table
3342 * \note search by sequential search
3344 IRQL = DISPATCH_LEVEL
3347 ULONG BssTableSearch(
3354 for (i = 0; i < Tab->BssNr; i++)
3357 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3358 // We should distinguish this case.
3360 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3361 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3362 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3367 return (ULONG)BSS_NOT_FOUND;
3370 ULONG BssSsidTableSearch(
3379 for (i = 0; i < Tab->BssNr; i++)
3382 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3383 // We should distinguish this case.
3385 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3386 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3387 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3388 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3393 return (ULONG)BSS_NOT_FOUND;
3396 ULONG BssTableSearchWithSSID(
3405 for (i = 0; i < Tab->BssNr; i++)
3407 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3408 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3409 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3410 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3411 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3412 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3417 return (ULONG)BSS_NOT_FOUND;
3420 // IRQL = DISPATCH_LEVEL
3421 VOID BssTableDeleteEntry(
3422 IN OUT BSS_TABLE *Tab,
3428 for (i = 0; i < Tab->BssNr; i++)
3430 if ((Tab->BssEntry[i].Channel == Channel) &&
3431 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3433 for (j = i; j < Tab->BssNr - 1; j++)
3435 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3437 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3444 #ifdef DOT11_N_SUPPORT
3446 ========================================================================
3447 Routine Description:
3448 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3451 // IRQL = DISPATCH_LEVEL
3452 ========================================================================
3454 VOID BATableDeleteORIEntry(
3455 IN OUT PRTMP_ADAPTER pAd,
3456 IN BA_ORI_ENTRY *pBAORIEntry)
3459 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3461 NdisAcquireSpinLock(&pAd->BATabLock);
3462 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3464 pAd->BATable.numAsOriginator -= 1;
3465 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3466 // Erase Bitmap flag.
3468 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3469 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3470 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3471 pBAORIEntry->Token = 1;
3472 // Not clear Sequence here.
3473 NdisReleaseSpinLock(&pAd->BATabLock);
3476 #endif // DOT11_N_SUPPORT //
3484 IRQL = DISPATCH_LEVEL
3488 IN PRTMP_ADAPTER pAd,
3489 OUT BSS_ENTRY *pBss,
3494 IN USHORT BeaconPeriod,
3495 IN PCF_PARM pCfParm,
3497 IN USHORT CapabilityInfo,
3499 IN UCHAR SupRateLen,
3501 IN UCHAR ExtRateLen,
3502 IN HT_CAPABILITY_IE *pHtCapability,
3503 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3504 IN UCHAR HtCapabilityLen,
3505 IN UCHAR AddHtInfoLen,
3506 IN UCHAR NewExtChanOffset,
3509 IN LARGE_INTEGER TimeStamp,
3511 IN PEDCA_PARM pEdcaParm,
3512 IN PQOS_CAPABILITY_PARM pQosCapability,
3513 IN PQBSS_LOAD_PARM pQbssLoad,
3514 IN USHORT LengthVIE,
3515 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3517 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3518 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3522 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3523 // Or send beacon /probe response with SSID len matching real SSID length,
3524 // but SSID is all zero. such as "00-00-00-00" with length 4.
3525 // We have to prevent this case overwrite correct table
3526 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3528 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3529 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3530 pBss->SsidLen = SsidLen;
3536 pBss->BssType = BssType;
3537 pBss->BeaconPeriod = BeaconPeriod;
3538 if (BssType == BSS_INFRA)
3540 if (pCfParm->bValid)
3542 pBss->CfpCount = pCfParm->CfpCount;
3543 pBss->CfpPeriod = pCfParm->CfpPeriod;
3544 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3545 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3550 pBss->AtimWin = AtimWin;
3553 pBss->CapabilityInfo = CapabilityInfo;
3554 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3555 // Combine with AuthMode, they will decide the connection methods.
3556 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3557 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3558 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3559 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3561 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3562 pBss->SupRateLen = SupRateLen;
3563 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3564 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3565 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3566 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3567 pBss->NewExtChanOffset = NewExtChanOffset;
3568 pBss->ExtRateLen = ExtRateLen;
3569 pBss->Channel = Channel;
3570 pBss->CentralChannel = Channel;
3572 // Update CkipFlag. if not exists, the value is 0x0
3573 pBss->CkipFlag = CkipFlag;
3575 // New for microsoft Fixed IEs
3576 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3577 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3578 pBss->FixIEs.Capabilities = CapabilityInfo;
3580 // New for microsoft Variable IEs
3583 pBss->VarIELen = LengthVIE;
3584 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3591 pBss->AddHtInfoLen = 0;
3592 pBss->HtCapabilityLen = 0;
3593 #ifdef DOT11_N_SUPPORT
3594 if (HtCapabilityLen> 0)
3596 pBss->HtCapabilityLen = HtCapabilityLen;
3597 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3598 if (AddHtInfoLen > 0)
3600 pBss->AddHtInfoLen = AddHtInfoLen;
3601 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3603 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3605 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3607 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3609 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3613 #endif // DOT11_N_SUPPORT //
3615 BssCipherParse(pBss);
3619 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3621 pBss->EdcaParm.bValid = FALSE;
3623 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3625 pBss->QosCapability.bValid = FALSE;
3627 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3629 pBss->QbssLoad.bValid = FALSE;
3631 #ifdef CONFIG_STA_SUPPORT
3632 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3638 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3639 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3641 pEid = (PEID_STRUCT) pVIE;
3643 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3648 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3650 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3652 pBss->WpaIE.IELen = 0;
3655 pBss->WpaIE.IELen = pEid->Len + 2;
3656 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3660 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3662 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3664 pBss->RsnIE.IELen = 0;
3667 pBss->RsnIE.IELen = pEid->Len + 2;
3668 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
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 /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */
3771 if ((SSID_EQUAL(Ssid, SsidLen, Tab->BssEntry[Idx].Ssid, Tab->BssEntry[Idx].SsidLen)) ||
3772 (NdisEqualMemory(Tab->BssEntry[Idx].Ssid, ZeroSsid, Tab->BssEntry[Idx].SsidLen)))
3774 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3775 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3776 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3783 #ifdef CONFIG_STA_SUPPORT
3784 // IRQL = DISPATCH_LEVEL
3785 VOID BssTableSsidSort(
3786 IN PRTMP_ADAPTER pAd,
3787 OUT BSS_TABLE *OutTab,
3792 BssTableInit(OutTab);
3794 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3796 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3797 BOOLEAN bIsHiddenApIncluded = FALSE;
3799 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3800 (pAd->MlmeAux.Channel > 14) &&
3801 RadarChannelCheck(pAd, pInBss->Channel))
3805 bIsHiddenApIncluded = TRUE;
3808 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3809 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3811 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3812 #ifdef DOT11_N_SUPPORT
3813 // 2.4G/5G N only mode
3814 if ((pInBss->HtCapabilityLen == 0) &&
3815 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3817 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3820 #endif // DOT11_N_SUPPORT //
3823 // Check the Authmode first
3824 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3826 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3827 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3831 // Check cipher suite, AP must have more secured cipher than station setting
3832 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3834 // If it's not mixed mode, we should only let BSS pass with the same encryption
3835 if (pInBss->WPA.bMixMode == FALSE)
3836 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3839 // check group cipher
3840 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3843 // check pairwise cipher, skip if none matched
3844 // If profile set to AES, let it pass without question.
3845 // If profile set to TKIP, we must find one mateched
3846 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3847 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3848 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3851 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3853 // If it's not mixed mode, we should only let BSS pass with the same encryption
3854 if (pInBss->WPA2.bMixMode == FALSE)
3855 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3858 // check group cipher
3859 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3862 // check pairwise cipher, skip if none matched
3863 // If profile set to AES, let it pass without question.
3864 // If profile set to TKIP, we must find one mateched
3865 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3866 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3867 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3871 // Bss Type matched, SSID matched.
3872 // We will check wepstatus for qualification Bss
3873 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3875 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3877 // For the SESv2 case, we will not qualify WepStatus.
3883 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3884 // It definitely will fail. So, skip it.
3885 // CCX also require not even try to connect it!!
3889 #ifdef DOT11_N_SUPPORT
3890 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3891 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3892 if ((pInBss->CentralChannel != pInBss->Channel) &&
3893 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3895 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3897 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3899 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3903 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3909 #endif // DOT11_N_SUPPORT //
3911 // copy matching BSS from InTab to OutTab
3912 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3916 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3918 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3921 #ifdef DOT11_N_SUPPORT
3922 // 2.4G/5G N only mode
3923 if ((pInBss->HtCapabilityLen == 0) &&
3924 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3926 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3929 #endif // DOT11_N_SUPPORT //
3932 // Check the Authmode first
3933 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3935 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3936 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3940 // Check cipher suite, AP must have more secured cipher than station setting
3941 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3943 // If it's not mixed mode, we should only let BSS pass with the same encryption
3944 if (pInBss->WPA.bMixMode == FALSE)
3945 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3948 // check group cipher
3949 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3952 // check pairwise cipher, skip if none matched
3953 // If profile set to AES, let it pass without question.
3954 // If profile set to TKIP, we must find one mateched
3955 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3956 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3957 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3960 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3962 // If it's not mixed mode, we should only let BSS pass with the same encryption
3963 if (pInBss->WPA2.bMixMode == FALSE)
3964 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3967 // check group cipher
3968 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3971 // check pairwise cipher, skip if none matched
3972 // If profile set to AES, let it pass without question.
3973 // If profile set to TKIP, we must find one mateched
3974 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3975 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3976 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3980 // Bss Type matched, SSID matched.
3981 // We will check wepstatus for qualification Bss
3982 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3985 #ifdef DOT11_N_SUPPORT
3986 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3987 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3988 if ((pInBss->CentralChannel != pInBss->Channel) &&
3989 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3991 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3993 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3995 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3998 #endif // DOT11_N_SUPPORT //
4000 // copy matching BSS from InTab to OutTab
4001 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4006 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4010 BssTableSortByRssi(OutTab);
4014 // IRQL = DISPATCH_LEVEL
4015 VOID BssTableSortByRssi(
4016 IN OUT BSS_TABLE *OutTab)
4021 for (i = 0; i < OutTab->BssNr - 1; i++)
4023 for (j = i+1; j < OutTab->BssNr; j++)
4025 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4027 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4028 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4029 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4034 #endif // CONFIG_STA_SUPPORT //
4037 VOID BssCipherParse(
4038 IN OUT PBSS_ENTRY pBss)
4042 PRSN_IE_HEADER_STRUCT pRsnHeader;
4043 PCIPHER_SUITE_STRUCT pCipher;
4044 PAKM_SUITE_STRUCT pAKM;
4047 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4050 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4054 pBss->WepStatus = Ndis802_11WEPEnabled;
4058 pBss->WepStatus = Ndis802_11WEPDisabled;
4060 // Set default to disable & open authentication before parsing variable IE
4061 pBss->AuthMode = Ndis802_11AuthModeOpen;
4062 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4065 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4066 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4067 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4068 pBss->WPA.RsnCapability = 0;
4069 pBss->WPA.bMixMode = FALSE;
4071 // Init WPA2 setting
4072 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4073 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4074 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4075 pBss->WPA2.RsnCapability = 0;
4076 pBss->WPA2.bMixMode = FALSE;
4079 Length = (INT) pBss->VarIELen;
4083 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4084 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4085 pEid = (PEID_STRUCT) pTmp;
4089 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4090 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4096 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4097 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4098 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4099 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4102 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4103 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4104 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4107 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4108 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4109 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4115 // if Cisco IE_WPA, break
4118 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4123 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4125 // if unsupported vendor specific IE
4128 // Skip OUI, version, and multicast suite
4129 // This part should be improved in the future when AP supported multiple cipher suite.
4130 // For now, it's OK since almost all APs have fixed cipher suite supported.
4131 // pTmp = (PUCHAR) pEid->Octet;
4134 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4142 // Parse group cipher
4146 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4147 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4150 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4153 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4158 // number of unicast suite
4161 // skip all unicast cipher suites
4162 //Count = *(PUSHORT) pTmp;
4163 Count = (pTmp[1]<<8) + pTmp[0];
4164 pTmp += sizeof(USHORT);
4166 // Parsing all unicast cipher suite
4171 TmpCipher = Ndis802_11WEPDisabled;
4175 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4176 TmpCipher = Ndis802_11Encryption1Enabled;
4179 TmpCipher = Ndis802_11Encryption2Enabled;
4182 TmpCipher = Ndis802_11Encryption3Enabled;
4187 if (TmpCipher > pBss->WPA.PairCipher)
4189 // Move the lower cipher suite to PairCipherAux
4190 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4191 pBss->WPA.PairCipher = TmpCipher;
4195 pBss->WPA.PairCipherAux = TmpCipher;
4201 // 4. get AKM suite counts
4202 //Count = *(PUSHORT) pTmp;
4203 Count = (pTmp[1]<<8) + pTmp[0];
4204 pTmp += sizeof(USHORT);
4210 // Set AP support WPA mode
4211 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4212 pBss->AuthMode = Ndis802_11AuthModeWPA;
4214 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4217 // Set AP support WPA mode
4218 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4219 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4221 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4228 // Fixed for WPA-None
4229 if (pBss->BssType == BSS_ADHOC)
4231 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4232 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4233 pBss->WepStatus = pBss->WPA.GroupCipher;
4234 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4235 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4238 pBss->WepStatus = pBss->WPA.PairCipher;
4240 // Check the Pair & Group, if different, turn on mixed mode flag
4241 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4242 pBss->WPA.bMixMode = TRUE;
4247 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4249 // 0. Version must be 1
4250 if (le2cpu16(pRsnHeader->Version) != 1)
4252 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4254 // 1. Check group cipher
4255 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4256 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4259 // Parse group cipher
4260 switch (pCipher->Type)
4263 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4264 pBss->WPA2.GroupCipher = Ndis802_11Encryption1Enabled;
4267 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4270 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4275 // set to correct offset for next parsing
4276 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4278 // 2. Get pairwise cipher counts
4279 //Count = *(PUSHORT) pTmp;
4280 Count = (pTmp[1]<<8) + pTmp[0];
4281 pTmp += sizeof(USHORT);
4283 // 3. Get pairwise cipher
4284 // Parsing all unicast cipher suite
4288 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4289 TmpCipher = Ndis802_11WEPDisabled;
4290 switch (pCipher->Type)
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->WPA2.PairCipher)
4307 // Move the lower cipher suite to PairCipherAux
4308 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4309 pBss->WPA2.PairCipher = TmpCipher;
4313 pBss->WPA2.PairCipherAux = TmpCipher;
4315 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4319 // 4. get AKM suite counts
4320 //Count = *(PUSHORT) pTmp;
4321 Count = (pTmp[1]<<8) + pTmp[0];
4322 pTmp += sizeof(USHORT);
4324 // 5. Get AKM ciphers
4325 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4326 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4332 // Set AP support WPA mode
4333 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4334 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4336 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4339 // Set AP support WPA mode
4340 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4341 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4343 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4348 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4350 // Fixed for WPA-None
4351 if (pBss->BssType == BSS_ADHOC)
4353 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4354 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4355 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4356 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4357 pBss->WepStatus = pBss->WPA.GroupCipher;
4358 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4359 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4361 pBss->WepStatus = pBss->WPA2.PairCipher;
4363 // 6. Get RSN capability
4364 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4365 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4366 pTmp += sizeof(USHORT);
4368 // Check the Pair & Group, if different, turn on mixed mode flag
4369 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4370 pBss->WPA2.bMixMode = TRUE;
4376 Length -= (pEid->Len + 2);
4380 // ===========================================================================================
4382 // ===========================================================================================
4384 /*! \brief generates a random mac address value for IBSS BSSID
4385 * \param Addr the bssid location
4390 VOID MacAddrRandomBssid(
4391 IN PRTMP_ADAPTER pAd,
4396 for (i = 0; i < MAC_ADDR_LEN; i++)
4398 pAddr[i] = RandomByte(pAd);
4401 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4404 /*! \brief init the management mac frame header
4405 * \param p_hdr mac header
4406 * \param subtype subtype of the frame
4407 * \param p_ds destination address, don't care if it is a broadcast address
4409 * \pre the station has the following information in the pAd->StaCfg
4413 * \note this function initializes the following field
4415 IRQL = PASSIVE_LEVEL
4416 IRQL = DISPATCH_LEVEL
4419 VOID MgtMacHeaderInit(
4420 IN PRTMP_ADAPTER pAd,
4421 IN OUT PHEADER_802_11 pHdr80211,
4427 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4429 pHdr80211->FC.Type = BTYPE_MGMT;
4430 pHdr80211->FC.SubType = SubType;
4431 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4432 // pHdr80211->FC.Type = BTYPE_CNTL;
4433 pHdr80211->FC.ToDs = ToDs;
4434 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4435 #ifdef CONFIG_STA_SUPPORT
4436 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4437 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4438 #endif // CONFIG_STA_SUPPORT //
4439 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4442 // ===========================================================================================
4444 // ===========================================================================================
4446 /*!***************************************************************************
4447 * This routine build an outgoing frame, and fill all information specified
4448 * in argument list to the frame body. The actual frame size is the summation
4451 * Buffer - pointer to a pre-allocated memory segment
4452 * args - a list of <int arg_size, arg> pairs.
4453 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4454 * function will FAIL!!!
4456 * Size of the buffer
4458 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4460 IRQL = PASSIVE_LEVEL
4461 IRQL = DISPATCH_LEVEL
4463 ****************************************************************************/
4464 ULONG MakeOutgoingFrame(
4466 OUT ULONG *FrameLen, ...)
4473 // calculates the total length
4475 va_start(Args, FrameLen);
4478 leng = va_arg(Args, int);
4479 if (leng == END_OF_ARGS)
4483 p = va_arg(Args, PVOID);
4484 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4485 TotLeng = TotLeng + leng;
4488 va_end(Args); /* clean up */
4489 *FrameLen = TotLeng;
4493 // ===========================================================================================
4495 // ===========================================================================================
4497 /*! \brief Initialize The MLME Queue, used by MLME Functions
4498 * \param *Queue The MLME Queue
4499 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4502 * \note Because this is done only once (at the init stage), no need to be locked
4504 IRQL = PASSIVE_LEVEL
4507 NDIS_STATUS MlmeQueueInit(
4508 IN MLME_QUEUE *Queue)
4512 NdisAllocateSpinLock(&Queue->Lock);
4518 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4520 Queue->Entry[i].Occupied = FALSE;
4521 Queue->Entry[i].MsgLen = 0;
4522 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4525 return NDIS_STATUS_SUCCESS;
4528 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4529 * \param *Queue The MLME Queue
4530 * \param Machine The State Machine Id
4531 * \param MsgType The Message Type
4532 * \param MsgLen The Message length
4533 * \param *Msg The message pointer
4534 * \return TRUE if enqueue is successful, FALSE if the queue is full
4537 * \note The message has to be initialized
4539 IRQL = PASSIVE_LEVEL
4540 IRQL = DISPATCH_LEVEL
4543 BOOLEAN MlmeEnqueue(
4544 IN PRTMP_ADAPTER pAd,
4551 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4553 // Do nothing if the driver is starting halt state.
4554 // This might happen when timer already been fired before cancel timer with mlmehalt
4555 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4558 // First check the size, it MUST not exceed the mlme queue size
4559 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4561 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4565 if (MlmeQueueFull(Queue))
4570 NdisAcquireSpinLock(&(Queue->Lock));
4574 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4579 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4580 Queue->Entry[Tail].Occupied = TRUE;
4581 Queue->Entry[Tail].Machine = Machine;
4582 Queue->Entry[Tail].MsgType = MsgType;
4583 Queue->Entry[Tail].MsgLen = MsgLen;
4587 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4590 NdisReleaseSpinLock(&(Queue->Lock));
4594 /*! \brief This function is used when Recv gets a MLME message
4595 * \param *Queue The MLME Queue
4596 * \param TimeStampHigh The upper 32 bit of timestamp
4597 * \param TimeStampLow The lower 32 bit of timestamp
4598 * \param Rssi The receiving RSSI strength
4599 * \param MsgLen The length of the message
4600 * \param *Msg The message pointer
4601 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4605 IRQL = DISPATCH_LEVEL
4608 BOOLEAN MlmeEnqueueForRecv(
4609 IN PRTMP_ADAPTER pAd,
4611 IN ULONG TimeStampHigh,
4612 IN ULONG TimeStampLow,
4621 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4623 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4625 // Do nothing if the driver is starting halt state.
4626 // This might happen when timer already been fired before cancel timer with mlmehalt
4627 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4629 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4633 // First check the size, it MUST not exceed the mlme queue size
4634 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4636 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4640 if (MlmeQueueFull(Queue))
4645 #ifdef CONFIG_STA_SUPPORT
4646 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4648 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4650 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4654 #endif // CONFIG_STA_SUPPORT //
4656 // OK, we got all the informations, it is time to put things into queue
4657 NdisAcquireSpinLock(&(Queue->Lock));
4661 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4665 Queue->Entry[Tail].Occupied = TRUE;
4666 Queue->Entry[Tail].Machine = Machine;
4667 Queue->Entry[Tail].MsgType = MsgType;
4668 Queue->Entry[Tail].MsgLen = MsgLen;
4669 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4670 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4671 Queue->Entry[Tail].Rssi0 = Rssi0;
4672 Queue->Entry[Tail].Rssi1 = Rssi1;
4673 Queue->Entry[Tail].Rssi2 = Rssi2;
4674 Queue->Entry[Tail].Signal = Signal;
4675 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4677 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4681 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4684 NdisReleaseSpinLock(&(Queue->Lock));
4686 RT28XX_MLME_HANDLER(pAd);
4692 /*! \brief Dequeue a message from the MLME Queue
4693 * \param *Queue The MLME Queue
4694 * \param *Elem The message dequeued from MLME Queue
4695 * \return TRUE if the Elem contains something, FALSE otherwise
4699 IRQL = DISPATCH_LEVEL
4702 BOOLEAN MlmeDequeue(
4703 IN MLME_QUEUE *Queue,
4704 OUT MLME_QUEUE_ELEM **Elem)
4706 NdisAcquireSpinLock(&(Queue->Lock));
4707 *Elem = &(Queue->Entry[Queue->Head]);
4710 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4714 NdisReleaseSpinLock(&(Queue->Lock));
4718 // IRQL = DISPATCH_LEVEL
4719 VOID MlmeRestartStateMachine(
4720 IN PRTMP_ADAPTER pAd)
4722 #ifdef CONFIG_STA_SUPPORT
4724 #endif // CONFIG_STA_SUPPORT //
4726 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4729 #ifdef CONFIG_STA_SUPPORT
4730 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4732 // Cancel all timer events
4733 // Be careful to cancel new added timer
4734 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4735 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4736 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4737 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4738 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4739 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4741 #endif // CONFIG_STA_SUPPORT //
4743 // Change back to original channel in case of doing scan
4744 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4745 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4747 // Resume MSDU which is turned off durning scan
4748 RTMPResumeMsduTransmission(pAd);
4750 #ifdef CONFIG_STA_SUPPORT
4751 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4753 // Set all state machines back IDLE
4754 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4755 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4756 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4757 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4758 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4759 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4761 #endif // CONFIG_STA_SUPPORT //
4765 /*! \brief test if the MLME Queue is empty
4766 * \param *Queue The MLME Queue
4767 * \return TRUE if the Queue is empty, FALSE otherwise
4771 IRQL = DISPATCH_LEVEL
4774 BOOLEAN MlmeQueueEmpty(
4775 IN MLME_QUEUE *Queue)
4779 NdisAcquireSpinLock(&(Queue->Lock));
4780 Ans = (Queue->Num == 0);
4781 NdisReleaseSpinLock(&(Queue->Lock));
4786 /*! \brief test if the MLME Queue is full
4787 * \param *Queue The MLME Queue
4788 * \return TRUE if the Queue is empty, FALSE otherwise
4792 IRQL = PASSIVE_LEVEL
4793 IRQL = DISPATCH_LEVEL
4796 BOOLEAN MlmeQueueFull(
4797 IN MLME_QUEUE *Queue)
4801 NdisAcquireSpinLock(&(Queue->Lock));
4802 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4803 NdisReleaseSpinLock(&(Queue->Lock));
4808 /*! \brief The destructor of MLME Queue
4813 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4815 IRQL = PASSIVE_LEVEL
4818 VOID MlmeQueueDestroy(
4819 IN MLME_QUEUE *pQueue)
4821 NdisAcquireSpinLock(&(pQueue->Lock));
4825 NdisReleaseSpinLock(&(pQueue->Lock));
4826 NdisFreeSpinLock(&(pQueue->Lock));
4829 /*! \brief To substitute the message type if the message is coming from external
4830 * \param pFrame The frame received
4831 * \param *Machine The state machine
4832 * \param *MsgType the message type for the state machine
4833 * \return TRUE if the substitution is successful, FALSE otherwise
4837 IRQL = DISPATCH_LEVEL
4840 #ifdef CONFIG_STA_SUPPORT
4841 BOOLEAN MsgTypeSubst(
4842 IN PRTMP_ADAPTER pAd,
4843 IN PFRAME_802_11 pFrame,
4851 // Pointer to start of data frames including SNAP header
4852 pData = (PUCHAR) pFrame + LENGTH_802_11;
4854 // The only data type will pass to this function is EAPOL frame
4855 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4857 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4859 // Cisco Aironet SNAP header
4860 *Machine = AIRONET_STATE_MACHINE;
4861 *MsgType = MT2_AIRONET_MSG;
4865 *Machine = WPA_PSK_STATE_MACHINE;
4866 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4867 return(WpaMsgTypeSubst(EAPType, MsgType));
4871 switch (pFrame->Hdr.FC.SubType)
4873 case SUBTYPE_ASSOC_REQ:
4874 *Machine = ASSOC_STATE_MACHINE;
4875 *MsgType = MT2_PEER_ASSOC_REQ;
4877 case SUBTYPE_ASSOC_RSP:
4878 *Machine = ASSOC_STATE_MACHINE;
4879 *MsgType = MT2_PEER_ASSOC_RSP;
4881 case SUBTYPE_REASSOC_REQ:
4882 *Machine = ASSOC_STATE_MACHINE;
4883 *MsgType = MT2_PEER_REASSOC_REQ;
4885 case SUBTYPE_REASSOC_RSP:
4886 *Machine = ASSOC_STATE_MACHINE;
4887 *MsgType = MT2_PEER_REASSOC_RSP;
4889 case SUBTYPE_PROBE_REQ:
4890 *Machine = SYNC_STATE_MACHINE;
4891 *MsgType = MT2_PEER_PROBE_REQ;
4893 case SUBTYPE_PROBE_RSP:
4894 *Machine = SYNC_STATE_MACHINE;
4895 *MsgType = MT2_PEER_PROBE_RSP;
4897 case SUBTYPE_BEACON:
4898 *Machine = SYNC_STATE_MACHINE;
4899 *MsgType = MT2_PEER_BEACON;
4902 *Machine = SYNC_STATE_MACHINE;
4903 *MsgType = MT2_PEER_ATIM;
4905 case SUBTYPE_DISASSOC:
4906 *Machine = ASSOC_STATE_MACHINE;
4907 *MsgType = MT2_PEER_DISASSOC_REQ;
4910 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4911 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4912 if (Seq == 1 || Seq == 3)
4914 *Machine = AUTH_RSP_STATE_MACHINE;
4915 *MsgType = MT2_PEER_AUTH_ODD;
4917 else if (Seq == 2 || Seq == 4)
4919 *Machine = AUTH_STATE_MACHINE;
4920 *MsgType = MT2_PEER_AUTH_EVEN;
4927 case SUBTYPE_DEAUTH:
4928 *Machine = AUTH_RSP_STATE_MACHINE;
4929 *MsgType = MT2_PEER_DEAUTH;
4931 case SUBTYPE_ACTION:
4932 *Machine = ACTION_STATE_MACHINE;
4933 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4934 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4936 *MsgType = MT2_ACT_INVALID;
4940 *MsgType = (pFrame->Octet[0]&0x7F);
4950 #endif // CONFIG_STA_SUPPORT //
4952 // ===========================================================================================
4954 // ===========================================================================================
4956 /*! \brief Initialize the state machine.
4957 * \param *S pointer to the state machine
4958 * \param Trans State machine transition function
4959 * \param StNr number of states
4960 * \param MsgNr number of messages
4961 * \param DefFunc default function, when there is invalid state/message combination
4962 * \param InitState initial state of the state machine
4963 * \param Base StateMachine base, internal use only
4964 * \pre p_sm should be a legal pointer
4967 IRQL = PASSIVE_LEVEL
4970 VOID StateMachineInit(
4971 IN STATE_MACHINE *S,
4972 IN STATE_MACHINE_FUNC Trans[],
4975 IN STATE_MACHINE_FUNC DefFunc,
4981 // set number of states and messages
4986 S->TransFunc = Trans;
4988 // init all state transition to default function
4989 for (i = 0; i < StNr; i++)
4991 for (j = 0; j < MsgNr; j++)
4993 S->TransFunc[i * MsgNr + j] = DefFunc;
4997 // set the starting state
4998 S->CurrState = InitState;
5001 /*! \brief This function fills in the function pointer into the cell in the state machine
5002 * \param *S pointer to the state machine
5004 * \param Msg incoming message
5005 * \param f the function to be executed when (state, message) combination occurs at the state machine
5006 * \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
5009 IRQL = PASSIVE_LEVEL
5012 VOID StateMachineSetAction(
5013 IN STATE_MACHINE *S,
5016 IN STATE_MACHINE_FUNC Func)
5020 MsgIdx = Msg - S->Base;
5022 if (St < S->NrState && MsgIdx < S->NrMsg)
5024 // boundary checking before setting the action
5025 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5029 /*! \brief This function does the state transition
5030 * \param *Adapter the NIC adapter pointer
5031 * \param *S the state machine
5032 * \param *Elem the message to be executed
5035 IRQL = DISPATCH_LEVEL
5038 VOID StateMachinePerformAction(
5039 IN PRTMP_ADAPTER pAd,
5040 IN STATE_MACHINE *S,
5041 IN MLME_QUEUE_ELEM *Elem)
5043 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5047 ==========================================================================
5049 The drop function, when machine executes this, the message is simply
5050 ignored. This function does nothing, the message is freed in
5051 StateMachinePerformAction()
5052 ==========================================================================
5055 IN PRTMP_ADAPTER pAd,
5056 IN MLME_QUEUE_ELEM *Elem)
5060 // ===========================================================================================
5062 // ===========================================================================================
5065 ==========================================================================
5068 IRQL = PASSIVE_LEVEL
5070 ==========================================================================
5073 IN PRTMP_ADAPTER pAd,
5077 pAd->Mlme.ShiftReg = 1;
5079 pAd->Mlme.ShiftReg = Seed;
5083 ==========================================================================
5085 ==========================================================================
5088 IN PRTMP_ADAPTER pAd)
5095 if (pAd->Mlme.ShiftReg == 0)
5096 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5098 for (i = 0; i < 8; i++)
5100 if (pAd->Mlme.ShiftReg & 0x00000001)
5102 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5107 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5110 R = (R << 1) | Result;
5116 VOID AsicUpdateAutoFallBackTable(
5117 IN PRTMP_ADAPTER pAd,
5118 IN PUCHAR pRateTable)
5121 HT_FBK_CFG0_STRUC HtCfg0;
5122 HT_FBK_CFG1_STRUC HtCfg1;
5123 LG_FBK_CFG0_STRUC LgCfg0;
5124 LG_FBK_CFG1_STRUC LgCfg1;
5125 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5127 // set to initial value
5128 HtCfg0.word = 0x65432100;
5129 HtCfg1.word = 0xedcba988;
5130 LgCfg0.word = 0xedcba988;
5131 LgCfg1.word = 0x00002100;
5133 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5134 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5136 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5137 switch (pCurrTxRate->Mode)
5143 switch(pCurrTxRate->CurrMCS)
5146 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5149 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5152 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5155 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5158 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5161 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5164 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5167 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5172 #ifdef DOT11_N_SUPPORT
5176 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5178 switch(pCurrTxRate->CurrMCS)
5181 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5184 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5187 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5190 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5193 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5196 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5199 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5202 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5205 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5208 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5211 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5214 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5217 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5220 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5223 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5226 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5229 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5234 #endif // DOT11_N_SUPPORT //
5237 pNextTxRate = pCurrTxRate;
5240 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5241 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5242 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5243 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5247 ========================================================================
5249 Routine Description:
5250 Set MAC register value according operation mode.
5251 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5252 If MM or GF mask is not set, those passing argument doesn't not take effect.
5254 Operation mode meaning:
5255 = 0 : Pure HT, no preotection.
5256 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5257 = 0x10: No Transmission in 40M is protected.
5258 = 0x11: Transmission in both 40M and 20M shall be protected
5260 we should choose not to use GF. But still set correct ASIC registers.
5261 ========================================================================
5263 VOID AsicUpdateProtect(
5264 IN PRTMP_ADAPTER pAd,
5265 IN USHORT OperationMode,
5267 IN BOOLEAN bDisableBGProtect,
5268 IN BOOLEAN bNonGFExist)
5270 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5276 #ifdef DOT11_N_SUPPORT
5277 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5282 if (pAd->BATable.numAsOriginator)
5285 // enable the RTS/CTS to avoid channel collision
5287 SetMask = ALLN_SETPROTECT;
5290 #endif // DOT11_N_SUPPORT //
5292 // Config ASIC RTS threshold register
5293 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5294 MacReg &= 0xFF0000FF;
5296 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5298 #ifdef DOT11_N_SUPPORT
5299 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5300 #endif // DOT11_N_SUPPORT //
5301 (pAd->CommonCfg.bAggregationCapable == TRUE))
5302 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5304 MacReg |= (0x1000 << 8);
5308 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5311 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5313 // Initial common protection settings
5314 RTMPZeroMemory(Protect, sizeof(Protect));
5317 ProtCfg.field.TxopAllowGF40 = 1;
5318 ProtCfg.field.TxopAllowGF20 = 1;
5319 ProtCfg.field.TxopAllowMM40 = 1;
5320 ProtCfg.field.TxopAllowMM20 = 1;
5321 ProtCfg.field.TxopAllowOfdm = 1;
5322 ProtCfg.field.TxopAllowCck = 1;
5323 ProtCfg.field.RTSThEn = 1;
5324 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5326 // update PHY mode and rate
5327 if (pAd->CommonCfg.Channel > 14)
5328 ProtCfg.field.ProtectRate = 0x4000;
5329 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5331 // Handle legacy(B/G) protection
5332 if (bDisableBGProtect)
5334 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5335 ProtCfg.field.ProtectCtrl = 0;
5336 Protect[0] = ProtCfg.word;
5337 Protect[1] = ProtCfg.word;
5341 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5342 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5343 Protect[0] = ProtCfg.word;
5344 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5345 Protect[1] = ProtCfg.word;
5348 #ifdef DOT11_N_SUPPORT
5349 // Decide HT frame protection.
5350 if ((SetMask & ALLN_SETPROTECT) != 0)
5352 switch(OperationMode)
5356 // 1.All STAs in the BSS are 20/40 MHz HT
5357 // 2. in ai 20/40MHz BSS
5358 // 3. all STAs are 20MHz in a 20MHz BSS
5359 // Pure HT. no protection.
5363 // PROT_TXOP(25:20) -- 010111
5364 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5365 // PROT_CTRL(17:16) -- 00 (None)
5366 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5367 Protect[2] = 0x01744004;
5371 // PROT_TXOP(25:20) -- 111111
5372 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5373 // PROT_CTRL(17:16) -- 00 (None)
5374 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5375 Protect[3] = 0x03f44084;
5379 // PROT_TXOP(25:20) -- 010111
5380 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5381 // PROT_CTRL(17:16) -- 00 (None)
5382 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5383 Protect[4] = 0x01744004;
5387 // PROT_TXOP(25:20) -- 111111
5388 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5389 // PROT_CTRL(17:16) -- 00 (None)
5390 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5391 Protect[5] = 0x03f44084;
5395 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5396 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5397 Protect[4] = 0x01754004;
5398 Protect[5] = 0x03f54084;
5400 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5404 // This is "HT non-member protection mode."
5405 // If there may be non-HT STAs my BSS
5406 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5407 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5408 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5410 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5411 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5413 //Assign Protection method for 20&40 MHz packets
5414 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5415 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5416 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5417 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5418 Protect[2] = ProtCfg.word;
5419 Protect[3] = ProtCfg4.word;
5420 Protect[4] = ProtCfg.word;
5421 Protect[5] = ProtCfg4.word;
5422 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5426 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5427 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5428 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5430 //Assign Protection method for 40MHz packets
5431 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5432 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5433 Protect[2] = ProtCfg.word;
5434 Protect[3] = ProtCfg4.word;
5437 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5438 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5440 Protect[4] = ProtCfg.word;
5441 Protect[5] = ProtCfg4.word;
5443 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5447 // HT mixed mode. PROTECT ALL!
5449 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5450 ProtCfg4.word = 0x03f44084;
5451 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5452 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5454 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5455 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5457 //Assign Protection method for 20&40 MHz packets
5458 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5459 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5460 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5461 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5462 Protect[2] = ProtCfg.word;
5463 Protect[3] = ProtCfg4.word;
5464 Protect[4] = ProtCfg.word;
5465 Protect[5] = ProtCfg4.word;
5466 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5470 Protect[2] = 0x01754004;
5471 Protect[3] = 0x03f54084;
5472 Protect[4] = 0x01754004;
5473 Protect[5] = 0x03f54084;
5474 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5478 #endif // DOT11_N_SUPPORT //
5480 offset = CCK_PROT_CFG;
5481 for (i = 0;i < 6;i++)
5483 if ((SetMask & (1<< i)))
5485 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5493 ========================================================================
5495 Routine Description: Write RT30xx RF register through MAC
5505 ========================================================================
5507 NTSTATUS RT30xxWriteRFRegister(
5508 IN PRTMP_ADAPTER pAd,
5512 RF_CSR_CFG_STRUC rfcsr;
5517 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5519 if (!rfcsr.field.RF_CSR_KICK)
5523 while ((i < RETRY_LIMIT) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)));
5525 if ((i == RETRY_LIMIT) || (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
5527 DBGPRINT_RAW(RT_DEBUG_ERROR, ("Retry count exhausted or device removed!!!\n"));
5528 return STATUS_UNSUCCESSFUL;
5531 rfcsr.field.RF_CSR_WR = 1;
5532 rfcsr.field.RF_CSR_KICK = 1;
5533 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5534 rfcsr.field.RF_CSR_DATA = Value;
5536 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5538 return STATUS_SUCCESS;
5543 ========================================================================
5545 Routine Description: Read RT30xx RF register through MAC
5555 ========================================================================
5557 NTSTATUS RT30xxReadRFRegister(
5558 IN PRTMP_ADAPTER pAd,
5562 RF_CSR_CFG_STRUC rfcsr;
5565 for (i=0; i<MAX_BUSY_COUNT; i++)
5567 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5569 if (rfcsr.field.RF_CSR_KICK == BUSY)
5574 rfcsr.field.RF_CSR_WR = 0;
5575 rfcsr.field.RF_CSR_KICK = 1;
5576 rfcsr.field.TESTCSR_RFACC_REGNUM = RegID;
5577 RTMP_IO_WRITE32(pAd, RF_CSR_CFG, rfcsr.word);
5578 for (k=0; k<MAX_BUSY_COUNT; k++)
5580 RTMP_IO_READ32(pAd, RF_CSR_CFG, &rfcsr.word);
5582 if (rfcsr.field.RF_CSR_KICK == IDLE)
5585 if ((rfcsr.field.RF_CSR_KICK == IDLE) &&
5586 (rfcsr.field.TESTCSR_RFACC_REGNUM == RegID))
5588 *pValue = (UCHAR)rfcsr.field.RF_CSR_DATA;
5592 if (rfcsr.field.RF_CSR_KICK == BUSY)
5594 DBGPRINT_ERR(("RF read R%d=0x%x fail, i[%d], k[%d]\n", RegID, rfcsr.word,i,k));
5595 return STATUS_UNSUCCESSFUL;
5598 return STATUS_SUCCESS;
5603 // add by johnli, RF power sequence setup
5605 ==========================================================================
5608 Load RF normal operation-mode setup
5610 ==========================================================================
5612 VOID RT30xxLoadRFNormalModeSetup(
5613 IN PRTMP_ADAPTER pAd)
5617 // RX0_PD & TX0_PD, RF R1 register Bit 2 & Bit 3 to 0 and RF_BLOCK_en,RX1_PD & TX1_PD, Bit0, Bit 4 & Bit5 to 1
5618 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5619 RFValue = (RFValue & (~0x0C)) | 0x31;
5620 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5622 // TX_LO2_en, RF R15 register Bit 3 to 0
5623 RT30xxReadRFRegister(pAd, RF_R15, &RFValue);
5625 RT30xxWriteRFRegister(pAd, RF_R15, RFValue);
5627 // TX_LO1_en, RF R17 register Bit 3 to 0
5628 RT30xxReadRFRegister(pAd, RF_R17, &RFValue);
5630 // to fix rx long range issue
5631 if (((pAd->MACVersion & 0xffff) >= 0x0211) && (pAd->NicConfig2.field.ExternalLNAForG == 0))
5635 RT30xxWriteRFRegister(pAd, RF_R17, RFValue);
5637 // RX_LO1_en, RF R20 register Bit 3 to 0
5638 RT30xxReadRFRegister(pAd, RF_R20, &RFValue);
5640 RT30xxWriteRFRegister(pAd, RF_R20, RFValue);
5642 // RX_LO2_en, RF R21 register Bit 3 to 0
5643 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5645 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5647 // LDORF_VC, RF R27 register Bit 2 to 0
5648 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5649 if ((pAd->MACVersion & 0xffff) < 0x0211)
5650 RFValue = (RFValue & (~0x77)) | 0x3;
5652 RFValue = (RFValue & (~0x77));
5653 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5658 ==========================================================================
5661 Load RF sleep-mode setup
5663 ==========================================================================
5665 VOID RT30xxLoadRFSleepModeSetup(
5666 IN PRTMP_ADAPTER pAd)
5671 // RF_BLOCK_en. RF R1 register Bit 0 to 0
5672 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5674 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5676 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 0
5677 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5679 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5681 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 0
5682 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5684 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5686 // RX_CTB_en, RF R21 register Bit 7 to 0
5687 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5689 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5691 // LDORF_VC, RF R27 register Bit 0, Bit 1 & Bit 2 to 1
5692 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5694 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5696 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5697 MACValue |= 0x1D000000;
5698 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5702 ==========================================================================
5705 Reverse RF sleep-mode setup
5707 ==========================================================================
5709 VOID RT30xxReverseRFSleepModeSetup(
5710 IN PRTMP_ADAPTER pAd)
5715 // RF_BLOCK_en, RF R1 register Bit 0 to 1
5716 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5718 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5720 // VCO_IC, RF R7 register Bit 4 & Bit 5 to 1
5721 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5723 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5725 // Idoh, RF R9 register Bit 1, Bit 2 & Bit 3 to 1
5726 RT30xxReadRFRegister(pAd, RF_R09, &RFValue);
5728 RT30xxWriteRFRegister(pAd, RF_R09, RFValue);
5730 // RX_CTB_en, RF R21 register Bit 7 to 1
5731 RT30xxReadRFRegister(pAd, RF_R21, &RFValue);
5733 RT30xxWriteRFRegister(pAd, RF_R21, RFValue);
5735 // LDORF_VC, RF R27 register Bit 2 to 0
5736 RT30xxReadRFRegister(pAd, RF_R27, &RFValue);
5737 if ((pAd->MACVersion & 0xffff) < 0x0211)
5738 RFValue = (RFValue & (~0x77)) | 0x3;
5740 RFValue = (RFValue & (~0x77));
5741 RT30xxWriteRFRegister(pAd, RF_R27, RFValue);
5743 // RT3071 version E has fixed this issue
5744 if ((pAd->NicConfig2.field.DACTestBit == 1) && ((pAd->MACVersion & 0xffff) < 0x0211))
5746 // patch tx EVM issue temporarily
5747 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5748 MACValue = ((MACValue & 0xE0FFFFFF) | 0x0D000000);
5749 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5753 RTMP_IO_READ32(pAd, LDO_CFG0, &MACValue);
5754 MACValue = ((MACValue & 0xE0FFFFFF) | 0x01000000);
5755 RTMP_IO_WRITE32(pAd, LDO_CFG0, MACValue);
5762 ==========================================================================
5765 IRQL = PASSIVE_LEVEL
5766 IRQL = DISPATCH_LEVEL
5768 ==========================================================================
5770 VOID AsicSwitchChannel(
5771 IN PRTMP_ADAPTER pAd,
5775 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5776 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5778 UINT32 Value = 0; //BbpReg, Value;
5779 RTMP_RF_REGS *RFRegTable;
5781 // Search Tx power value
5783 // We can't use ChannelList to search channel, since some central channl's txpowr doesn't list
5784 // in ChannelList, so use TxPower array instead.
5786 for (index = 0; index < MAX_NUM_OF_CHANNELS; index++)
5788 if (Channel == pAd->TxPower[index].Channel)
5790 TxPwer = pAd->TxPower[index].Power;
5791 TxPwer2 = pAd->TxPower[index].Power2;
5796 for (index = 0; index < pAd->ChannelListNum; index++)
5798 if (Channel == pAd->ChannelList[index].Channel)
5800 TxPwer = pAd->ChannelList[index].Power;
5801 TxPwer2 = pAd->ChannelList[index].Power2;
5807 if (index == MAX_NUM_OF_CHANNELS)
5809 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Can't find the Channel#%d \n", Channel));
5813 // The RF programming sequence is difference between 3xxx and 2xxx
5814 if ((IS_RT3070(pAd) || IS_RT3090(pAd)) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020) ||
5815 (pAd->RfIcType == RFIC_3021) || (pAd->RfIcType == RFIC_3022)))
5817 /* modify by WY for Read RF Reg. error */
5820 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5822 if (Channel == FreqItems3020[index].Channel)
5824 // Programming channel parameters
5825 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5826 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5827 RT30xxReadRFRegister(pAd, RF_R06, &RFValue);
5828 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5829 RT30xxWriteRFRegister(pAd, RF_R06, RFValue);
5832 RT30xxReadRFRegister(pAd, RF_R12, &RFValue);
5833 RFValue = (RFValue & 0xE0) | TxPwer;
5834 RT30xxWriteRFRegister(pAd, RF_R12, RFValue);
5837 RT30xxReadRFRegister(pAd, RF_R13, &RFValue);
5838 RFValue = (RFValue & 0xE0) | TxPwer2;
5839 RT30xxWriteRFRegister(pAd, RF_R13, RFValue);
5841 // Tx/Rx Stream setting
5842 RT30xxReadRFRegister(pAd, RF_R01, &RFValue);
5843 //if (IS_RT3090(pAd))
5844 // RFValue |= 0x01; // Enable RF block.
5845 RFValue &= 0x03; //clear bit[7~2]
5846 if (pAd->Antenna.field.TxPath == 1)
5848 else if (pAd->Antenna.field.TxPath == 2)
5850 if (pAd->Antenna.field.RxPath == 1)
5852 else if (pAd->Antenna.field.RxPath == 2)
5854 RT30xxWriteRFRegister(pAd, RF_R01, RFValue);
5857 RT30xxReadRFRegister(pAd, RF_R23, &RFValue);
5858 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5859 RT30xxWriteRFRegister(pAd, RF_R23, RFValue);
5862 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5864 RFValue = pAd->Mlme.CaliBW40RfR24;
5865 //DISABLE_11N_CHECK(pAd);
5869 RFValue = pAd->Mlme.CaliBW20RfR24;
5871 RT30xxWriteRFRegister(pAd, RF_R24, RFValue);
5872 RT30xxWriteRFRegister(pAd, RF_R31, RFValue);
5875 RT30xxReadRFRegister(pAd, RF_R07, &RFValue);
5876 RFValue = RFValue | 0x1;
5877 RT30xxWriteRFRegister(pAd, RF_R07, RFValue);
5879 // latch channel for future usage.
5880 pAd->LatchRfRegs.Channel = Channel;
5882 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5887 pAd->Antenna.field.TxPath,
5888 FreqItems3020[index].N,
5889 FreqItems3020[index].K,
5890 FreqItems3020[index].R));
5900 RFRegTable = RF2850RegTable;
5902 switch (pAd->RfIcType)
5909 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5911 if (Channel == RFRegTable[index].Channel)
5913 R2 = RFRegTable[index].R2;
5914 if (pAd->Antenna.field.TxPath == 1)
5916 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5919 if (pAd->Antenna.field.RxPath == 2)
5921 R2 |= 0x40; // write 1 to off Rxpath.
5923 else if (pAd->Antenna.field.RxPath == 1)
5925 R2 |= 0x20040; // write 1 to off RxPath
5930 // initialize R3, R4
5931 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5932 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5934 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5936 if ((TxPwer >= -7) && (TxPwer < 0))
5938 TxPwer = (7+TxPwer);
5939 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5940 R3 |= (TxPwer << 10);
5941 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5945 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5946 R3 |= (TxPwer << 10) | (1 << 9);
5950 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5952 TxPwer2 = (7+TxPwer2);
5953 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5954 R4 |= (TxPwer2 << 7);
5955 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5959 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5960 R4 |= (TxPwer2 << 7) | (1 << 6);
5965 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5966 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5969 // Based on BBP current mode before changing RF channel.
5970 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5976 pAd->LatchRfRegs.Channel = Channel;
5977 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5978 pAd->LatchRfRegs.R2 = R2;
5979 pAd->LatchRfRegs.R3 = R3;
5980 pAd->LatchRfRegs.R4 = R4;
5982 // Set RF value 1's set R3[bit2] = [0]
5983 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5984 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5985 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5986 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5990 // Set RF value 2's set R3[bit2] = [1]
5991 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5992 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5993 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5994 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5998 // Set RF value 3's set R3[bit2] = [0]
5999 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
6000 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
6001 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
6002 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
6014 // Change BBP setting during siwtch from a->g, g->a
6017 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
6019 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6020 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6021 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6022 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.
6023 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6025 // Rx High power VGA offset for LNA select
6026 if (pAd->NicConfig2.field.ExternalLNAForG)
6028 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
6029 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6033 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
6034 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6037 // 5G band selection PIN, bit1 and bit2 are complement
6038 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6041 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6043 // Turn off unused PA or LNA when only 1T or 1R
6044 if (pAd->Antenna.field.TxPath == 1)
6046 TxPinCfg &= 0xFFFFFFF3;
6048 if (pAd->Antenna.field.RxPath == 1)
6050 TxPinCfg &= 0xFFFFF3FF;
6053 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6057 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6059 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6060 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6061 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6062 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.
6063 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6065 // Rx High power VGA offset for LNA select
6066 if (pAd->NicConfig2.field.ExternalLNAForA)
6068 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6072 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
6075 // 5G band selection PIN, bit1 and bit2 are complement
6076 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6079 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6081 // Turn off unused PA or LNA when only 1T or 1R
6082 if (pAd->Antenna.field.TxPath == 1)
6084 TxPinCfg &= 0xFFFFFFF3;
6086 if (pAd->Antenna.field.RxPath == 1)
6088 TxPinCfg &= 0xFFFFF3FF;
6091 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6094 // R66 should be set according to Channel and use 20MHz when scanning
6095 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6097 RTMPSetAGCInitValue(pAd, BW_20);
6099 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6102 // On 11A, We should delay and wait RF/BBP to be stable
6103 // and the appropriate time should be 1000 micro seconds
6104 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6106 RTMPusecDelay(1000);
6108 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",
6111 (R3 & 0x00003e00) >> 9,
6112 (R4 & 0x000007c0) >> 6,
6113 pAd->Antenna.field.TxPath,
6114 pAd->LatchRfRegs.R1,
6115 pAd->LatchRfRegs.R2,
6116 pAd->LatchRfRegs.R3,
6117 pAd->LatchRfRegs.R4));
6121 ==========================================================================
6123 This function is required for 2421 only, and should not be used during
6124 site survey. It's only required after NIC decided to stay at a channel
6125 for a longer period.
6126 When this function is called, it's always after AsicSwitchChannel().
6128 IRQL = PASSIVE_LEVEL
6129 IRQL = DISPATCH_LEVEL
6131 ==========================================================================
6133 VOID AsicLockChannel(
6134 IN PRTMP_ADAPTER pAd,
6140 ==========================================================================
6143 IRQL = PASSIVE_LEVEL
6144 IRQL = DISPATCH_LEVEL
6146 ==========================================================================
6148 VOID AsicAntennaSelect(
6149 IN PRTMP_ADAPTER pAd,
6152 if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
6154 // patch for AsicSetRxAnt failed
6155 pAd->RxAnt.EvaluatePeriod = 0;
6157 // check every 2 second. If rcv-beacon less than 5 in the past 2 second, then AvgRSSI is no longer a
6158 // valid indication of the distance between this AP and its clients.
6159 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
6163 // if no traffic then reset average rssi to trigger evaluation
6164 #ifdef CONFIG_STA_SUPPORT
6165 if (pAd->StaCfg.NumOfAvgRssiSample < 5)
6167 pAd->RxAnt.Pair1LastAvgRssi = (-99);
6168 pAd->RxAnt.Pair2LastAvgRssi = (-99);
6169 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no traffic/beacon, reset RSSI\n"));
6172 pAd->StaCfg.NumOfAvgRssiSample = 0;
6173 #endif // CONFIG_STA_SUPPORT //
6174 realavgrssi1 = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt] >> 3);
6176 DBGPRINT(RT_DEBUG_TRACE,("Ant-realrssi0(%d), Lastrssi0(%d), EvaluateStableCnt=%d\n", realavgrssi1, pAd->RxAnt.Pair1LastAvgRssi, pAd->RxAnt.EvaluateStableCnt));
6178 // if the difference between two rssi is larger or less than 5, then evaluate the other antenna
6179 if ((pAd->RxAnt.EvaluateStableCnt < 2) || (realavgrssi1 > (pAd->RxAnt.Pair1LastAvgRssi + 5)) || (realavgrssi1 < (pAd->RxAnt.Pair1LastAvgRssi - 5)))
6181 pAd->RxAnt.Pair1LastAvgRssi = realavgrssi1;
6182 AsicEvaluateRxAnt(pAd);
6187 // if not connected, always switch antenna to try to connect
6190 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
6191 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
6192 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
6194 DBGPRINT(RT_DEBUG_TRACE, ("MlmePeriodicExec: no connect, switch to another one to try connection\n"));
6196 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
6202 ========================================================================
6204 Routine Description:
6205 Antenna miscellaneous setting.
6208 pAd Pointer to our adapter
6209 BandState Indicate current Band State.
6214 IRQL <= DISPATCH_LEVEL
6217 1.) Frame End type control
6218 only valid for G only (RF_2527 & RF_2529)
6219 0: means DPDT, set BBP R4 bit 5 to 1
6220 1: means SPDT, set BBP R4 bit 5 to 0
6223 ========================================================================
6225 VOID AsicAntennaSetting(
6226 IN PRTMP_ADAPTER pAd,
6227 IN ABGBAND_STATE BandState)
6231 VOID AsicRfTuningExec(
6232 IN PVOID SystemSpecific1,
6233 IN PVOID FunctionContext,
6234 IN PVOID SystemSpecific2,
6235 IN PVOID SystemSpecific3)
6240 ==========================================================================
6242 Gives CCK TX rate 2 more dB TX power.
6243 This routine works only in LINK UP in INFRASTRUCTURE mode.
6245 calculate desired Tx power in RF R3.Tx0~5, should consider -
6246 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6247 1. TxPowerPercentage
6248 2. auto calibration based on TSSI feedback
6249 3. extra 2 db for CCK
6250 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6252 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6253 it should be called AFTER MlmeDynamicTxRatSwitching()
6254 ==========================================================================
6256 VOID AsicAdjustTxPower(
6257 IN PRTMP_ADAPTER pAd)
6261 BOOLEAN bAutoTxAgc = FALSE;
6262 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6263 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6264 PCHAR pTxAgcCompensate;
6270 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6272 if (pAd->CommonCfg.CentralChannel > 14)
6274 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6275 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6276 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6277 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6278 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6282 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6283 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6284 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6285 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6286 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6291 if (pAd->CommonCfg.Channel > 14)
6293 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6294 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6295 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6296 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6297 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6301 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6302 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6303 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6304 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6305 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6309 // TX power compensation for temperature variation based on TSSI. try every 4 second
6310 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6312 if (pAd->CommonCfg.Channel <= 14)
6315 bAutoTxAgc = pAd->bAutoTxAgcG;
6316 TssiRef = pAd->TssiRefG;
6317 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6318 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6319 TxAgcStep = pAd->TxAgcStepG;
6320 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6325 bAutoTxAgc = pAd->bAutoTxAgcA;
6326 TssiRef = pAd->TssiRefA;
6327 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6328 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6329 TxAgcStep = pAd->TxAgcStepA;
6330 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6335 /* BbpR1 is unsigned char */
6336 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6338 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6339 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6340 /* step value is defined in pAd->TxAgcStepG for tx power value */
6342 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6343 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6344 above value are examined in mass factory production */
6345 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6347 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6348 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6349 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6351 if (BbpR49 > pTssiMinusBoundary[1])
6353 // Reading is larger than the reference value
6354 // check for how large we need to decrease the Tx power
6355 for (idx = 1; idx < 5; idx++)
6357 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6360 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6361 // if (R3 > (ULONG) (TxAgcStep * (idx-1)))
6362 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6364 // *pTxAgcCompensate = -((UCHAR)R3);
6366 DeltaPwr += (*pTxAgcCompensate);
6367 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6368 BbpR49, TssiRef, TxAgcStep, idx-1));
6370 else if (BbpR49 < pTssiPlusBoundary[1])
6372 // Reading is smaller than the reference value
6373 // check for how large we need to increase the Tx power
6374 for (idx = 1; idx < 5; idx++)
6376 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6379 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6380 *pTxAgcCompensate = TxAgcStep * (idx-1);
6381 DeltaPwr += (*pTxAgcCompensate);
6382 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6383 BbpR49, TssiRef, TxAgcStep, idx-1));
6387 *pTxAgcCompensate = 0;
6388 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6389 BbpR49, TssiRef, TxAgcStep, 0));
6395 if (pAd->CommonCfg.Channel <= 14)
6397 bAutoTxAgc = pAd->bAutoTxAgcG;
6398 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6402 bAutoTxAgc = pAd->bAutoTxAgcA;
6403 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6407 DeltaPwr += (*pTxAgcCompensate);
6410 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6413 /* calculate delta power based on the percentage specified from UI */
6414 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6415 // We lower TX power here according to the percentage specified from UI
6416 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6418 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6420 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6424 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6428 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6432 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6437 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6442 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6444 /* reset different new tx power for different TX rate */
6447 if (TxPwr[i] != 0xffffffff)
6451 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6453 if ((Value + DeltaPwr) < 0)
6455 Value = 0; /* min */
6457 else if ((Value + DeltaPwr) > 0xF)
6459 Value = 0xF; /* max */
6463 Value += DeltaPwr; /* temperature compensation */
6466 /* fill new value to CSR offset */
6467 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6470 /* write tx power value to CSR */
6471 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6472 TX power for OFDM 6M/9M
6473 TX power for CCK5.5M/11M
6474 TX power for CCK1M/2M */
6475 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6476 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6483 #ifdef CONFIG_STA_SUPPORT
6485 ==========================================================================
6487 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6488 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6489 the wakeup timer timeout. Driver has to issue a separate command to wake
6492 IRQL = DISPATCH_LEVEL
6494 ==========================================================================
6496 VOID AsicSleepThenAutoWakeup(
6497 IN PRTMP_ADAPTER pAd,
6498 IN USHORT TbttNumToNextWakeUp)
6500 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6504 ==========================================================================
6506 AsicForceWakeup() is used whenever manual wakeup is required
6507 AsicForceSleep() should only be used when not in INFRA BSS. When
6508 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6509 ==========================================================================
6511 VOID AsicForceSleep(
6512 IN PRTMP_ADAPTER pAd)
6518 ==========================================================================
6520 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6523 IRQL = PASSIVE_LEVEL
6524 IRQL = DISPATCH_LEVEL
6525 ==========================================================================
6527 VOID AsicForceWakeup(
6528 IN PRTMP_ADAPTER pAd,
6531 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6532 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6534 #endif // CONFIG_STA_SUPPORT //
6536 ==========================================================================
6540 IRQL = DISPATCH_LEVEL
6542 ==========================================================================
6545 IN PRTMP_ADAPTER pAd,
6549 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6550 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6552 Addr4 = (ULONG)(pBssid[0]) |
6553 (ULONG)(pBssid[1] << 8) |
6554 (ULONG)(pBssid[2] << 16) |
6555 (ULONG)(pBssid[3] << 24);
6556 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6559 // always one BSSID in STA mode
6560 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6562 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6565 VOID AsicSetMcastWC(
6566 IN PRTMP_ADAPTER pAd)
6568 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6571 pEntry->Sst = SST_ASSOC;
6572 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6573 pEntry->PsMode = PWR_ACTIVE;
6574 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6575 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6579 ==========================================================================
6582 IRQL = DISPATCH_LEVEL
6584 ==========================================================================
6586 VOID AsicDelWcidTab(
6587 IN PRTMP_ADAPTER pAd,
6590 ULONG Addr0 = 0x0, Addr1 = 0x0;
6593 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6594 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6595 RTMP_IO_WRITE32(pAd, offset, Addr0);
6597 RTMP_IO_WRITE32(pAd, offset, Addr1);
6601 ==========================================================================
6604 IRQL = DISPATCH_LEVEL
6606 ==========================================================================
6609 IN PRTMP_ADAPTER pAd)
6611 TX_LINK_CFG_STRUC TxLinkCfg;
6614 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6615 TxLinkCfg.field.TxRDGEn = 1;
6616 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6618 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6621 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6623 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6627 ==========================================================================
6630 IRQL = DISPATCH_LEVEL
6632 ==========================================================================
6634 VOID AsicDisableRDG(
6635 IN PRTMP_ADAPTER pAd)
6637 TX_LINK_CFG_STRUC TxLinkCfg;
6641 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6642 TxLinkCfg.field.TxRDGEn = 0;
6643 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6645 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6650 //if ( pAd->CommonCfg.bEnableTxBurst )
6651 // Data |= 0x60; // for performance issue not set the TXOP to 0
6653 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6654 #ifdef DOT11_N_SUPPORT
6655 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6656 #endif // DOT11_N_SUPPORT //
6659 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6660 if (pAd->CommonCfg.bEnableTxBurst)
6663 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6667 ==========================================================================
6670 IRQL = PASSIVE_LEVEL
6671 IRQL = DISPATCH_LEVEL
6673 ==========================================================================
6675 VOID AsicDisableSync(
6676 IN PRTMP_ADAPTER pAd)
6678 BCN_TIME_CFG_STRUC csr;
6680 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6682 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6683 // that NIC will never wakes up because TSF stops and no more
6685 pAd->TbttTickCount = 0;
6686 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6687 csr.field.bBeaconGen = 0;
6688 csr.field.bTBTTEnable = 0;
6689 csr.field.TsfSyncMode = 0;
6690 csr.field.bTsfTicking = 0;
6691 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6696 ==========================================================================
6699 IRQL = DISPATCH_LEVEL
6701 ==========================================================================
6703 VOID AsicEnableBssSync(
6704 IN PRTMP_ADAPTER pAd)
6706 BCN_TIME_CFG_STRUC csr;
6708 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6710 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6711 // RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);
6712 #ifdef CONFIG_STA_SUPPORT
6713 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6715 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6716 csr.field.bTsfTicking = 1;
6717 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6718 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6719 csr.field.bTBTTEnable = 1;
6721 #endif // CONFIG_STA_SUPPORT //
6722 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6726 ==========================================================================
6729 BEACON frame in shared memory should be built ok before this routine
6730 can be called. Otherwise, a garbage frame maybe transmitted out every
6733 IRQL = DISPATCH_LEVEL
6735 ==========================================================================
6737 VOID AsicEnableIbssSync(
6738 IN PRTMP_ADAPTER pAd)
6740 BCN_TIME_CFG_STRUC csr9;
6744 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6746 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6747 csr9.field.bBeaconGen = 0;
6748 csr9.field.bTBTTEnable = 0;
6749 csr9.field.bTsfTicking = 0;
6750 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6754 // move BEACON TXD and frame content to on-chip memory
6755 ptr = (PUCHAR)&pAd->BeaconTxWI;
6756 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6758 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6759 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6760 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6764 // start right after the 16-byte TXWI field
6765 ptr = pAd->BeaconBuf;
6766 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6768 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6769 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6770 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6776 // For Wi-Fi faily generated beacons between participating stations.
6777 // Set TBTT phase adaptive adjustment step to 8us (default 16us)
6778 // don't change settings 2006-5- by Jerry
6779 //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);
6781 // start sending BEACON
6782 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6783 csr9.field.bTsfTicking = 1;
6784 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6785 csr9.field.bTBTTEnable = 1;
6786 csr9.field.bBeaconGen = 1;
6787 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6791 ==========================================================================
6794 IRQL = PASSIVE_LEVEL
6795 IRQL = DISPATCH_LEVEL
6797 ==========================================================================
6799 VOID AsicSetEdcaParm(
6800 IN PRTMP_ADAPTER pAd,
6801 IN PEDCA_PARM pEdcaParm)
6803 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6804 AC_TXOP_CSR0_STRUC csr0;
6805 AC_TXOP_CSR1_STRUC csr1;
6806 AIFSN_CSR_STRUC AifsnCsr;
6807 CWMIN_CSR_STRUC CwminCsr;
6808 CWMAX_CSR_STRUC CwmaxCsr;
6815 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6817 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6818 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6819 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6821 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6822 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6825 //========================================================
6826 // MAC Register has a copy .
6827 //========================================================
6829 if( pAd->CommonCfg.bEnableTxBurst )
6831 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6832 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6835 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6837 // Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6839 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6840 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6841 Ac0Cfg.field.Aifsn = 2;
6842 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6844 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6845 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6846 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6847 Ac1Cfg.field.Aifsn = 2;
6848 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6850 if (pAd->CommonCfg.PhyMode == PHY_11B)
6852 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6853 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6857 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6858 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6860 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6861 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6862 Ac2Cfg.field.Aifsn = 2;
6863 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6864 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6865 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6866 Ac3Cfg.field.Aifsn = 2;
6867 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6869 //========================================================
6870 // DMA Register has a copy too.
6871 //========================================================
6872 csr0.field.Ac0Txop = 0; // QID_AC_BE
6873 csr0.field.Ac1Txop = 0; // QID_AC_BK
6874 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6875 if (pAd->CommonCfg.PhyMode == PHY_11B)
6877 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6878 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6882 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6883 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6885 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6888 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6889 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6890 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6891 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6892 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6895 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6896 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6897 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6898 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6899 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6901 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6903 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6907 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6908 //========================================================
6909 // MAC Register has a copy.
6910 //========================================================
6912 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6913 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6915 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6917 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6918 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6919 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6920 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6922 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6923 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6924 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6925 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6927 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6928 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6929 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6930 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6931 #ifdef INF_AMAZON_SE
6932 #endif // INF_AMAZON_SE //
6935 #ifdef CONFIG_STA_SUPPORT
6936 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6938 // Tuning for Wi-Fi WMM S06
6939 if (pAd->CommonCfg.bWiFiTest &&
6940 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6941 Ac2Cfg.field.Aifsn -= 1;
6943 // Tuning for TGn Wi-Fi 5.2.32
6944 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6945 if (STA_TGN_WIFI_ON(pAd) &&
6946 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6948 Ac0Cfg.field.Aifsn = 3;
6949 Ac2Cfg.field.AcTxop = 5;
6953 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
6955 // Tuning for WiFi WMM S3-T07: connexant legacy sta ==> broadcom 11n sta.
6956 Ac2Cfg.field.Aifsn = 5;
6960 #endif // CONFIG_STA_SUPPORT //
6962 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6963 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6964 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6965 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6968 if (pAd->CommonCfg.bWiFiTest)
6970 if (Ac3Cfg.field.AcTxop == 102)
6972 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6973 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6974 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6975 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6976 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6979 //#endif // WIFI_TEST //
6981 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6982 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6983 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6984 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6987 //========================================================
6988 // DMA Register has a copy too.
6989 //========================================================
6990 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6991 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6992 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6994 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6995 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6996 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6999 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
7000 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
7001 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
7002 #ifdef CONFIG_STA_SUPPORT
7003 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7004 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
7005 #endif // CONFIG_STA_SUPPORT //
7006 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
7009 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
7010 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7011 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7012 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7013 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7016 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7017 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7018 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7019 #ifdef INF_AMAZON_SE
7020 #endif // INF_AMAZON_SE //
7023 #ifdef CONFIG_STA_SUPPORT
7024 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7026 // Tuning for Wi-Fi WMM S06
7027 if (pAd->CommonCfg.bWiFiTest &&
7028 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7029 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7031 // Tuning for TGn Wi-Fi 5.2.32
7032 // STA TestBed changes in this item: connexant legacy sta ==> broadcom 11n sta
7033 if (STA_TGN_WIFI_ON(pAd) &&
7034 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7036 AifsnCsr.field.Aifsn0 = 3;
7037 AifsnCsr.field.Aifsn2 = 7;
7041 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7043 #endif // CONFIG_STA_SUPPORT //
7045 #ifdef CONFIG_STA_SUPPORT
7046 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7047 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7049 if (pAd->RfIcType == RFIC_3020 || pAd->RfIcType == RFIC_2020)
7051 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7052 AifsnCsr.field.Aifsn2 = 0x2; //pEdcaParm->Aifsn[QID_AC_VI]; //for WiFi WMM S4-T04.
7055 #endif // CONFIG_STA_SUPPORT //
7056 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7058 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7061 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7062 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7063 pEdcaParm->Aifsn[0],
7064 pEdcaParm->Cwmin[0],
7065 pEdcaParm->Cwmax[0],
7066 pEdcaParm->Txop[0]<<5,
7067 pEdcaParm->bACM[0]));
7068 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7069 pEdcaParm->Aifsn[1],
7070 pEdcaParm->Cwmin[1],
7071 pEdcaParm->Cwmax[1],
7072 pEdcaParm->Txop[1]<<5,
7073 pEdcaParm->bACM[1]));
7074 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7075 pEdcaParm->Aifsn[2],
7076 pEdcaParm->Cwmin[2],
7077 pEdcaParm->Cwmax[2],
7078 pEdcaParm->Txop[2]<<5,
7079 pEdcaParm->bACM[2]));
7080 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7081 pEdcaParm->Aifsn[3],
7082 pEdcaParm->Cwmin[3],
7083 pEdcaParm->Cwmax[3],
7084 pEdcaParm->Txop[3]<<5,
7085 pEdcaParm->bACM[3]));
7091 ==========================================================================
7094 IRQL = PASSIVE_LEVEL
7095 IRQL = DISPATCH_LEVEL
7097 ==========================================================================
7099 VOID AsicSetSlotTime(
7100 IN PRTMP_ADAPTER pAd,
7101 IN BOOLEAN bUseShortSlotTime)
7104 UINT32 RegValue = 0;
7106 #ifdef CONFIG_STA_SUPPORT
7107 if (pAd->CommonCfg.Channel > 14)
7108 bUseShortSlotTime = TRUE;
7109 #endif // CONFIG_STA_SUPPORT //
7111 if (bUseShortSlotTime)
7112 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7114 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7116 SlotTime = (bUseShortSlotTime)? 9 : 20;
7118 #ifdef CONFIG_STA_SUPPORT
7119 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7121 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7122 if (pAd->CommonCfg.bEnableTxBurst)
7125 #endif // CONFIG_STA_SUPPORT //
7128 // For some reasons, always set it to short slot time.
7130 // ToDo: Should consider capability with 11B
7132 #ifdef CONFIG_STA_SUPPORT
7133 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7135 if (pAd->StaCfg.BssType == BSS_ADHOC)
7138 #endif // CONFIG_STA_SUPPORT //
7140 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7141 RegValue = RegValue & 0xFFFFFF00;
7143 RegValue |= SlotTime;
7145 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7149 ========================================================================
7151 Add Shared key information into ASIC.
7152 Update shared key, TxMic and RxMic to Asic Shared key table
7153 Update its cipherAlg to Asic Shared key Mode.
7156 ========================================================================
7158 VOID AsicAddSharedKeyEntry(
7159 IN PRTMP_ADAPTER pAd,
7167 ULONG offset; //, csr0;
7168 SHAREDKEY_MODE_STRUC csr1;
7170 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7171 //============================================================================================
7173 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7174 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7175 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]));
7178 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7179 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7183 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7184 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7186 //============================================================================================
7188 // fill key material - key + TX MIC + RX MIC
7193 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7194 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7196 offset += MAX_LEN_OF_SHARE_KEY;
7199 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7205 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7211 // Update cipher algorithm. WSTA always use BSS0
7213 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7214 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7215 if ((BssIndex%2) == 0)
7218 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7219 else if (KeyIdx == 1)
7220 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7221 else if (KeyIdx == 2)
7222 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7224 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7229 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7230 else if (KeyIdx == 1)
7231 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7232 else if (KeyIdx == 2)
7233 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7235 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7237 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7238 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7242 // IRQL = DISPATCH_LEVEL
7243 VOID AsicRemoveSharedKeyEntry(
7244 IN PRTMP_ADAPTER pAd,
7249 SHAREDKEY_MODE_STRUC csr1;
7251 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7253 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7254 if ((BssIndex%2) == 0)
7257 csr1.field.Bss0Key0CipherAlg = 0;
7258 else if (KeyIdx == 1)
7259 csr1.field.Bss0Key1CipherAlg = 0;
7260 else if (KeyIdx == 2)
7261 csr1.field.Bss0Key2CipherAlg = 0;
7263 csr1.field.Bss0Key3CipherAlg = 0;
7268 csr1.field.Bss1Key0CipherAlg = 0;
7269 else if (KeyIdx == 1)
7270 csr1.field.Bss1Key1CipherAlg = 0;
7271 else if (KeyIdx == 2)
7272 csr1.field.Bss1Key2CipherAlg = 0;
7274 csr1.field.Bss1Key3CipherAlg = 0;
7276 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7277 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7278 ASSERT(BssIndex < 4);
7284 VOID AsicUpdateWCIDAttribute(
7285 IN PRTMP_ADAPTER pAd,
7289 IN BOOLEAN bUsePairewiseKeyTable)
7291 ULONG WCIDAttri = 0, offset;
7294 // Update WCID attribute.
7295 // Only TxKey could update WCID attribute.
7297 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7298 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7299 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7302 VOID AsicUpdateWCIDIVEIV(
7303 IN PRTMP_ADAPTER pAd,
7310 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7312 RTMP_IO_WRITE32(pAd, offset, uIV);
7313 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7316 VOID AsicUpdateRxWCIDTable(
7317 IN PRTMP_ADAPTER pAd,
7324 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7325 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7326 RTMP_IO_WRITE32(pAd, offset, Addr);
7327 Addr = pAddr[4] + (pAddr[5] << 8);
7328 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7333 ========================================================================
7335 Routine Description:
7336 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7339 pAd Pointer to our adapter
7340 WCID WCID Entry number.
7341 BssIndex BSSID index, station or none multiple BSSID support
7342 this value should be 0.
7343 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7344 pCipherKey Pointer to Cipher Key.
7345 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7346 otherwise PairewiseKey table
7347 bTxKey This is the transmit key if enabled.
7353 This routine will set the relative key stuff to Asic including WCID attribute,
7354 Cipher Key, Cipher algorithm and IV/EIV.
7356 IV/EIV will be update if this CipherKey is the transmission key because
7357 ASIC will base on IV's KeyID value to select Cipher Key.
7359 If bTxKey sets to FALSE, this is not the TX key, but it could be
7362 For AP mode bTxKey must be always set to TRUE.
7363 ========================================================================
7365 VOID AsicAddKeyEntry(
7366 IN PRTMP_ADAPTER pAd,
7370 IN PCIPHER_KEY pCipherKey,
7371 IN BOOLEAN bUsePairewiseKeyTable,
7375 // ULONG WCIDAttri = 0;
7377 PUCHAR pKey = pCipherKey->Key;
7378 // ULONG KeyLen = pCipherKey->KeyLen;
7379 PUCHAR pTxMic = pCipherKey->TxMic;
7380 PUCHAR pRxMic = pCipherKey->RxMic;
7381 PUCHAR pTxtsc = pCipherKey->TxTsc;
7382 UCHAR CipherAlg = pCipherKey->CipherAlg;
7383 SHAREDKEY_MODE_STRUC csr1;
7385 // ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY);
7387 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7389 // 1.) decide key table offset
7391 if (bUsePairewiseKeyTable)
7392 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7394 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7397 // 2.) Set Key to Asic
7399 //for (i = 0; i < KeyLen; i++)
7402 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7403 offset += MAX_LEN_OF_PEER_KEY;
7406 // 3.) Set MIC key if available
7410 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7412 offset += LEN_TKIP_TXMICK;
7416 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7421 // 4.) Modify IV/EIV if needs
7422 // This will force Asic to use this key ID by setting IV.
7433 IV4 = (KeyIdx << 6);
7434 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7435 IV4 |= 0x20; // turn on extension bit means EIV existence
7437 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7438 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7444 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7446 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7449 if (!bUsePairewiseKeyTable)
7452 // Only update the shared key security mode
7454 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7455 if ((BssIndex % 2) == 0)
7458 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7459 else if (KeyIdx == 1)
7460 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7461 else if (KeyIdx == 2)
7462 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7464 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7469 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7470 else if (KeyIdx == 1)
7471 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7472 else if (KeyIdx == 2)
7473 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7475 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7477 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7480 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7485 ========================================================================
7487 Add Pair-wise key material into ASIC.
7488 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7491 ========================================================================
7493 VOID AsicAddPairwiseKeyEntry(
7494 IN PRTMP_ADAPTER pAd,
7497 IN CIPHER_KEY *pCipherKey)
7501 PUCHAR pKey = pCipherKey->Key;
7502 PUCHAR pTxMic = pCipherKey->TxMic;
7503 PUCHAR pRxMic = pCipherKey->RxMic;
7505 UCHAR CipherAlg = pCipherKey->CipherAlg;
7509 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7511 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7513 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7516 RTMP_IO_READ32(pAd, offset + i, &Value);
7519 offset += MAX_LEN_OF_PEER_KEY;
7525 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7532 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7536 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7537 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7538 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]));
7541 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7542 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7546 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7547 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7551 ========================================================================
7553 Remove Pair-wise key material from ASIC.
7556 ========================================================================
7558 VOID AsicRemovePairwiseKeyEntry(
7559 IN PRTMP_ADAPTER pAd,
7566 // re-set the entry's WCID attribute as OPEN-NONE.
7567 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7568 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7569 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7572 BOOLEAN AsicSendCommandToMcu(
7573 IN PRTMP_ADAPTER pAd,
7579 HOST_CMD_CSR_STRUC H2MCmd;
7580 H2M_MAILBOX_STRUC H2MMailbox;
7584 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7585 if (H2MMailbox.field.Owner == 0)
7594 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7600 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7601 H2MMailbox.field.CmdToken = Token;
7602 H2MMailbox.field.HighByte = Arg1;
7603 H2MMailbox.field.LowByte = Arg0;
7604 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7607 H2MCmd.field.HostCommand = Command;
7608 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7610 if (Command != 0x80)
7619 ========================================================================
7621 Routine Description:
7622 Verify the support rate for different PHY type
7625 pAd Pointer to our adapter
7630 IRQL = PASSIVE_LEVEL
7632 ========================================================================
7634 VOID RTMPCheckRates(
7635 IN PRTMP_ADAPTER pAd,
7636 IN OUT UCHAR SupRate[],
7637 IN OUT UCHAR *SupRateLen)
7639 UCHAR RateIdx, i, j;
7640 UCHAR NewRate[12], NewRateLen;
7644 if (pAd->CommonCfg.PhyMode == PHY_11B)
7649 // Check for support rates exclude basic rate bit
7650 for (i = 0; i < *SupRateLen; i++)
7651 for (j = 0; j < RateIdx; j++)
7652 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7653 NewRate[NewRateLen++] = SupRate[i];
7655 *SupRateLen = NewRateLen;
7656 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7659 #ifdef CONFIG_STA_SUPPORT
7660 #ifdef DOT11_N_SUPPORT
7661 BOOLEAN RTMPCheckChannel(
7662 IN PRTMP_ADAPTER pAd,
7663 IN UCHAR CentralChannel,
7667 UCHAR UpperChannel = 0, LowerChannel = 0;
7668 UCHAR NoEffectChannelinList = 0;
7670 // Find upper and lower channel according to 40MHz current operation.
7671 if (CentralChannel < Channel)
7673 UpperChannel = Channel;
7674 if (CentralChannel > 2)
7675 LowerChannel = CentralChannel - 2;
7679 else if (CentralChannel > Channel)
7681 UpperChannel = CentralChannel + 2;
7682 LowerChannel = Channel;
7685 for (k = 0;k < pAd->ChannelListNum;k++)
7687 if (pAd->ChannelList[k].Channel == UpperChannel)
7689 NoEffectChannelinList ++;
7691 if (pAd->ChannelList[k].Channel == LowerChannel)
7693 NoEffectChannelinList ++;
7697 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7698 if (NoEffectChannelinList == 2)
7705 ========================================================================
7707 Routine Description:
7708 Verify the support rate for HT phy type
7711 pAd Pointer to our adapter
7714 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7716 IRQL = PASSIVE_LEVEL
7718 ========================================================================
7720 BOOLEAN RTMPCheckHt(
7721 IN PRTMP_ADAPTER pAd,
7723 IN HT_CAPABILITY_IE *pHtCapability,
7724 IN ADD_HT_INFO_IE *pAddHtInfo)
7726 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7729 // If use AMSDU, set flag.
7730 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7731 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7732 // Save Peer Capability
7733 if (pHtCapability->HtCapInfo.ShortGIfor20)
7734 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7735 if (pHtCapability->HtCapInfo.ShortGIfor40)
7736 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7737 if (pHtCapability->HtCapInfo.TxSTBC)
7738 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7739 if (pHtCapability->HtCapInfo.RxSTBC)
7740 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7741 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7743 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7746 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7748 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7751 // Will check ChannelWidth for MCSSet[4] below
7752 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7753 switch (pAd->CommonCfg.RxStream)
7756 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7757 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7758 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7759 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7762 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7763 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7764 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7765 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7768 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7769 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7770 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7771 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7775 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7777 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7778 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7779 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7781 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7783 // Send Assoc Req with my HT capability.
7784 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7785 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7786 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7787 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7788 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7789 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7790 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7791 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7792 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7793 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7794 if (pAd->CommonCfg.bRdg)
7796 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7797 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7800 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7801 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7803 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7806 #endif // DOT11_N_SUPPORT //
7807 #endif // CONFIG_STA_SUPPORT //
7810 ========================================================================
7812 Routine Description:
7813 Verify the support rate for different PHY type
7816 pAd Pointer to our adapter
7821 IRQL = PASSIVE_LEVEL
7823 ========================================================================
7825 VOID RTMPUpdateMlmeRate(
7826 IN PRTMP_ADAPTER pAd)
7829 UCHAR ProperMlmeRate; //= RATE_54;
7830 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7831 BOOLEAN bMatch = FALSE;
7833 switch (pAd->CommonCfg.PhyMode)
7836 ProperMlmeRate = RATE_11;
7837 MinimumRate = RATE_1;
7839 case PHY_11BG_MIXED:
7840 #ifdef DOT11_N_SUPPORT
7841 case PHY_11ABGN_MIXED:
7842 case PHY_11BGN_MIXED:
7843 #endif // DOT11_N_SUPPORT //
7844 if ((pAd->MlmeAux.SupRateLen == 4) &&
7845 (pAd->MlmeAux.ExtRateLen == 0))
7847 ProperMlmeRate = RATE_11;
7849 ProperMlmeRate = RATE_24;
7851 if (pAd->MlmeAux.Channel <= 14)
7852 MinimumRate = RATE_1;
7854 MinimumRate = RATE_6;
7857 #ifdef DOT11_N_SUPPORT
7858 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7859 case PHY_11GN_MIXED:
7860 case PHY_11AGN_MIXED:
7861 case PHY_11AN_MIXED:
7863 #endif // DOT11_N_SUPPORT //
7864 ProperMlmeRate = RATE_24;
7865 MinimumRate = RATE_6;
7867 case PHY_11ABG_MIXED:
7868 ProperMlmeRate = RATE_24;
7869 if (pAd->MlmeAux.Channel <= 14)
7870 MinimumRate = RATE_1;
7872 MinimumRate = RATE_6;
7875 ProperMlmeRate = RATE_1;
7876 MinimumRate = RATE_1;
7880 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7882 for (j = 0; j < RateIdx; j++)
7884 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7886 if (j == ProperMlmeRate)
7898 if (bMatch == FALSE)
7900 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7902 for (j = 0; j < RateIdx; j++)
7904 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7906 if (j == ProperMlmeRate)
7919 if (bMatch == FALSE)
7921 ProperMlmeRate = MinimumRate;
7924 pAd->CommonCfg.MlmeRate = MinimumRate;
7925 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7926 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7928 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7929 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7930 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7931 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7935 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7936 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7937 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7938 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7941 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7945 IN PRTMP_ADAPTER pAd,
7952 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7957 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7959 larger = max(Rssi0, Rssi1);
7962 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7964 larger = max(larger, Rssi2);
7974 // Antenna divesity use GPIO3 and EESK pin for control
7975 // Antenna and EEPROM access are both using EESK pin,
7976 // Therefor we should avoid accessing EESK at the same time
7977 // Then restore antenna after EEPROM access
7979 IN PRTMP_ADAPTER pAd,
7986 if ((pAd->EepromAccess) ||
7987 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) ||
7988 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) ||
7989 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) ||
7990 (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
7995 // the antenna selection is through firmware and MAC register(GPIO3)
7999 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8001 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8003 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8005 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8006 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to main antenna\n"));
8011 RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
8013 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
8015 RTMP_IO_READ32(pAd, GPIO_CTRL_CFG, &Value);
8018 RTMP_IO_WRITE32(pAd, GPIO_CTRL_CFG, Value);
8019 DBGPRINT_RAW(RT_DEBUG_TRACE, ("AsicSetRxAnt, switch to aux antenna\n"));
8026 ========================================================================
8027 Routine Description:
8028 Periodic evaluate antenna link status
8031 pAd - Adapter pointer
8036 ========================================================================
8038 VOID AsicEvaluateRxAnt(
8039 IN PRTMP_ADAPTER pAd)
8043 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8044 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8045 fRTMP_ADAPTER_RADIO_OFF |
8046 fRTMP_ADAPTER_NIC_NOT_EXIST |
8047 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) ||
8048 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8050 || (pAd->EepromAccess)
8056 #ifdef CONFIG_STA_SUPPORT
8057 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8059 //if (pAd->StaCfg.Psm == PWR_SAVE)
8062 #endif // CONFIG_STA_SUPPORT //
8064 // two antenna selection mechanism- one is antenna diversity, the other is failed antenna remove
8065 // one is antenna diversity:there is only one antenna can rx and tx
8066 // the other is failed antenna remove:two physical antenna can rx and tx
8067 if (pAd->NicConfig2.field.AntDiversity)
8069 DBGPRINT(RT_DEBUG_TRACE,("AntDiv - before evaluate Pair1-Ant (%d,%d)\n",
8070 pAd->RxAnt.Pair1PrimaryRxAnt, pAd->RxAnt.Pair1SecondaryRxAnt));
8072 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1SecondaryRxAnt);
8074 pAd->RxAnt.EvaluatePeriod = 1; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8075 pAd->RxAnt.FirstPktArrivedWhenEvaluate = FALSE;
8076 pAd->RxAnt.RcvPktNumWhenEvaluate = 0;
8078 // a one-shot timer to end the evalution
8079 // dynamic adjust antenna evaluation period according to the traffic
8080 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8081 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 100);
8083 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8088 #ifdef CONFIG_STA_SUPPORT
8089 if (pAd->StaCfg.Psm == PWR_SAVE)
8091 #endif // CONFIG_STA_SUPPORT //
8093 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8095 if(pAd->Antenna.field.RxPath == 3)
8099 else if(pAd->Antenna.field.RxPath == 2)
8103 else if(pAd->Antenna.field.RxPath == 1)
8107 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8108 #ifdef CONFIG_STA_SUPPORT
8109 #endif // CONFIG_STA_SUPPORT //
8110 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8113 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8114 pAd->RalinkCounters.OneSecTxRetryOkCount +
8115 pAd->RalinkCounters.OneSecTxFailCount;
8117 // dynamic adjust antenna evaluation period according to the traffic
8118 if (TxTotalCnt > 50)
8120 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8121 pAd->Mlme.bLowThroughput = FALSE;
8125 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8126 pAd->Mlme.bLowThroughput = TRUE;
8133 ========================================================================
8134 Routine Description:
8135 After evaluation, check antenna link status
8138 pAd - Adapter pointer
8143 ========================================================================
8145 VOID AsicRxAntEvalTimeout(
8146 IN PVOID SystemSpecific1,
8147 IN PVOID FunctionContext,
8148 IN PVOID SystemSpecific2,
8149 IN PVOID SystemSpecific3)
8151 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8152 #ifdef CONFIG_STA_SUPPORT
8154 CHAR larger = -127, rssi0, rssi1, rssi2;
8155 #endif // CONFIG_STA_SUPPORT //
8157 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
8158 fRTMP_ADAPTER_HALT_IN_PROGRESS |
8159 fRTMP_ADAPTER_RADIO_OFF |
8160 fRTMP_ADAPTER_NIC_NOT_EXIST) ||
8161 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
8163 || (pAd->EepromAccess)
8169 #ifdef CONFIG_STA_SUPPORT
8170 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8172 //if (pAd->StaCfg.Psm == PWR_SAVE)
8175 if (pAd->NicConfig2.field.AntDiversity)
8177 if ((pAd->RxAnt.RcvPktNumWhenEvaluate != 0) && (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >= pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1PrimaryRxAnt]))
8182 // select PrimaryRxAntPair
8183 // Role change, Used Pair1SecondaryRxAnt as PrimaryRxAntPair.
8184 // Since Pair1SecondaryRxAnt Quality good than Pair1PrimaryRxAnt
8186 temp = pAd->RxAnt.Pair1PrimaryRxAnt;
8187 pAd->RxAnt.Pair1PrimaryRxAnt = pAd->RxAnt.Pair1SecondaryRxAnt;
8188 pAd->RxAnt.Pair1SecondaryRxAnt = temp;
8190 pAd->RxAnt.Pair1LastAvgRssi = (pAd->RxAnt.Pair1AvgRssi[pAd->RxAnt.Pair1SecondaryRxAnt] >> 3);
8191 pAd->RxAnt.EvaluateStableCnt = 0;
8195 // if the evaluated antenna is not better than original, switch back to original antenna
8196 AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
8197 pAd->RxAnt.EvaluateStableCnt ++;
8200 pAd->RxAnt.EvaluatePeriod = 0; // 1:Means switch to SecondaryRxAnt, 0:Means switch to Pair1PrimaryRxAnt
8202 DBGPRINT(RT_DEBUG_TRACE,("AsicRxAntEvalAction::After Eval(fix in #%d), <%d, %d>, RcvPktNumWhenEvaluate=%ld\n",
8203 pAd->RxAnt.Pair1PrimaryRxAnt, (pAd->RxAnt.Pair1AvgRssi[0] >> 3), (pAd->RxAnt.Pair1AvgRssi[1] >> 3), pAd->RxAnt.RcvPktNumWhenEvaluate));
8207 if (pAd->StaCfg.Psm == PWR_SAVE)
8210 // if the traffic is low, use average rssi as the criteria
8211 if (pAd->Mlme.bLowThroughput == TRUE)
8213 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8214 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8215 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8219 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8220 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8221 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8224 if(pAd->Antenna.field.RxPath == 3)
8226 larger = max(rssi0, rssi1);
8228 if (larger > (rssi2 + 20))
8229 pAd->Mlme.RealRxPath = 2;
8231 pAd->Mlme.RealRxPath = 3;
8233 else if(pAd->Antenna.field.RxPath == 2)
8235 if (rssi0 > (rssi1 + 20))
8236 pAd->Mlme.RealRxPath = 1;
8238 pAd->Mlme.RealRxPath = 2;
8241 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8243 if(pAd->Mlme.RealRxPath == 3)
8247 else if(pAd->Mlme.RealRxPath == 2)
8251 else if(pAd->Mlme.RealRxPath == 1)
8255 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8259 #endif // CONFIG_STA_SUPPORT //
8265 VOID APSDPeriodicExec(
8266 IN PVOID SystemSpecific1,
8267 IN PVOID FunctionContext,
8268 IN PVOID SystemSpecific2,
8269 IN PVOID SystemSpecific3)
8271 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8273 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8276 pAd->CommonCfg.TriggerTimerCount++;
8278 // Driver should not send trigger frame, it should be send by application layer
8280 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
8281 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
8282 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
8284 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
8285 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
8286 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
8287 pAd->CommonCfg.TriggerTimerCount = 0;
8288 pAd->CommonCfg.bInServicePeriod = TRUE;
8293 ========================================================================
8294 Routine Description:
8295 Set/reset MAC registers according to bPiggyBack parameter
8298 pAd - Adapter pointer
8299 bPiggyBack - Enable / Disable Piggy-Back
8304 ========================================================================
8306 VOID RTMPSetPiggyBack(
8307 IN PRTMP_ADAPTER pAd,
8308 IN BOOLEAN bPiggyBack)
8310 TX_LINK_CFG_STRUC TxLinkCfg;
8312 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8314 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8315 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8319 ========================================================================
8320 Routine Description:
8321 check if this entry need to switch rate automatically
8331 ========================================================================
8333 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8334 IN PRTMP_ADAPTER pAd,
8335 IN PMAC_TABLE_ENTRY pEntry)
8337 BOOLEAN result = TRUE;
8340 #ifdef CONFIG_STA_SUPPORT
8341 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8343 // only associated STA counts
8344 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8346 result = pAd->StaCfg.bAutoTxRateSwitch;
8351 #endif // CONFIG_STA_SUPPORT //
8359 BOOLEAN RTMPAutoRateSwitchCheck(
8360 IN PRTMP_ADAPTER pAd)
8363 #ifdef CONFIG_STA_SUPPORT
8364 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8366 if (pAd->StaCfg.bAutoTxRateSwitch)
8369 #endif // CONFIG_STA_SUPPORT //
8375 ========================================================================
8376 Routine Description:
8377 check if this entry need to fix tx legacy rate
8387 ========================================================================
8389 UCHAR RTMPStaFixedTxMode(
8390 IN PRTMP_ADAPTER pAd,
8391 IN PMAC_TABLE_ENTRY pEntry)
8393 UCHAR tx_mode = FIXED_TXMODE_HT;
8396 #ifdef CONFIG_STA_SUPPORT
8397 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8399 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8401 #endif // CONFIG_STA_SUPPORT //
8407 ========================================================================
8408 Routine Description:
8409 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8419 ========================================================================
8421 VOID RTMPUpdateLegacyTxSetting(
8422 UCHAR fixed_tx_mode,
8423 PMAC_TABLE_ENTRY pEntry)
8425 HTTRANSMIT_SETTING TransmitSetting;
8427 if (fixed_tx_mode == FIXED_TXMODE_HT)
8430 TransmitSetting.word = 0;
8432 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8433 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8435 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8437 TransmitSetting.field.MODE = MODE_CCK;
8438 // CCK mode allow MCS 0~3
8439 if (TransmitSetting.field.MCS > MCS_3)
8440 TransmitSetting.field.MCS = MCS_3;
8444 TransmitSetting.field.MODE = MODE_OFDM;
8445 // OFDM mode allow MCS 0~7
8446 if (TransmitSetting.field.MCS > MCS_7)
8447 TransmitSetting.field.MCS = MCS_7;
8450 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8452 pEntry->HTPhyMode.word = TransmitSetting.word;
8453 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8454 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8458 #ifdef CONFIG_STA_SUPPORT
8460 ==========================================================================
8462 dynamic tune BBP R66 to find a balance between sensibility and
8465 IRQL = DISPATCH_LEVEL
8467 ==========================================================================
8469 VOID AsicStaBbpTuning(
8470 IN PRTMP_ADAPTER pAd)
8472 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8475 // 2860C did not support Fase CCA, therefore can't tune
8476 if (pAd->MACVersion == 0x28600100)
8482 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8485 if ((pAd->OpMode == OPMODE_STA)
8486 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8488 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8491 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8494 if (pAd->Antenna.field.RxPath > 1)
8495 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8497 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8499 if (pAd->LatchRfRegs.Channel <= 14)
8502 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8503 // Otherwise, it will have some throughput side effect when low RSSI
8506 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8508 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8509 if (OrigR66Value != R66)
8511 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8516 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8517 if (OrigR66Value != R66)
8519 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8526 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8528 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8529 if (OrigR66Value != R66)
8531 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8536 R66 = 0x2E + GET_LNA_GAIN(pAd);
8537 if (OrigR66Value != R66)
8539 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8547 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8549 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8551 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8552 if (OrigR66Value != R66)
8554 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8559 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8560 if (OrigR66Value != R66)
8562 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8568 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8570 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8571 if (OrigR66Value != R66)
8573 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8578 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8579 if (OrigR66Value != R66)
8581 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8590 #endif // CONFIG_STA_SUPPORT //
8592 VOID RTMPSetAGCInitValue(
8593 IN PRTMP_ADAPTER pAd,
8598 if (pAd->LatchRfRegs.Channel <= 14)
8600 R66 = 0x2E + GET_LNA_GAIN(pAd);
8601 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8605 if (BandWidth == BW_20)
8607 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8608 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8610 #ifdef DOT11_N_SUPPORT
8613 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8614 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8616 #endif // DOT11_N_SUPPORT //
8621 VOID AsicTurnOffRFClk(
8622 IN PRTMP_ADAPTER pAd,
8626 UINT32 R1 = 0, R2 = 0, R3 = 0;
8628 RTMP_RF_REGS *RFRegTable;
8631 // The RF programming sequence is difference between 3xxx and 2xxx
8634 RT30xxLoadRFSleepModeSetup(pAd); // add by johnli, RF power sequence setup, load RF sleep-mode setup
8639 RFRegTable = RF2850RegTable;
8641 switch (pAd->RfIcType)
8648 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8650 if (Channel == RFRegTable[index].Channel)
8652 R1 = RFRegTable[index].R1 & 0xffffdfff;
8653 R2 = RFRegTable[index].R2 & 0xfffbffff;
8654 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8656 RTMP_RF_IO_WRITE32(pAd, R1);
8657 RTMP_RF_IO_WRITE32(pAd, R2);
8659 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8660 // Set RF R2 bit18=0, R3 bit[18:19]=0
8661 //if (pAd->StaCfg.bRadio == FALSE)
8664 RTMP_RF_IO_WRITE32(pAd, R3);
8666 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8667 Channel, pAd->RfIcType, R2, R3));
8670 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8671 Channel, pAd->RfIcType, R2));
8687 VOID AsicTurnOnRFClk(
8688 IN PRTMP_ADAPTER pAd,
8692 UINT32 R1 = 0, R2 = 0, R3 = 0;
8694 RTMP_RF_REGS *RFRegTable;
8697 // The RF programming sequence is difference between 3xxx and 2xxx
8704 RFRegTable = RF2850RegTable;
8706 switch (pAd->RfIcType)
8713 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8715 if (Channel == RFRegTable[index].Channel)
8717 R3 = pAd->LatchRfRegs.R3;
8720 RTMP_RF_IO_WRITE32(pAd, R3);
8722 R1 = RFRegTable[index].R1;
8723 RTMP_RF_IO_WRITE32(pAd, R1);
8725 R2 = RFRegTable[index].R2;
8726 if (pAd->Antenna.field.TxPath == 1)
8728 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8731 if (pAd->Antenna.field.RxPath == 2)
8733 R2 |= 0x40; // write 1 to off Rxpath.
8735 else if (pAd->Antenna.field.RxPath == 1)
8737 R2 |= 0x20040; // write 1 to off RxPath
8739 RTMP_RF_IO_WRITE32(pAd, R2);