Staging: add rt2870 wireless driver
[linux-2.6/mini2440.git] / drivers / staging / rt2870 / common / mlme.c
blob8a82cee8bf269b622e3efeb6b298e78cd715c195
1 /*
2 *************************************************************************
3 * Ralink Tech Inc.
4 * 5F., No.36, Taiyuan St., Jhubei City,
5 * Hsinchu County 302,
6 * Taiwan, R.O.C.
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. *
14 * *
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. *
19 * *
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. *
24 * *
25 *************************************************************************
27 Module Name:
28 mlme.c
30 Abstract:
32 Revision History:
33 Who When What
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"
40 #include <stdarg.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,
72 0x0a, 0x21, 6, 8, 25,
73 0x0b, 0x21, 7, 8, 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,
79 0x11, 0x00, 0, 0, 0,
80 0x12, 0x00, 0, 0, 0,
81 0x13, 0x00, 0, 0, 0,
82 0x14, 0x00, 0, 0, 0,
83 0x15, 0x00, 0, 0, 0,
84 0x16, 0x00, 0, 0, 0,
85 0x17, 0x00, 0, 0, 0,
86 0x18, 0x00, 0, 0, 0,
87 0x19, 0x00, 0, 0, 0,
88 0x1a, 0x00, 0, 0, 0,
89 0x1b, 0x00, 0, 0, 0,
90 0x1c, 0x00, 0, 0, 0,
91 0x1d, 0x00, 0, 0, 0,
92 0x1e, 0x00, 0, 0, 0,
93 0x1f, 0x00, 0, 0, 0,
96 UCHAR RateSwitchTable11B[] = {
97 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
98 0x04, 0x03, 0, 0, 0, // Initial used item after association
99 0x00, 0x00, 0, 40, 101,
100 0x01, 0x00, 1, 40, 50,
101 0x02, 0x00, 2, 35, 45,
102 0x03, 0x00, 3, 20, 45,
105 UCHAR RateSwitchTable11BG[] = {
106 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
107 0x0a, 0x00, 0, 0, 0, // Initial used item after association
108 0x00, 0x00, 0, 40, 101,
109 0x01, 0x00, 1, 40, 50,
110 0x02, 0x00, 2, 35, 45,
111 0x03, 0x00, 3, 20, 45,
112 0x04, 0x10, 2, 20, 35,
113 0x05, 0x10, 3, 16, 35,
114 0x06, 0x10, 4, 10, 25,
115 0x07, 0x10, 5, 16, 25,
116 0x08, 0x10, 6, 10, 25,
117 0x09, 0x10, 7, 10, 13,
120 UCHAR RateSwitchTable11G[] = {
121 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
122 0x08, 0x00, 0, 0, 0, // Initial used item after association
123 0x00, 0x10, 0, 20, 101,
124 0x01, 0x10, 1, 20, 35,
125 0x02, 0x10, 2, 20, 35,
126 0x03, 0x10, 3, 16, 35,
127 0x04, 0x10, 4, 10, 25,
128 0x05, 0x10, 5, 16, 25,
129 0x06, 0x10, 6, 10, 25,
130 0x07, 0x10, 7, 10, 13,
133 #ifdef DOT11_N_SUPPORT
134 UCHAR RateSwitchTable11N1S[] = {
135 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
136 0x09, 0x00, 0, 0, 0, // Initial used item after association
137 0x00, 0x21, 0, 30, 101,
138 0x01, 0x21, 1, 20, 50,
139 0x02, 0x21, 2, 20, 50,
140 0x03, 0x21, 3, 15, 50,
141 0x04, 0x21, 4, 15, 30,
142 0x05, 0x21, 5, 10, 25,
143 0x06, 0x21, 6, 8, 14,
144 0x07, 0x21, 7, 8, 14,
145 0x08, 0x23, 7, 8, 14,
148 UCHAR RateSwitchTable11N2S[] = {
149 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
150 0x0a, 0x00, 0, 0, 0, // Initial used item after association
151 0x00, 0x21, 0, 30, 101,
152 0x01, 0x21, 1, 20, 50,
153 0x02, 0x21, 2, 20, 50,
154 0x03, 0x21, 3, 15, 50,
155 0x04, 0x21, 4, 15, 30,
156 0x05, 0x20, 12, 15, 30,
157 0x06, 0x20, 13, 8, 20,
158 0x07, 0x20, 14, 8, 20,
159 0x08, 0x20, 15, 8, 25,
160 0x09, 0x22, 15, 8, 25,
163 UCHAR RateSwitchTable11N3S[] = {
164 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
165 0x0a, 0x00, 0, 0, 0, // Initial used item after association
166 0x00, 0x21, 0, 30, 101,
167 0x01, 0x21, 1, 20, 50,
168 0x02, 0x21, 2, 20, 50,
169 0x03, 0x21, 3, 15, 50,
170 0x04, 0x21, 4, 15, 30,
171 0x05, 0x20, 12, 15, 30,
172 0x06, 0x20, 13, 8, 20,
173 0x07, 0x20, 14, 8, 20,
174 0x08, 0x20, 15, 8, 25,
175 0x09, 0x22, 15, 8, 25,
178 UCHAR RateSwitchTable11N2SForABand[] = {
179 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
180 0x0b, 0x09, 0, 0, 0, // Initial used item after association
181 0x00, 0x21, 0, 30, 101,
182 0x01, 0x21, 1, 20, 50,
183 0x02, 0x21, 2, 20, 50,
184 0x03, 0x21, 3, 15, 50,
185 0x04, 0x21, 4, 15, 30,
186 0x05, 0x21, 5, 15, 30,
187 0x06, 0x20, 12, 15, 30,
188 0x07, 0x20, 13, 8, 20,
189 0x08, 0x20, 14, 8, 20,
190 0x09, 0x20, 15, 8, 25,
191 0x0a, 0x22, 15, 8, 25,
194 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
195 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
196 0x0b, 0x09, 0, 0, 0, // Initial used item after association
197 0x00, 0x21, 0, 30, 101,
198 0x01, 0x21, 1, 20, 50,
199 0x02, 0x21, 2, 20, 50,
200 0x03, 0x21, 3, 15, 50,
201 0x04, 0x21, 4, 15, 30,
202 0x05, 0x21, 5, 15, 30,
203 0x06, 0x20, 12, 15, 30,
204 0x07, 0x20, 13, 8, 20,
205 0x08, 0x20, 14, 8, 20,
206 0x09, 0x20, 15, 8, 25,
207 0x0a, 0x22, 15, 8, 25,
210 UCHAR RateSwitchTable11BGN1S[] = {
211 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
212 0x0d, 0x00, 0, 0, 0, // Initial used item after association
213 0x00, 0x00, 0, 40, 101,
214 0x01, 0x00, 1, 40, 50,
215 0x02, 0x00, 2, 35, 45,
216 0x03, 0x00, 3, 20, 45,
217 0x04, 0x21, 0, 30,101, //50
218 0x05, 0x21, 1, 20, 50,
219 0x06, 0x21, 2, 20, 50,
220 0x07, 0x21, 3, 15, 50,
221 0x08, 0x21, 4, 15, 30,
222 0x09, 0x21, 5, 10, 25,
223 0x0a, 0x21, 6, 8, 14,
224 0x0b, 0x21, 7, 8, 14,
225 0x0c, 0x23, 7, 8, 14,
228 UCHAR RateSwitchTable11BGN2S[] = {
229 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
230 0x0a, 0x00, 0, 0, 0, // Initial used item after association
231 0x00, 0x21, 0, 30,101, //50
232 0x01, 0x21, 1, 20, 50,
233 0x02, 0x21, 2, 20, 50,
234 0x03, 0x21, 3, 15, 50,
235 0x04, 0x21, 4, 15, 30,
236 0x05, 0x20, 12, 15, 30,
237 0x06, 0x20, 13, 8, 20,
238 0x07, 0x20, 14, 8, 20,
239 0x08, 0x20, 15, 8, 25,
240 0x09, 0x22, 15, 8, 25,
243 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
244 // Item No. Mode Curr-MCS TrainUp TrainDown // Mode- Bit0: STBC, Bit1: Short GI, Bit4,5: Mode(0:CCK, 1:OFDM, 2:HT Mix, 3:HT GF)
245 0x0a, 0x00, 0, 0, 0, // Initial used item after association
246 0x00, 0x21, 0, 30,101, //50
247 0x01, 0x21, 1, 20, 50,
248 0x02, 0x21, 2, 20, 50,
249 0x03, 0x21, 3, 20, 50,
250 0x04, 0x21, 4, 15, 50,
251 #if 1
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,
263 #endif
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[] = {
301 /* 0 */ "Reserved",
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",
311 /* 10 */ "Reserved",
312 /* 11 */ "Reserved",
313 /* 12 */ "Reserved",
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",
319 /* 18 */
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 #ifdef DOT11N_DRAFT3
350 UCHAR ExtHtCapIe = IE_EXT_CAPABILITY;
351 #endif // DOT11N_DRAFT3 //
352 #endif // DOT11_N_SUPPORT //
353 UCHAR ErpIe = IE_ERP;
354 UCHAR DsIe = IE_DS_PARM;
355 UCHAR TimIe = IE_TIM;
356 UCHAR WpaIe = IE_WPA;
357 UCHAR Wpa2Ie = IE_WPA2;
358 UCHAR IbssIe = IE_IBSS_PARM;
359 UCHAR Ccx2Ie = IE_CCX_V2;
360 UCHAR WapiIe = IE_WAPI;
362 extern UCHAR WPA_OUI[];
364 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
366 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
367 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
369 // Reset the RFIC setting to new series
370 RTMP_RF_REGS RF2850RegTable[] = {
371 // ch R1 R2 R3(TX0~4=0) R4
372 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
373 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
374 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
375 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
376 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
377 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
378 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
379 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
380 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
381 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
382 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
383 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
384 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
385 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
387 // 802.11 UNI / HyperLan 2
388 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
389 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
390 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
391 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
392 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
393 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
394 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
395 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
396 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
397 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
398 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
399 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
401 // 802.11 HyperLan 2
402 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
404 // 2008.04.30 modified
405 // The system team has AN to improve the EVM value
406 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
407 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
408 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
409 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
411 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
412 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
413 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
414 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
415 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
416 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
417 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
418 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
419 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
420 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
421 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
422 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
424 // 802.11 UNII
425 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
426 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
427 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
428 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
429 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
430 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
431 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
433 // Japan
434 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
435 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
436 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
437 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
438 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
439 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
440 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
442 // still lack of MMAC(Japan) ch 34,38,42,46
444 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
446 FREQUENCY_ITEM FreqItems3020[] =
448 /**************************************************/
449 // ISM : 2.4 to 2.483 GHz //
450 /**************************************************/
451 // 11g
452 /**************************************************/
453 //-CH---N-------R---K-----------
454 {1, 241, 2, 2},
455 {2, 241, 2, 7},
456 {3, 242, 2, 2},
457 {4, 242, 2, 7},
458 {5, 243, 2, 2},
459 {6, 243, 2, 7},
460 {7, 244, 2, 2},
461 {8, 244, 2, 7},
462 {9, 245, 2, 2},
463 {10, 245, 2, 7},
464 {11, 246, 2, 2},
465 {12, 246, 2, 7},
466 {13, 247, 2, 2},
467 {14, 248, 2, 4},
469 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
472 ==========================================================================
473 Description:
474 initialize the MLME task and its data structure (queue, spinlock,
475 timer, state machines).
477 IRQL = PASSIVE_LEVEL
479 Return:
480 always return NDIS_STATUS_SUCCESS
482 ==========================================================================
484 NDIS_STATUS MlmeInit(
485 IN PRTMP_ADAPTER pAd)
487 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
489 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
493 Status = MlmeQueueInit(&pAd->Mlme.Queue);
494 if(Status != NDIS_STATUS_SUCCESS)
495 break;
497 pAd->Mlme.bRunning = FALSE;
498 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
500 #ifdef CONFIG_STA_SUPPORT
501 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
503 BssTableInit(&pAd->ScanTab);
505 // init STA state machines
506 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
507 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
508 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
509 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
510 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
511 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
513 #ifdef QOS_DLS_SUPPORT
514 DlsStateMachineInit(pAd, &pAd->Mlme.DlsMachine, pAd->Mlme.DlsFunc);
515 #endif // QOS_DLS_SUPPORT //
518 // Since we are using switch/case to implement it, the init is different from the above
519 // state machine init
520 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
522 #endif // CONFIG_STA_SUPPORT //
526 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
528 // Init mlme periodic timer
529 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
531 // Set mlme periodic timer
532 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
534 // software-based RX Antenna diversity
535 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
537 } while (FALSE);
539 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
541 return Status;
545 ==========================================================================
546 Description:
547 main loop of the MLME
548 Pre:
549 Mlme has to be initialized, and there are something inside the queue
550 Note:
551 This function is invoked from MPSetInformation and MPReceive;
552 This task guarantee only one MlmeHandler will run.
554 IRQL = DISPATCH_LEVEL
556 ==========================================================================
558 VOID MlmeHandler(
559 IN PRTMP_ADAPTER pAd)
561 MLME_QUEUE_ELEM *Elem = NULL;
562 #ifdef APCLI_SUPPORT
563 SHORT apcliIfIndex;
564 #endif
566 // Only accept MLME and Frame from peer side, no other (control/data) frame should
567 // get into this state machine
569 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
570 if(pAd->Mlme.bRunning)
572 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
573 return;
575 else
577 pAd->Mlme.bRunning = TRUE;
579 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
581 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
583 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
584 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
585 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
587 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
588 break;
591 #ifdef RALINK_ATE
592 if(ATE_ON(pAd))
594 DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now in MlmeHandler\n"));
595 break;
597 #endif // RALINK_ATE //
599 //From message type, determine which state machine I should drive
600 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
602 #ifdef RT2870
603 if (Elem->MsgType == MT2_RESET_CONF)
605 DBGPRINT_RAW(RT_DEBUG_TRACE, ("!!! reset MLME state machine !!!\n"));
606 MlmeRestartStateMachine(pAd);
607 Elem->Occupied = FALSE;
608 Elem->MsgLen = 0;
609 continue;
611 #endif // RT2870 //
613 // if dequeue success
614 switch (Elem->Machine)
616 // STA state machines
617 #ifdef CONFIG_STA_SUPPORT
618 case ASSOC_STATE_MACHINE:
619 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
620 break;
621 case AUTH_STATE_MACHINE:
622 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
623 break;
624 case AUTH_RSP_STATE_MACHINE:
625 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
626 break;
627 case SYNC_STATE_MACHINE:
628 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
629 break;
630 case MLME_CNTL_STATE_MACHINE:
631 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
632 break;
633 case WPA_PSK_STATE_MACHINE:
634 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
635 break;
636 #ifdef LEAP_SUPPORT
637 case LEAP_STATE_MACHINE:
638 LeapMachinePerformAction(pAd, &pAd->Mlme.LeapMachine, Elem);
639 break;
640 #endif
641 case AIRONET_STATE_MACHINE:
642 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
643 break;
645 #ifdef QOS_DLS_SUPPORT
646 case DLS_STATE_MACHINE:
647 StateMachinePerformAction(pAd, &pAd->Mlme.DlsMachine, Elem);
648 break;
649 #endif // QOS_DLS_SUPPORT //
650 #endif // CONFIG_STA_SUPPORT //
652 case ACTION_STATE_MACHINE:
653 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
654 break;
659 default:
660 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
661 break;
662 } // end of switch
664 // free MLME element
665 Elem->Occupied = FALSE;
666 Elem->MsgLen = 0;
669 else {
670 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
674 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
675 pAd->Mlme.bRunning = FALSE;
676 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
680 ==========================================================================
681 Description:
682 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
683 Parameters:
684 Adapter - NIC Adapter pointer
685 Post:
686 The MLME task will no longer work properly
688 IRQL = PASSIVE_LEVEL
690 ==========================================================================
692 VOID MlmeHalt(
693 IN PRTMP_ADAPTER pAd)
695 BOOLEAN Cancelled;
697 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
699 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
701 // disable BEACON generation and other BEACON related hardware timers
702 AsicDisableSync(pAd);
705 #ifdef CONFIG_STA_SUPPORT
706 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
708 #ifdef QOS_DLS_SUPPORT
709 UCHAR i;
710 #endif // QOS_DLS_SUPPORT //
711 // Cancel pending timers
712 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
713 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
714 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
715 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
716 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
717 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
719 #ifdef QOS_DLS_SUPPORT
720 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
722 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
724 #endif // QOS_DLS_SUPPORT //
726 #endif // CONFIG_STA_SUPPORT //
728 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
729 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
733 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
735 // Set LED
736 RTMPSetLED(pAd, LED_HALT);
737 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
738 #ifdef RT2870
740 LED_CFG_STRUC LedCfg;
741 RTMP_IO_READ32(pAd, LED_CFG, &LedCfg.word);
742 LedCfg.field.LedPolar = 0;
743 LedCfg.field.RLedMode = 0;
744 LedCfg.field.GLedMode = 0;
745 LedCfg.field.YLedMode = 0;
746 RTMP_IO_WRITE32(pAd, LED_CFG, LedCfg.word);
748 #endif // RT2870 //
751 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
753 MlmeQueueDestroy(&pAd->Mlme.Queue);
754 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
756 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
759 VOID MlmeResetRalinkCounters(
760 IN PRTMP_ADAPTER pAd)
762 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
763 // clear all OneSecxxx counters.
764 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
765 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
766 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
767 pAd->RalinkCounters.OneSecRxOkCnt = 0;
768 pAd->RalinkCounters.OneSecTxFailCount = 0;
769 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
770 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
771 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
773 // TODO: for debug only. to be removed
774 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
775 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
776 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
777 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
778 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
779 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
780 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
781 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
782 pAd->RalinkCounters.OneSecTxDoneCount = 0;
783 pAd->RalinkCounters.OneSecRxCount = 0;
784 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
785 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
787 return;
790 unsigned long rx_AMSDU;
791 unsigned long rx_Total;
794 ==========================================================================
795 Description:
796 This routine is executed periodically to -
797 1. Decide if it's a right time to turn on PwrMgmt bit of all
798 outgoiing frames
799 2. Calculate ChannelQuality based on statistics of the last
800 period, so that TX rate won't toggling very frequently between a
801 successful TX and a failed TX.
802 3. If the calculated ChannelQuality indicated current connection not
803 healthy, then a ROAMing attempt is tried here.
805 IRQL = DISPATCH_LEVEL
807 ==========================================================================
809 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
810 VOID MlmePeriodicExec(
811 IN PVOID SystemSpecific1,
812 IN PVOID FunctionContext,
813 IN PVOID SystemSpecific2,
814 IN PVOID SystemSpecific3)
816 ULONG TxTotalCnt;
817 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
819 // Do nothing if the driver is starting halt state.
820 // This might happen when timer already been fired before cancel timer with mlmehalt
821 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
822 fRTMP_ADAPTER_RADIO_OFF |
823 fRTMP_ADAPTER_RADIO_MEASUREMENT |
824 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
825 return;
827 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
829 #ifdef RALINK_ATE
830 /* Do not show RSSI until "Normal 1 second Mlme PeriodicExec". */
831 if (ATE_ON(pAd))
833 if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE != (MLME_TASK_EXEC_MULTIPLE - 1))
835 pAd->Mlme.PeriodicRound ++;
836 return;
839 #endif // RALINK_ATE //
841 #ifdef CONFIG_STA_SUPPORT
842 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
844 // Do nothing if monitor mode is on
845 if (MONITOR_ON(pAd))
846 return;
848 if (pAd->Mlme.PeriodicRound & 0x1)
850 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
851 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
852 (STA_TGN_WIFI_ON(pAd)) &&
853 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
856 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
857 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
859 else if ((STA_TGN_WIFI_ON(pAd)) &&
860 ((pAd->MACVersion & 0xffff) == 0x0101))
862 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
863 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
867 #endif // CONFIG_STA_SUPPORT //
869 pAd->bUpdateBcnCntDone = FALSE;
871 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
872 pAd->Mlme.PeriodicRound ++;
874 // execute every 500ms
875 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
877 #ifdef CONFIG_STA_SUPPORT
878 // perform dynamic tx rate switching based on past TX history
879 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
881 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
883 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
884 MlmeDynamicTxRateSwitching(pAd);
886 #endif // CONFIG_STA_SUPPORT //
889 // Normal 1 second Mlme PeriodicExec.
890 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
892 pAd->Mlme.OneSecPeriodicRound ++;
894 #ifdef RALINK_ATE
895 if (ATE_ON(pAd))
897 /* request from Baron : move this routine from later to here */
898 /* for showing Rx error count in ATE RXFRAME */
899 NICUpdateRawCounters(pAd);
900 if (pAd->ate.bRxFer == 1)
902 pAd->ate.RxTotalCnt += pAd->ate.RxCntPerSec;
903 ate_print(KERN_EMERG "MlmePeriodicExec: Rx packet cnt = %d/%d\n", pAd->ate.RxCntPerSec, pAd->ate.RxTotalCnt);
904 pAd->ate.RxCntPerSec = 0;
906 if (pAd->ate.RxAntennaSel == 0)
907 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi0=%d, AvgRssi1=%d, AvgRssi2=%d\n\n",
908 pAd->ate.AvgRssi0, pAd->ate.AvgRssi1, pAd->ate.AvgRssi2);
909 else
910 ate_print(KERN_EMERG "MlmePeriodicExec: Rx AvgRssi=%d\n\n", pAd->ate.AvgRssi0);
912 MlmeResetRalinkCounters(pAd);
913 return;
915 #endif // RALINK_ATE //
918 if (rx_Total)
921 // reset counters
922 rx_AMSDU = 0;
923 rx_Total = 0;
926 //ORIBATimerTimeout(pAd);
928 // Media status changed, report to NDIS
929 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
931 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
932 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
934 pAd->IndicateMediaState = NdisMediaStateConnected;
935 RTMP_IndicateMediaState(pAd);
938 else
940 pAd->IndicateMediaState = NdisMediaStateDisconnected;
941 RTMP_IndicateMediaState(pAd);
945 NdisGetSystemUpTime(&pAd->Mlme.Now32);
947 // add the most up-to-date h/w raw counters into software variable, so that
948 // the dynamic tuning mechanism below are based on most up-to-date information
949 NICUpdateRawCounters(pAd);
951 #ifdef RT2870
952 RT2870_WatchDog(pAd);
953 #endif // RT2870 //
955 #ifdef DOT11_N_SUPPORT
956 // Need statistics after read counter. So put after NICUpdateRawCounters
957 ORIBATimerTimeout(pAd);
958 #endif // DOT11_N_SUPPORT //
960 // if MGMT RING is full more than twice within 1 second, we consider there's
961 // a hardware problem stucking the TX path. In this case, try a hardware reset
962 // to recover the system
963 // if (pAd->RalinkCounters.MgmtRingFullCount >= 2)
964 // RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HARDWARE_ERROR);
965 // else
966 // pAd->RalinkCounters.MgmtRingFullCount = 0;
968 // The time period for checking antenna is according to traffic
969 if (pAd->Mlme.bEnableAutoAntennaCheck)
971 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
972 pAd->RalinkCounters.OneSecTxRetryOkCount +
973 pAd->RalinkCounters.OneSecTxFailCount;
975 if (TxTotalCnt > 50)
977 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
979 AsicEvaluateRxAnt(pAd);
982 else
984 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
986 AsicEvaluateRxAnt(pAd);
991 #ifdef CONFIG_STA_SUPPORT
992 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
993 STAMlmePeriodicExec(pAd);
994 #endif // CONFIG_STA_SUPPORT //
996 MlmeResetRalinkCounters(pAd);
998 #ifdef CONFIG_STA_SUPPORT
999 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1002 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
1003 // and sending CTS-to-self over and over.
1004 // Software Patch Solution:
1005 // 1. Polling debug state register 0x10F4 every one second.
1006 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
1007 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
1009 UINT32 MacReg = 0;
1011 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
1012 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
1014 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
1015 RTMPusecDelay(1);
1016 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
1018 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
1022 #endif // CONFIG_STA_SUPPORT //
1024 RT28XX_MLME_HANDLER(pAd);
1028 pAd->bUpdateBcnCntDone = FALSE;
1031 #ifdef CONFIG_STA_SUPPORT
1032 VOID STAMlmePeriodicExec(
1033 PRTMP_ADAPTER pAd)
1035 ULONG TxTotalCnt;
1036 int i;
1039 // We return here in ATE mode, because the statistics
1040 // that ATE needs are not collected via this routine.
1042 #ifdef RALINK_ATE
1043 // It is supposed that we will never reach here in ATE mode.
1044 ASSERT(!(ATE_ON(pAd)));
1045 if (ATE_ON(pAd))
1046 return;
1047 #endif // RALINK_ATE //
1049 #ifdef WPA_SUPPLICANT_SUPPORT
1050 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1051 #endif // WPA_SUPPLICANT_SUPPORT //
1053 // WPA MIC error should block association attempt for 60 seconds
1054 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1055 pAd->StaCfg.bBlockAssoc = FALSE;
1058 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1060 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1062 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1064 pAd->PreMediaState = pAd->IndicateMediaState;
1070 AsicStaBbpTuning(pAd);
1072 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1073 pAd->RalinkCounters.OneSecTxRetryOkCount +
1074 pAd->RalinkCounters.OneSecTxFailCount;
1076 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1078 // update channel quality for Roaming and UI LinkQuality display
1079 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1082 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1083 // Radio is currently in noisy environment
1084 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1085 AsicAdjustTxPower(pAd);
1087 if (INFRA_ON(pAd))
1089 #ifdef QOS_DLS_SUPPORT
1090 // Check DLS time out, then tear down those session
1091 RTMPCheckDLSTimeOut(pAd);
1092 #endif // QOS_DLS_SUPPORT //
1094 // Is PSM bit consistent with user power management policy?
1095 // This is the only place that will set PSM bit ON.
1096 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1097 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1099 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1101 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1102 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1103 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1105 RTMPSetAGCInitValue(pAd, BW_20);
1106 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1109 //if ((pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
1110 // (pAd->RalinkCounters.OneSecTxRetryOkCount == 0))
1112 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1114 // When APSD is enabled, the period changes as 20 sec
1115 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1116 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1118 else
1120 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1121 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1123 if (pAd->CommonCfg.bWmmCapable)
1124 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1125 else
1126 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1131 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1133 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1134 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1135 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1137 // Lost AP, send disconnect & link down event
1138 LinkDown(pAd, FALSE);
1140 #ifdef WPA_SUPPLICANT_SUPPORT
1141 #ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
1142 if (pAd->StaCfg.WpaSupplicantUP)
1144 union iwreq_data wrqu;
1145 //send disassociate event to wpa_supplicant
1146 memset(&wrqu, 0, sizeof(wrqu));
1147 wrqu.data.flags = RT_DISASSOC_EVENT_FLAG;
1148 wireless_send_event(pAd->net_dev, IWEVCUSTOM, &wrqu, NULL);
1150 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1151 #endif // WPA_SUPPLICANT_SUPPORT //
1153 #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
1155 union iwreq_data wrqu;
1156 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1157 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1159 #endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
1161 // RTMPPatchMacBbpBug(pAd);
1162 MlmeAutoReconnectLastSSID(pAd);
1164 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1166 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1167 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1168 MlmeAutoReconnectLastSSID(pAd);
1171 // Add auto seamless roaming
1172 if (pAd->StaCfg.bFastRoaming)
1174 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1176 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));
1178 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1180 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1184 else if (ADHOC_ON(pAd))
1186 //radar detect
1187 if ((pAd->CommonCfg.Channel > 14)
1188 && (pAd->CommonCfg.bIEEE80211H == 1)
1189 && RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
1191 RadarDetectPeriodic(pAd);
1194 // If all peers leave, and this STA becomes the last one in this IBSS, then change MediaState
1195 // to DISCONNECTED. But still holding this IBSS (i.e. sending BEACON) so that other STAs can
1196 // join later.
1197 if ((pAd->StaCfg.LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32) &&
1198 OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1200 MLME_START_REQ_STRUCT StartReq;
1202 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - excessive BEACON lost, last STA in this IBSS, MediaState=Disconnected\n"));
1203 LinkDown(pAd, FALSE);
1205 StartParmFill(pAd, &StartReq, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen);
1206 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_START_REQ, sizeof(MLME_START_REQ_STRUCT), &StartReq);
1207 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_START;
1210 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1212 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i];
1214 if (pEntry->ValidAsCLI == FALSE)
1215 continue;
1217 if (pEntry->LastBeaconRxTime + ADHOC_BEACON_LOST_TIME < pAd->Mlme.Now32)
1218 MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
1221 else // no INFRA nor ADHOC connection
1224 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1225 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1226 goto SKIP_AUTO_SCAN_CONN;
1227 else
1228 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1230 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1231 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1232 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1234 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1236 MLME_SCAN_REQ_STRUCT ScanReq;
1238 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1240 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1241 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1242 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1243 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1244 // Reset Missed scan number
1245 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1247 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1248 MlmeAutoReconnectLastSSID(pAd);
1250 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1252 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1254 MlmeAutoScan(pAd);
1255 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1257 else
1259 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1260 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1262 if ((pAd->Mlme.OneSecPeriodicRound % 5) == 1)
1263 MlmeAutoReconnectLastSSID(pAd);
1265 else
1266 #endif // CARRIER_DETECTION_SUPPORT //
1267 MlmeAutoReconnectLastSSID(pAd);
1273 SKIP_AUTO_SCAN_CONN:
1275 #ifdef DOT11_N_SUPPORT
1276 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1278 pAd->MacTab.fAnyBASession = TRUE;
1279 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1281 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1283 pAd->MacTab.fAnyBASession = FALSE;
1284 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1286 #endif // DOT11_N_SUPPORT //
1289 #ifdef DOT11_N_SUPPORT
1290 #ifdef DOT11N_DRAFT3
1291 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040))
1292 TriEventCounterMaintenance(pAd);
1293 #endif // DOT11N_DRAFT3 //
1294 #endif // DOT11_N_SUPPORT //
1296 return;
1299 // Link down report
1300 VOID LinkDownExec(
1301 IN PVOID SystemSpecific1,
1302 IN PVOID FunctionContext,
1303 IN PVOID SystemSpecific2,
1304 IN PVOID SystemSpecific3)
1307 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1309 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1310 RTMP_IndicateMediaState(pAd);
1311 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1314 // IRQL = DISPATCH_LEVEL
1315 VOID MlmeAutoScan(
1316 IN PRTMP_ADAPTER pAd)
1318 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1319 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1321 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1322 MlmeEnqueue(pAd,
1323 MLME_CNTL_STATE_MACHINE,
1324 OID_802_11_BSSID_LIST_SCAN,
1326 NULL);
1327 RT28XX_MLME_HANDLER(pAd);
1331 // IRQL = DISPATCH_LEVEL
1332 VOID MlmeAutoReconnectLastSSID(
1333 IN PRTMP_ADAPTER pAd)
1337 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1338 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1339 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1341 NDIS_802_11_SSID OidSsid;
1342 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1343 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1345 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1346 MlmeEnqueue(pAd,
1347 MLME_CNTL_STATE_MACHINE,
1348 OID_802_11_SSID,
1349 sizeof(NDIS_802_11_SSID),
1350 &OidSsid);
1351 RT28XX_MLME_HANDLER(pAd);
1354 #endif // CONFIG_STA_SUPPORT //
1357 ==========================================================================
1358 Validate SSID for connection try and rescan purpose
1359 Valid SSID will have visible chars only.
1360 The valid length is from 0 to 32.
1361 IRQL = DISPATCH_LEVEL
1362 ==========================================================================
1364 BOOLEAN MlmeValidateSSID(
1365 IN PUCHAR pSsid,
1366 IN UCHAR SsidLen)
1368 int index;
1370 if (SsidLen > MAX_LEN_OF_SSID)
1371 return (FALSE);
1373 // Check each character value
1374 for (index = 0; index < SsidLen; index++)
1376 if (pSsid[index] < 0x20)
1377 return (FALSE);
1380 // All checked
1381 return (TRUE);
1384 VOID MlmeSelectTxRateTable(
1385 IN PRTMP_ADAPTER pAd,
1386 IN PMAC_TABLE_ENTRY pEntry,
1387 IN PUCHAR *ppTable,
1388 IN PUCHAR pTableSize,
1389 IN PUCHAR pInitTxRateIdx)
1393 // decide the rate table for tuning
1394 if (pAd->CommonCfg.TxRateTableSize > 0)
1396 *ppTable = RateSwitchTable;
1397 *pTableSize = RateSwitchTable[0];
1398 *pInitTxRateIdx = RateSwitchTable[1];
1400 break;
1403 #ifdef CONFIG_STA_SUPPORT
1404 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1406 #ifdef DOT11_N_SUPPORT
1407 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1408 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1409 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1410 {// 11N 1S Adhoc
1411 *ppTable = RateSwitchTable11N1S;
1412 *pTableSize = RateSwitchTable11N1S[0];
1413 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1416 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1417 (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1418 (pEntry->HTCapability.MCSSet[1] == 0xff) &&
1419 (pAd->Antenna.field.TxPath == 2))
1420 {// 11N 2S Adhoc
1421 if (pAd->LatchRfRegs.Channel <= 14)
1423 *ppTable = RateSwitchTable11N2S;
1424 *pTableSize = RateSwitchTable11N2S[0];
1425 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1427 else
1429 *ppTable = RateSwitchTable11N2SForABand;
1430 *pTableSize = RateSwitchTable11N2SForABand[0];
1431 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1435 else
1436 #endif // DOT11_N_SUPPORT //
1437 if ((pEntry->RateLen == 4)
1438 #ifdef DOT11_N_SUPPORT
1439 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1440 #endif // DOT11_N_SUPPORT //
1443 *ppTable = RateSwitchTable11B;
1444 *pTableSize = RateSwitchTable11B[0];
1445 *pInitTxRateIdx = RateSwitchTable11B[1];
1448 else if (pAd->LatchRfRegs.Channel <= 14)
1450 *ppTable = RateSwitchTable11BG;
1451 *pTableSize = RateSwitchTable11BG[0];
1452 *pInitTxRateIdx = RateSwitchTable11BG[1];
1455 else
1457 *ppTable = RateSwitchTable11G;
1458 *pTableSize = RateSwitchTable11G[0];
1459 *pInitTxRateIdx = RateSwitchTable11G[1];
1462 break;
1464 #endif // CONFIG_STA_SUPPORT //
1466 #ifdef DOT11_N_SUPPORT
1467 //if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1468 // ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1469 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1470 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1471 {// 11BGN 1S AP
1472 *ppTable = RateSwitchTable11BGN1S;
1473 *pTableSize = RateSwitchTable11BGN1S[0];
1474 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1476 break;
1479 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1480 // (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1481 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1482 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1483 {// 11BGN 2S AP
1484 if (pAd->LatchRfRegs.Channel <= 14)
1486 *ppTable = RateSwitchTable11BGN2S;
1487 *pTableSize = RateSwitchTable11BGN2S[0];
1488 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1491 else
1493 *ppTable = RateSwitchTable11BGN2SForABand;
1494 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1495 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1498 break;
1501 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1502 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1503 {// 11N 1S AP
1504 *ppTable = RateSwitchTable11N1S;
1505 *pTableSize = RateSwitchTable11N1S[0];
1506 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1508 break;
1511 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2))
1512 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1513 {// 11N 2S AP
1514 if (pAd->LatchRfRegs.Channel <= 14)
1516 *ppTable = RateSwitchTable11N2S;
1517 *pTableSize = RateSwitchTable11N2S[0];
1518 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1520 else
1522 *ppTable = RateSwitchTable11N2SForABand;
1523 *pTableSize = RateSwitchTable11N2SForABand[0];
1524 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1527 break;
1529 #endif // DOT11_N_SUPPORT //
1530 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1531 if ((pEntry->RateLen == 4)
1532 #ifdef DOT11_N_SUPPORT
1533 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1534 #endif // DOT11_N_SUPPORT //
1536 {// B only AP
1537 *ppTable = RateSwitchTable11B;
1538 *pTableSize = RateSwitchTable11B[0];
1539 *pInitTxRateIdx = RateSwitchTable11B[1];
1541 break;
1544 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1545 if ((pEntry->RateLen > 8)
1546 #ifdef DOT11_N_SUPPORT
1547 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1548 #endif // DOT11_N_SUPPORT //
1550 {// B/G mixed AP
1551 *ppTable = RateSwitchTable11BG;
1552 *pTableSize = RateSwitchTable11BG[0];
1553 *pInitTxRateIdx = RateSwitchTable11BG[1];
1555 break;
1558 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1559 if ((pEntry->RateLen == 8)
1560 #ifdef DOT11_N_SUPPORT
1561 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1562 #endif // DOT11_N_SUPPORT //
1564 {// G only AP
1565 *ppTable = RateSwitchTable11G;
1566 *pTableSize = RateSwitchTable11G[0];
1567 *pInitTxRateIdx = RateSwitchTable11G[1];
1569 break;
1571 #ifdef DOT11_N_SUPPORT
1572 #endif // DOT11_N_SUPPORT //
1574 #ifdef CONFIG_STA_SUPPORT
1575 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1577 #ifdef DOT11_N_SUPPORT
1578 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1579 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1580 #endif // DOT11_N_SUPPORT //
1581 { // Legacy mode
1582 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1584 *ppTable = RateSwitchTable11B;
1585 *pTableSize = RateSwitchTable11B[0];
1586 *pInitTxRateIdx = RateSwitchTable11B[1];
1588 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1590 *ppTable = RateSwitchTable11G;
1591 *pTableSize = RateSwitchTable11G[0];
1592 *pInitTxRateIdx = RateSwitchTable11G[1];
1595 else
1597 *ppTable = RateSwitchTable11BG;
1598 *pTableSize = RateSwitchTable11BG[0];
1599 *pInitTxRateIdx = RateSwitchTable11BG[1];
1601 break;
1603 #ifdef DOT11_N_SUPPORT
1604 if (pAd->LatchRfRegs.Channel <= 14)
1606 if (pAd->CommonCfg.TxStream == 1)
1608 *ppTable = RateSwitchTable11N1S;
1609 *pTableSize = RateSwitchTable11N1S[0];
1610 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1611 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1613 else
1615 *ppTable = RateSwitchTable11N2S;
1616 *pTableSize = RateSwitchTable11N2S[0];
1617 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1618 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1621 else
1623 if (pAd->CommonCfg.TxStream == 1)
1625 *ppTable = RateSwitchTable11N1S;
1626 *pTableSize = RateSwitchTable11N1S[0];
1627 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1628 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1630 else
1632 *ppTable = RateSwitchTable11N2SForABand;
1633 *pTableSize = RateSwitchTable11N2SForABand[0];
1634 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1635 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1638 #endif // DOT11_N_SUPPORT //
1639 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1640 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1642 #endif // CONFIG_STA_SUPPORT //
1643 } while(FALSE);
1646 #ifdef CONFIG_STA_SUPPORT
1648 ==========================================================================
1649 Description:
1650 This routine checks if there're other APs out there capable for
1651 roaming. Caller should call this routine only when Link up in INFRA mode
1652 and channel quality is below CQI_GOOD_THRESHOLD.
1654 IRQL = DISPATCH_LEVEL
1656 Output:
1657 ==========================================================================
1659 VOID MlmeCheckForRoaming(
1660 IN PRTMP_ADAPTER pAd,
1661 IN ULONG Now32)
1663 USHORT i;
1664 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1665 BSS_ENTRY *pBss;
1667 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1668 // put all roaming candidates into RoamTab, and sort in RSSI order
1669 BssTableInit(pRoamTab);
1670 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1672 pBss = &pAd->ScanTab.BssEntry[i];
1674 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1675 continue; // AP disappear
1676 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1677 continue; // RSSI too weak. forget it.
1678 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1679 continue; // skip current AP
1680 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1681 continue; // only AP with stronger RSSI is eligible for roaming
1683 // AP passing all above rules is put into roaming candidate table
1684 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1685 pRoamTab->BssNr += 1;
1688 if (pRoamTab->BssNr > 0)
1690 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1691 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1693 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1694 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1695 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1696 RT28XX_MLME_HANDLER(pAd);
1699 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1703 ==========================================================================
1704 Description:
1705 This routine checks if there're other APs out there capable for
1706 roaming. Caller should call this routine only when link up in INFRA mode
1707 and channel quality is below CQI_GOOD_THRESHOLD.
1709 IRQL = DISPATCH_LEVEL
1711 Output:
1712 ==========================================================================
1714 VOID MlmeCheckForFastRoaming(
1715 IN PRTMP_ADAPTER pAd,
1716 IN ULONG Now)
1718 USHORT i;
1719 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1720 BSS_ENTRY *pBss;
1722 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1723 // put all roaming candidates into RoamTab, and sort in RSSI order
1724 BssTableInit(pRoamTab);
1725 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1727 pBss = &pAd->ScanTab.BssEntry[i];
1729 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1730 continue; // RSSI too weak. forget it.
1731 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1732 continue; // skip current AP
1733 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1734 continue; // skip different SSID
1735 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1736 continue; // skip AP without better RSSI
1738 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));
1739 // AP passing all above rules is put into roaming candidate table
1740 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1741 pRoamTab->BssNr += 1;
1744 if (pRoamTab->BssNr > 0)
1746 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1747 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1749 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1750 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1751 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1752 RT28XX_MLME_HANDLER(pAd);
1755 // Maybe site survey required
1756 else
1758 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1760 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1761 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1762 pAd->StaCfg.ScanCnt = 2;
1763 pAd->StaCfg.LastScanTime = Now;
1764 MlmeAutoScan(pAd);
1768 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1772 ==========================================================================
1773 Description:
1774 This routine calculates TxPER, RxPER of the past N-sec period. And
1775 according to the calculation result, ChannelQuality is calculated here
1776 to decide if current AP is still doing the job.
1778 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1779 Output:
1780 StaCfg.ChannelQuality - 0..100
1782 IRQL = DISPATCH_LEVEL
1784 NOTE: This routine decide channle quality based on RX CRC error ratio.
1785 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1786 is performed right before this routine, so that this routine can decide
1787 channel quality based on the most up-to-date information
1788 ==========================================================================
1790 VOID MlmeCalculateChannelQuality(
1791 IN PRTMP_ADAPTER pAd,
1792 IN ULONG Now32)
1794 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1795 ULONG RxCnt, RxPER;
1796 UCHAR NorRssi;
1797 CHAR MaxRssi;
1798 ULONG BeaconLostTime = BEACON_LOST_TIME;
1800 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
1801 // longer beacon lost time when carrier detection enabled
1802 if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
1804 BeaconLostTime = BEACON_LOST_TIME + BEACON_LOST_TIME/2;
1806 #endif // CARRIER_DETECTION_SUPPORT //
1808 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1811 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1813 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1814 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1815 if (TxCnt < 5)
1817 TxPER = 0;
1818 TxPRR = 0;
1820 else
1822 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1823 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1827 // calculate RX PER - don't take RxPER into consideration if too few sample
1829 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1830 if (RxCnt < 5)
1831 RxPER = 0;
1832 else
1833 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1836 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1838 if (INFRA_ON(pAd) &&
1839 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1840 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1842 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1843 pAd->Mlme.ChannelQuality = 0;
1845 else
1847 // Normalize Rssi
1848 if (MaxRssi > -40)
1849 NorRssi = 100;
1850 else if (MaxRssi < -90)
1851 NorRssi = 0;
1852 else
1853 NorRssi = (MaxRssi + 90) * 2;
1855 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1856 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1857 TX_WEIGHTING * (100 - TxPRR) +
1858 RX_WEIGHTING* (100 - RxPER)) / 100;
1859 if (pAd->Mlme.ChannelQuality >= 100)
1860 pAd->Mlme.ChannelQuality = 100;
1865 VOID MlmeSetTxRate(
1866 IN PRTMP_ADAPTER pAd,
1867 IN PMAC_TABLE_ENTRY pEntry,
1868 IN PRTMP_TX_RATE_SWITCH pTxRate)
1870 UCHAR MaxMode = MODE_OFDM;
1872 #ifdef DOT11_N_SUPPORT
1873 MaxMode = MODE_HTGREENFIELD;
1875 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1876 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1877 else
1878 #endif // DOT11_N_SUPPORT //
1879 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1881 if (pTxRate->CurrMCS < MCS_AUTO)
1882 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1884 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1885 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1887 if (ADHOC_ON(pAd))
1889 // If peer adhoc is b-only mode, we can't send 11g rate.
1890 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1891 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1894 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1896 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1897 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1898 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1900 // Patch speed error in status page
1901 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1903 else
1905 if (pTxRate->Mode <= MaxMode)
1906 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1908 #ifdef DOT11_N_SUPPORT
1909 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1910 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1911 else
1912 #endif // DOT11_N_SUPPORT //
1913 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1915 #ifdef DOT11_N_SUPPORT
1916 // Reexam each bandwidth's SGI support.
1917 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1919 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1920 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1921 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1922 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1925 // Turn RTS/CTS rate to 6Mbps.
1926 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1928 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1929 if (pAd->MacTab.fAnyBASession)
1931 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1933 else
1935 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1938 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1940 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1941 if (pAd->MacTab.fAnyBASession)
1943 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1945 else
1947 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1950 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1952 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1955 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1957 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1959 #endif // DOT11_N_SUPPORT //
1961 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1962 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1963 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1964 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1965 #ifdef DOT11_N_SUPPORT
1966 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1967 pAd->WIFItestbed.bGreenField)
1968 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1969 #endif // DOT11_N_SUPPORT //
1972 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1976 ==========================================================================
1977 Description:
1978 This routine calculates the acumulated TxPER of eaxh TxRate. And
1979 according to the calculation result, change CommonCfg.TxRate which
1980 is the stable TX Rate we expect the Radio situation could sustained.
1982 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1983 Output:
1984 CommonCfg.TxRate -
1986 IRQL = DISPATCH_LEVEL
1988 NOTE:
1989 call this routine every second
1990 ==========================================================================
1992 VOID MlmeDynamicTxRateSwitching(
1993 IN PRTMP_ADAPTER pAd)
1995 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1996 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1997 ULONG TxErrorRatio = 0;
1998 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1999 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2000 PUCHAR pTable;
2001 UCHAR TableSize = 0;
2002 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2003 CHAR Rssi, RssiOffset = 0;
2004 TX_STA_CNT1_STRUC StaTx1;
2005 TX_STA_CNT0_STRUC TxStaCnt0;
2006 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2007 MAC_TABLE_ENTRY *pEntry;
2009 #ifdef RALINK_ATE
2010 if (ATE_ON(pAd))
2012 return;
2014 #endif // RALINK_ATE //
2017 // walk through MAC table, see if need to change AP's TX rate toward each entry
2019 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2021 pEntry = &pAd->MacTab.Content[i];
2023 // check if this entry need to switch rate automatically
2024 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2025 continue;
2027 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
2029 Rssi = RTMPMaxRssi(pAd,
2030 pAd->StaCfg.RssiSample.AvgRssi0,
2031 pAd->StaCfg.RssiSample.AvgRssi1,
2032 pAd->StaCfg.RssiSample.AvgRssi2);
2034 // Update statistic counter
2035 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2036 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2037 pAd->bUpdateBcnCntDone = TRUE;
2038 TxRetransmit = StaTx1.field.TxRetransmit;
2039 TxSuccess = StaTx1.field.TxSuccess;
2040 TxFailCount = TxStaCnt0.field.TxFailCount;
2041 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2043 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2044 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2045 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2046 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2047 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2048 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2050 // if no traffic in the past 1-sec period, don't change TX rate,
2051 // but clear all bad history. because the bad history may affect the next
2052 // Chariot throughput test
2053 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2054 pAd->RalinkCounters.OneSecTxRetryOkCount +
2055 pAd->RalinkCounters.OneSecTxFailCount;
2057 if (TxTotalCnt)
2058 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2060 else
2062 if (INFRA_ON(pAd) && (i == 1))
2063 Rssi = RTMPMaxRssi(pAd,
2064 pAd->StaCfg.RssiSample.AvgRssi0,
2065 pAd->StaCfg.RssiSample.AvgRssi1,
2066 pAd->StaCfg.RssiSample.AvgRssi2);
2067 else
2068 Rssi = RTMPMaxRssi(pAd,
2069 pEntry->RssiSample.AvgRssi0,
2070 pEntry->RssiSample.AvgRssi1,
2071 pEntry->RssiSample.AvgRssi2);
2073 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2074 pEntry->OneSecTxRetryOkCount +
2075 pEntry->OneSecTxFailCount;
2077 if (TxTotalCnt)
2078 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2081 CurrRateIdx = pEntry->CurrTxRateIndex;
2083 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2085 if (CurrRateIdx >= TableSize)
2087 CurrRateIdx = TableSize - 1;
2090 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2091 // So need to sync here.
2092 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2093 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2094 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2098 // Need to sync Real Tx rate and our record.
2099 // Then return for next DRS.
2100 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2101 pEntry->CurrTxRateIndex = InitTxRateIdx;
2102 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2104 // reset all OneSecTx counters
2105 RESET_ONE_SEC_TX_CNT(pEntry);
2106 continue;
2109 // decide the next upgrade rate and downgrade rate, if any
2110 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2112 UpRateIdx = CurrRateIdx + 1;
2113 DownRateIdx = CurrRateIdx -1;
2115 else if (CurrRateIdx == 0)
2117 UpRateIdx = CurrRateIdx + 1;
2118 DownRateIdx = CurrRateIdx;
2120 else if (CurrRateIdx == (TableSize - 1))
2122 UpRateIdx = CurrRateIdx;
2123 DownRateIdx = CurrRateIdx - 1;
2126 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2128 #ifdef DOT11_N_SUPPORT
2129 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2131 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2132 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2134 else
2135 #endif // DOT11_N_SUPPORT //
2137 TrainUp = pCurrTxRate->TrainUp;
2138 TrainDown = pCurrTxRate->TrainDown;
2141 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2144 // Keep the last time TxRateChangeAction status.
2146 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2151 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2152 // (criteria copied from RT2500 for Netopia case)
2154 if (TxTotalCnt <= 15)
2156 CHAR idx = 0;
2157 UCHAR TxRateIdx;
2158 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2159 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2160 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2161 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2163 // check the existence and index of each needed MCS
2164 while (idx < pTable[0])
2166 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2168 if (pCurrTxRate->CurrMCS == MCS_0)
2170 MCS0 = idx;
2172 else if (pCurrTxRate->CurrMCS == MCS_1)
2174 MCS1 = idx;
2176 else if (pCurrTxRate->CurrMCS == MCS_2)
2178 MCS2 = idx;
2180 else if (pCurrTxRate->CurrMCS == MCS_3)
2182 MCS3 = idx;
2184 else if (pCurrTxRate->CurrMCS == MCS_4)
2186 MCS4 = idx;
2188 else if (pCurrTxRate->CurrMCS == MCS_5)
2190 MCS5 = idx;
2192 else if (pCurrTxRate->CurrMCS == MCS_6)
2194 MCS6 = idx;
2196 //else if (pCurrTxRate->CurrMCS == MCS_7)
2197 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2199 MCS7 = idx;
2201 else if (pCurrTxRate->CurrMCS == MCS_12)
2203 MCS12 = idx;
2205 else if (pCurrTxRate->CurrMCS == MCS_13)
2207 MCS13 = idx;
2209 else if (pCurrTxRate->CurrMCS == MCS_14)
2211 MCS14 = idx;
2213 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2214 else if ((pCurrTxRate->CurrMCS == MCS_15) && (pCurrTxRate->ShortGI == GI_800)) //we hope to use ShortGI as initial rate, however Atheros's chip has bugs when short GI
2216 MCS15 = idx;
2218 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2220 MCS20 = idx;
2222 else if (pCurrTxRate->CurrMCS == MCS_21)
2224 MCS21 = idx;
2226 else if (pCurrTxRate->CurrMCS == MCS_22)
2228 MCS22 = idx;
2230 else if (pCurrTxRate->CurrMCS == MCS_23)
2232 MCS23 = idx;
2234 idx ++;
2237 if (pAd->LatchRfRegs.Channel <= 14)
2239 if (pAd->NicConfig2.field.ExternalLNAForG)
2241 RssiOffset = 2;
2243 else
2245 RssiOffset = 5;
2248 else
2250 if (pAd->NicConfig2.field.ExternalLNAForA)
2252 RssiOffset = 5;
2254 else
2256 RssiOffset = 8;
2259 #ifdef DOT11_N_SUPPORT
2260 /*if (MCS15)*/
2261 if ((pTable == RateSwitchTable11BGN3S) ||
2262 (pTable == RateSwitchTable11N3S) ||
2263 (pTable == RateSwitchTable))
2264 {// N mode with 3 stream // 3*3
2265 if (MCS23 && (Rssi >= -70))
2266 TxRateIdx = MCS15;
2267 else if (MCS22 && (Rssi >= -72))
2268 TxRateIdx = MCS14;
2269 else if (MCS21 && (Rssi >= -76))
2270 TxRateIdx = MCS13;
2271 else if (MCS20 && (Rssi >= -78))
2272 TxRateIdx = MCS12;
2273 else if (MCS4 && (Rssi >= -82))
2274 TxRateIdx = MCS4;
2275 else if (MCS3 && (Rssi >= -84))
2276 TxRateIdx = MCS3;
2277 else if (MCS2 && (Rssi >= -86))
2278 TxRateIdx = MCS2;
2279 else if (MCS1 && (Rssi >= -88))
2280 TxRateIdx = MCS1;
2281 else
2282 TxRateIdx = MCS0;
2284 // else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand) || (pTable == RateSwitchTable))
2285 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2286 {// N mode with 2 stream
2287 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2288 TxRateIdx = MCS15;
2289 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2290 TxRateIdx = MCS14;
2291 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2292 TxRateIdx = MCS13;
2293 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2294 TxRateIdx = MCS12;
2295 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2296 TxRateIdx = MCS4;
2297 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2298 TxRateIdx = MCS3;
2299 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2300 TxRateIdx = MCS2;
2301 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2302 TxRateIdx = MCS1;
2303 else
2304 TxRateIdx = MCS0;
2306 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2307 {// N mode with 1 stream
2308 if (MCS7 && (Rssi > (-72+RssiOffset)))
2309 TxRateIdx = MCS7;
2310 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2311 TxRateIdx = MCS6;
2312 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2313 TxRateIdx = MCS5;
2314 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2315 TxRateIdx = MCS4;
2316 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2317 TxRateIdx = MCS3;
2318 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2319 TxRateIdx = MCS2;
2320 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2321 TxRateIdx = MCS1;
2322 else
2323 TxRateIdx = MCS0;
2325 else
2326 #endif // DOT11_N_SUPPORT //
2327 {// Legacy mode
2328 if (MCS7 && (Rssi > -70))
2329 TxRateIdx = MCS7;
2330 else if (MCS6 && (Rssi > -74))
2331 TxRateIdx = MCS6;
2332 else if (MCS5 && (Rssi > -78))
2333 TxRateIdx = MCS5;
2334 else if (MCS4 && (Rssi > -82))
2335 TxRateIdx = MCS4;
2336 else if (MCS4 == 0) // for B-only mode
2337 TxRateIdx = MCS3;
2338 else if (MCS3 && (Rssi > -85))
2339 TxRateIdx = MCS3;
2340 else if (MCS2 && (Rssi > -87))
2341 TxRateIdx = MCS2;
2342 else if (MCS1 && (Rssi > -90))
2343 TxRateIdx = MCS1;
2344 else
2345 TxRateIdx = MCS0;
2348 // if (TxRateIdx != pAd->CommonCfg.TxRateIndex)
2350 pEntry->CurrTxRateIndex = TxRateIdx;
2351 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2352 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2355 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2356 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2357 pEntry->fLastSecAccordingRSSI = TRUE;
2358 // reset all OneSecTx counters
2359 RESET_ONE_SEC_TX_CNT(pEntry);
2361 continue;
2364 if (pEntry->fLastSecAccordingRSSI == TRUE)
2366 pEntry->fLastSecAccordingRSSI = FALSE;
2367 pEntry->LastSecTxRateChangeAction = 0;
2368 // reset all OneSecTx counters
2369 RESET_ONE_SEC_TX_CNT(pEntry);
2371 continue;
2376 BOOLEAN bTrainUpDown = FALSE;
2378 pEntry->CurrTxRateStableTime ++;
2380 // downgrade TX quality if PER >= Rate-Down threshold
2381 if (TxErrorRatio >= TrainDown)
2383 bTrainUpDown = TRUE;
2384 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2386 // upgrade TX quality if PER <= Rate-Up threshold
2387 else if (TxErrorRatio <= TrainUp)
2389 bTrainUpDown = TRUE;
2390 bUpgradeQuality = TRUE;
2391 if (pEntry->TxQuality[CurrRateIdx])
2392 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2394 if (pEntry->TxRateUpPenalty)
2395 pEntry->TxRateUpPenalty --;
2396 else if (pEntry->TxQuality[UpRateIdx])
2397 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2400 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2402 if (bTrainUpDown)
2404 // perform DRS - consider TxRate Down first, then rate up.
2405 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2407 pEntry->CurrTxRateIndex = DownRateIdx;
2409 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2411 pEntry->CurrTxRateIndex = UpRateIdx;
2414 } while (FALSE);
2416 // if rate-up happen, clear all bad history of all TX rates
2417 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2419 pEntry->CurrTxRateStableTime = 0;
2420 pEntry->TxRateUpPenalty = 0;
2421 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2422 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2423 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2426 // For TxRate fast train up
2428 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2430 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2432 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2434 bTxRateChanged = TRUE;
2436 // if rate-down happen, only clear DownRate's bad history
2437 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2439 pEntry->CurrTxRateStableTime = 0;
2440 pEntry->TxRateUpPenalty = 0; // no penalty
2441 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2442 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2443 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2446 // For TxRate fast train down
2448 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2450 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2452 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2454 bTxRateChanged = TRUE;
2456 else
2458 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2459 bTxRateChanged = FALSE;
2462 pEntry->LastTxOkCount = TxSuccess;
2464 // reset all OneSecTx counters
2465 RESET_ONE_SEC_TX_CNT(pEntry);
2467 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2468 if (bTxRateChanged && pNextTxRate)
2470 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2476 ========================================================================
2477 Routine Description:
2478 Station side, Auto TxRate faster train up timer call back function.
2480 Arguments:
2481 SystemSpecific1 - Not used.
2482 FunctionContext - Pointer to our Adapter context.
2483 SystemSpecific2 - Not used.
2484 SystemSpecific3 - Not used.
2486 Return Value:
2487 None
2489 ========================================================================
2491 VOID StaQuickResponeForRateUpExec(
2492 IN PVOID SystemSpecific1,
2493 IN PVOID FunctionContext,
2494 IN PVOID SystemSpecific2,
2495 IN PVOID SystemSpecific3)
2497 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2498 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2499 ULONG TxTotalCnt;
2500 ULONG TxErrorRatio = 0;
2501 BOOLEAN bTxRateChanged; //, bUpgradeQuality = FALSE;
2502 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2503 PUCHAR pTable;
2504 UCHAR TableSize = 0;
2505 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2506 TX_STA_CNT1_STRUC StaTx1;
2507 TX_STA_CNT0_STRUC TxStaCnt0;
2508 CHAR Rssi, ratio;
2509 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2510 MAC_TABLE_ENTRY *pEntry;
2511 ULONG i;
2513 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2516 // walk through MAC table, see if need to change AP's TX rate toward each entry
2518 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2520 pEntry = &pAd->MacTab.Content[i];
2522 // check if this entry need to switch rate automatically
2523 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2524 continue;
2526 if (INFRA_ON(pAd) && (i == 1))
2527 Rssi = RTMPMaxRssi(pAd,
2528 pAd->StaCfg.RssiSample.AvgRssi0,
2529 pAd->StaCfg.RssiSample.AvgRssi1,
2530 pAd->StaCfg.RssiSample.AvgRssi2);
2531 else
2532 Rssi = RTMPMaxRssi(pAd,
2533 pEntry->RssiSample.AvgRssi0,
2534 pEntry->RssiSample.AvgRssi1,
2535 pEntry->RssiSample.AvgRssi2);
2537 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2539 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2541 // decide the next upgrade rate and downgrade rate, if any
2542 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2544 UpRateIdx = CurrRateIdx + 1;
2545 DownRateIdx = CurrRateIdx -1;
2547 else if (CurrRateIdx == 0)
2549 UpRateIdx = CurrRateIdx + 1;
2550 DownRateIdx = CurrRateIdx;
2552 else if (CurrRateIdx == (TableSize - 1))
2554 UpRateIdx = CurrRateIdx;
2555 DownRateIdx = CurrRateIdx - 1;
2558 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2560 #ifdef DOT11_N_SUPPORT
2561 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2563 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2564 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2566 else
2567 #endif // DOT11_N_SUPPORT //
2569 TrainUp = pCurrTxRate->TrainUp;
2570 TrainDown = pCurrTxRate->TrainDown;
2573 if (pAd->MacTab.Size == 1)
2575 // Update statistic counter
2576 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2577 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2579 TxRetransmit = StaTx1.field.TxRetransmit;
2580 TxSuccess = StaTx1.field.TxSuccess;
2581 TxFailCount = TxStaCnt0.field.TxFailCount;
2582 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2584 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2585 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2586 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2587 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2588 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2589 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2591 #if 0 // test by Gary.
2592 // if no traffic in the past 1-sec period, don't change TX rate,
2593 // but clear all bad history. because the bad history may affect the next
2594 // Chariot throughput test
2595 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2596 pAd->RalinkCounters.OneSecTxRetryOkCount +
2597 pAd->RalinkCounters.OneSecTxFailCount;
2598 #endif
2599 if (TxTotalCnt)
2600 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2602 else
2604 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2605 pEntry->OneSecTxRetryOkCount +
2606 pEntry->OneSecTxFailCount;
2608 if (TxTotalCnt)
2609 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2614 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2615 // (criteria copied from RT2500 for Netopia case)
2617 if (TxTotalCnt <= 12)
2619 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2620 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2622 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2624 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2625 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2627 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2629 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2632 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2633 return;
2638 ULONG OneSecTxNoRetryOKRationCount;
2640 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2641 ratio = 5;
2642 else
2643 ratio = 4;
2645 // downgrade TX quality if PER >= Rate-Down threshold
2646 if (TxErrorRatio >= TrainDown)
2648 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2651 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2653 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2655 // perform DRS - consider TxRate Down first, then rate up.
2656 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2658 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2660 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2661 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2666 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2668 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2672 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2674 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2677 }while (FALSE);
2679 // if rate-up happen, clear all bad history of all TX rates
2680 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2682 pAd->DrsCounters.TxRateUpPenalty = 0;
2683 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2684 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2685 bTxRateChanged = TRUE;
2687 // if rate-down happen, only clear DownRate's bad history
2688 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2690 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2692 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2693 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2694 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2695 bTxRateChanged = TRUE;
2697 else
2699 bTxRateChanged = FALSE;
2702 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2703 if (bTxRateChanged && pNextTxRate)
2705 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2711 ==========================================================================
2712 Description:
2713 This routine is executed periodically inside MlmePeriodicExec() after
2714 association with an AP.
2715 It checks if StaCfg.Psm is consistent with user policy (recorded in
2716 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2717 there're some conditions to consider:
2718 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2719 the time when Mibss==TRUE
2720 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2721 if outgoing traffic available in TxRing or MgmtRing.
2722 Output:
2723 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2725 IRQL = DISPATCH_LEVEL
2727 ==========================================================================
2729 VOID MlmeCheckPsmChange(
2730 IN PRTMP_ADAPTER pAd,
2731 IN ULONG Now32)
2733 ULONG PowerMode;
2735 // condition -
2736 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2737 // 2. user wants either MAX_PSP or FAST_PSP
2738 // 3. but current psm is not in PWR_SAVE
2739 // 4. CNTL state machine is not doing SCANning
2740 // 5. no TX SUCCESS event for the past 1-sec period
2741 #ifdef NDIS51_MINIPORT
2742 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2743 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2744 else
2745 #endif
2746 PowerMode = pAd->StaCfg.WindowsPowerMode;
2748 if (INFRA_ON(pAd) &&
2749 (PowerMode != Ndis802_11PowerModeCAM) &&
2750 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2751 // (! RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
2752 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) /*&&
2753 (pAd->RalinkCounters.OneSecTxNoRetryOkCount == 0) &&
2754 (pAd->RalinkCounters.OneSecTxRetryOkCount == 0)*/)
2756 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2757 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2758 MlmeSetPsmBit(pAd, PWR_SAVE);
2759 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2761 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2763 else
2765 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2770 // IRQL = PASSIVE_LEVEL
2771 // IRQL = DISPATCH_LEVEL
2772 VOID MlmeSetPsmBit(
2773 IN PRTMP_ADAPTER pAd,
2774 IN USHORT psm)
2776 AUTO_RSP_CFG_STRUC csr4;
2778 pAd->StaCfg.Psm = psm;
2779 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2780 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2781 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2782 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2784 #endif // CONFIG_STA_SUPPORT //
2787 // IRQL = DISPATCH_LEVEL
2788 VOID MlmeSetTxPreamble(
2789 IN PRTMP_ADAPTER pAd,
2790 IN USHORT TxPreamble)
2792 AUTO_RSP_CFG_STRUC csr4;
2795 // Always use Long preamble before verifiation short preamble functionality works well.
2796 // Todo: remove the following line if short preamble functionality works
2798 //TxPreamble = Rt802_11PreambleLong;
2800 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2801 if (TxPreamble == Rt802_11PreambleLong)
2803 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2804 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2805 csr4.field.AutoResponderPreamble = 0;
2807 else
2809 // NOTE: 1Mbps should always use long preamble
2810 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2811 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2812 csr4.field.AutoResponderPreamble = 1;
2815 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2819 ==========================================================================
2820 Description:
2821 Update basic rate bitmap
2822 ==========================================================================
2825 VOID UpdateBasicRateBitmap(
2826 IN PRTMP_ADAPTER pAdapter)
2828 INT i, j;
2829 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2830 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2831 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2832 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2833 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2836 /* if A mode, always use fix BasicRateBitMap */
2837 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2838 if (pAdapter->CommonCfg.Channel > 14)
2839 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2840 /* End of if */
2842 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2844 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2845 return;
2846 } /* End of if */
2848 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2850 sup_p[i] &= 0x7f;
2851 ext_p[i] &= 0x7f;
2852 } /* End of for */
2854 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2856 if (bitmap & (1 << i))
2858 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2860 if (sup_p[j] == rate[i])
2861 sup_p[j] |= 0x80;
2862 /* End of if */
2863 } /* End of for */
2865 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2867 if (ext_p[j] == rate[i])
2868 ext_p[j] |= 0x80;
2869 /* End of if */
2870 } /* End of for */
2871 } /* End of if */
2872 } /* End of for */
2873 } /* End of UpdateBasicRateBitmap */
2875 // IRQL = PASSIVE_LEVEL
2876 // IRQL = DISPATCH_LEVEL
2877 // bLinkUp is to identify the inital link speed.
2878 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2879 VOID MlmeUpdateTxRates(
2880 IN PRTMP_ADAPTER pAd,
2881 IN BOOLEAN bLinkUp,
2882 IN UCHAR apidx)
2884 int i, num;
2885 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2886 UCHAR MinSupport = RATE_54;
2887 ULONG BasicRateBitmap = 0;
2888 UCHAR CurrBasicRate = RATE_1;
2889 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2890 PHTTRANSMIT_SETTING pHtPhy = NULL;
2891 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2892 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2893 BOOLEAN *auto_rate_cur_p;
2894 UCHAR HtMcs = MCS_AUTO;
2896 // find max desired rate
2897 UpdateBasicRateBitmap(pAd);
2899 num = 0;
2900 auto_rate_cur_p = NULL;
2901 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2903 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2905 case 2: Rate = RATE_1; num++; break;
2906 case 4: Rate = RATE_2; num++; break;
2907 case 11: Rate = RATE_5_5; num++; break;
2908 case 22: Rate = RATE_11; num++; break;
2909 case 12: Rate = RATE_6; num++; break;
2910 case 18: Rate = RATE_9; num++; break;
2911 case 24: Rate = RATE_12; num++; break;
2912 case 36: Rate = RATE_18; num++; break;
2913 case 48: Rate = RATE_24; num++; break;
2914 case 72: Rate = RATE_36; num++; break;
2915 case 96: Rate = RATE_48; num++; break;
2916 case 108: Rate = RATE_54; num++; break;
2917 //default: Rate = RATE_1; break;
2919 if (MaxDesire < Rate) MaxDesire = Rate;
2922 //===========================================================================
2923 //===========================================================================
2925 #ifdef CONFIG_STA_SUPPORT
2926 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2928 pHtPhy = &pAd->StaCfg.HTPhyMode;
2929 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2930 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2932 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2933 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2935 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2936 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2937 (MaxDesire > RATE_11))
2939 MaxDesire = RATE_11;
2942 #endif // CONFIG_STA_SUPPORT //
2944 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2945 pMinHtPhy->word = 0;
2946 pMaxHtPhy->word = 0;
2947 pHtPhy->word = 0;
2949 // Auto rate switching is enabled only if more than one DESIRED RATES are
2950 // specified; otherwise disabled
2951 if (num <= 1)
2953 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2954 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2955 *auto_rate_cur_p = FALSE;
2957 else
2959 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2960 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2961 *auto_rate_cur_p = TRUE;
2964 #if 1
2965 if (HtMcs != MCS_AUTO)
2967 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2968 //pAd->CommonCfg.bAutoTxRateSwitch = FALSE;
2969 *auto_rate_cur_p = FALSE;
2971 else
2973 //OPSTATUS_SET_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED);
2974 //pAd->CommonCfg.bAutoTxRateSwitch = TRUE;
2975 *auto_rate_cur_p = TRUE;
2977 #endif
2979 #ifdef CONFIG_STA_SUPPORT
2980 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2982 pSupRate = &pAd->StaActive.SupRate[0];
2983 pExtRate = &pAd->StaActive.ExtRate[0];
2984 SupRateLen = pAd->StaActive.SupRateLen;
2985 ExtRateLen = pAd->StaActive.ExtRateLen;
2987 else
2988 #endif // CONFIG_STA_SUPPORT //
2990 pSupRate = &pAd->CommonCfg.SupRate[0];
2991 pExtRate = &pAd->CommonCfg.ExtRate[0];
2992 SupRateLen = pAd->CommonCfg.SupRateLen;
2993 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2996 // find max supported rate
2997 for (i=0; i<SupRateLen; i++)
2999 switch (pSupRate[i] & 0x7f)
3001 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3002 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3003 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3004 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3005 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3006 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3007 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3008 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3009 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3010 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3011 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3012 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3013 default: Rate = RATE_1; break;
3015 if (MaxSupport < Rate) MaxSupport = Rate;
3017 if (MinSupport > Rate) MinSupport = Rate;
3020 for (i=0; i<ExtRateLen; i++)
3022 switch (pExtRate[i] & 0x7f)
3024 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
3025 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
3026 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
3027 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
3028 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
3029 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
3030 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
3031 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
3032 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
3033 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
3034 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
3035 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
3036 default: Rate = RATE_1; break;
3038 if (MaxSupport < Rate) MaxSupport = Rate;
3040 if (MinSupport > Rate) MinSupport = Rate;
3043 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
3045 // bug fix
3046 // pAd->CommonCfg.BasicRateBitmap = BasicRateBitmap;
3048 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
3049 // the DURATION field of outgoing uniicast DATA/MGMT frame
3050 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
3052 if (BasicRateBitmap & (0x01 << i))
3053 CurrBasicRate = (UCHAR)i;
3054 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
3057 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
3058 // max tx rate = min {max desire rate, max supported rate}
3059 if (MaxSupport < MaxDesire)
3060 pAd->CommonCfg.MaxTxRate = MaxSupport;
3061 else
3062 pAd->CommonCfg.MaxTxRate = MaxDesire;
3064 pAd->CommonCfg.MinTxRate = MinSupport;
3065 // 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success
3066 // ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending
3067 // on average RSSI
3068 // 1. RSSI >= -70db, start at 54 Mbps (short distance)
3069 // 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance)
3070 // 3. -75 > RSSI, start at 11 Mbps (long distance)
3071 //if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)/* &&
3072 // OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)*/)
3073 if (*auto_rate_cur_p)
3075 short dbm = 0;
3076 #ifdef CONFIG_STA_SUPPORT
3077 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3078 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
3079 #endif // CONFIG_STA_SUPPORT //
3080 if (bLinkUp == TRUE)
3081 pAd->CommonCfg.TxRate = RATE_24;
3082 else
3083 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3085 if (dbm < -75)
3086 pAd->CommonCfg.TxRate = RATE_11;
3087 else if (dbm < -70)
3088 pAd->CommonCfg.TxRate = RATE_24;
3090 // should never exceed MaxTxRate (consider 11B-only mode)
3091 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
3092 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3094 pAd->CommonCfg.TxRateIndex = 0;
3096 else
3098 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3099 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3100 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3102 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3103 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3104 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3105 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3108 if (pAd->CommonCfg.TxRate <= RATE_11)
3110 pMaxHtPhy->field.MODE = MODE_CCK;
3111 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3112 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3114 else
3116 pMaxHtPhy->field.MODE = MODE_OFDM;
3117 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3118 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3119 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3120 else
3121 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3124 pHtPhy->word = (pMaxHtPhy->word);
3125 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3127 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3128 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3129 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3131 else
3133 switch (pAd->CommonCfg.PhyMode)
3135 case PHY_11BG_MIXED:
3136 case PHY_11B:
3137 #ifdef DOT11_N_SUPPORT
3138 case PHY_11BGN_MIXED:
3139 #endif // DOT11_N_SUPPORT //
3140 pAd->CommonCfg.MlmeRate = RATE_1;
3141 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3142 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3144 //#ifdef WIFI_TEST
3145 pAd->CommonCfg.RtsRate = RATE_11;
3146 //#else
3147 // pAd->CommonCfg.RtsRate = RATE_1;
3148 //#endif
3149 break;
3150 case PHY_11G:
3151 case PHY_11A:
3152 #ifdef DOT11_N_SUPPORT
3153 case PHY_11AGN_MIXED:
3154 case PHY_11GN_MIXED:
3155 case PHY_11N_2_4G:
3156 case PHY_11AN_MIXED:
3157 case PHY_11N_5G:
3158 #endif // DOT11_N_SUPPORT //
3159 pAd->CommonCfg.MlmeRate = RATE_6;
3160 pAd->CommonCfg.RtsRate = RATE_6;
3161 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3162 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3163 break;
3164 case PHY_11ABG_MIXED:
3165 #ifdef DOT11_N_SUPPORT
3166 case PHY_11ABGN_MIXED:
3167 #endif // DOT11_N_SUPPORT //
3168 if (pAd->CommonCfg.Channel <= 14)
3170 pAd->CommonCfg.MlmeRate = RATE_1;
3171 pAd->CommonCfg.RtsRate = RATE_1;
3172 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3173 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3175 else
3177 pAd->CommonCfg.MlmeRate = RATE_6;
3178 pAd->CommonCfg.RtsRate = RATE_6;
3179 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3180 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3182 break;
3183 default: // error
3184 pAd->CommonCfg.MlmeRate = RATE_6;
3185 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3186 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3187 pAd->CommonCfg.RtsRate = RATE_1;
3188 break;
3191 // Keep Basic Mlme Rate.
3193 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3194 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3195 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3196 else
3197 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3198 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3201 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3202 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3203 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3204 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3205 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3206 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3207 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 ));
3210 #ifdef DOT11_N_SUPPORT
3212 ==========================================================================
3213 Description:
3214 This function update HT Rate setting.
3215 Input Wcid value is valid for 2 case :
3216 1. it's used for Station in infra mode that copy AP rate to Mactable.
3217 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3219 IRQL = DISPATCH_LEVEL
3221 ==========================================================================
3223 VOID MlmeUpdateHtTxRates(
3224 IN PRTMP_ADAPTER pAd,
3225 IN UCHAR apidx)
3227 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3228 CHAR i; // 3*3
3229 RT_HT_CAPABILITY *pRtHtCap = NULL;
3230 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3231 ULONG BasicMCS;
3232 UCHAR j, bitmask;
3233 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3234 PHTTRANSMIT_SETTING pHtPhy = NULL;
3235 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3236 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3237 BOOLEAN *auto_rate_cur_p;
3239 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3241 auto_rate_cur_p = NULL;
3243 #ifdef CONFIG_STA_SUPPORT
3244 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3246 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3247 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3248 pHtPhy = &pAd->StaCfg.HTPhyMode;
3249 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3250 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3252 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3254 #endif // CONFIG_STA_SUPPORT //
3256 #ifdef CONFIG_STA_SUPPORT
3257 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3259 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3260 return;
3262 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3263 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3264 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3265 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3266 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3267 pMaxHtPhy->field.STBC = STBC_USE;
3268 else
3269 pMaxHtPhy->field.STBC = STBC_NONE;
3271 else
3272 #endif // CONFIG_STA_SUPPORT //
3274 if (pDesireHtPhy->bHtEnable == FALSE)
3275 return;
3277 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3278 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3279 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3280 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3281 pMaxHtPhy->field.STBC = STBC_USE;
3282 else
3283 pMaxHtPhy->field.STBC = STBC_NONE;
3286 // Decide MAX ht rate.
3287 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3288 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3289 else
3290 pMaxHtPhy->field.MODE = MODE_HTMIX;
3292 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3293 pMaxHtPhy->field.BW = BW_40;
3294 else
3295 pMaxHtPhy->field.BW = BW_20;
3297 if (pMaxHtPhy->field.BW == BW_20)
3298 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3299 else
3300 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3302 for (i=23; i>=0; i--) // 3*3
3304 j = i/8;
3305 bitmask = (1<<(i-(j*8)));
3307 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3309 pMaxHtPhy->field.MCS = i;
3310 break;
3313 if (i==0)
3314 break;
3317 // Copy MIN ht rate. rt2860???
3318 pMinHtPhy->field.BW = BW_20;
3319 pMinHtPhy->field.MCS = 0;
3320 pMinHtPhy->field.STBC = 0;
3321 pMinHtPhy->field.ShortGI = 0;
3322 //If STA assigns fixed rate. update to fixed here.
3323 #ifdef CONFIG_STA_SUPPORT
3324 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3326 if (pDesireHtPhy->MCSSet[4] != 0)
3328 pMaxHtPhy->field.MCS = 32;
3329 pMinHtPhy->field.MCS = 32;
3330 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3333 for (i=23; (CHAR)i >= 0; i--) // 3*3
3335 j = i/8;
3336 bitmask = (1<<(i-(j*8)));
3337 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3339 pMaxHtPhy->field.MCS = i;
3340 pMinHtPhy->field.MCS = i;
3341 break;
3343 if (i==0)
3344 break;
3347 #endif // CONFIG_STA_SUPPORT //
3350 // Decide ht rate
3351 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3352 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3353 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3354 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3355 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3357 // use default now. rt2860
3358 if (pDesireHtPhy->MCSSet[0] != 0xff)
3359 *auto_rate_cur_p = FALSE;
3360 else
3361 *auto_rate_cur_p = TRUE;
3363 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3364 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3365 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3366 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3368 #endif // DOT11_N_SUPPORT //
3370 // IRQL = DISPATCH_LEVEL
3371 VOID MlmeRadioOff(
3372 IN PRTMP_ADAPTER pAd)
3374 RT28XX_MLME_RADIO_OFF(pAd);
3377 // IRQL = DISPATCH_LEVEL
3378 VOID MlmeRadioOn(
3379 IN PRTMP_ADAPTER pAd)
3381 RT28XX_MLME_RADIO_ON(pAd);
3384 // ===========================================================================================
3385 // bss_table.c
3386 // ===========================================================================================
3389 /*! \brief initialize BSS table
3390 * \param p_tab pointer to the table
3391 * \return none
3392 * \pre
3393 * \post
3395 IRQL = PASSIVE_LEVEL
3396 IRQL = DISPATCH_LEVEL
3399 VOID BssTableInit(
3400 IN BSS_TABLE *Tab)
3402 int i;
3404 Tab->BssNr = 0;
3405 Tab->BssOverlapNr = 0;
3406 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3408 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3409 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3413 #ifdef DOT11_N_SUPPORT
3414 VOID BATableInit(
3415 IN PRTMP_ADAPTER pAd,
3416 IN BA_TABLE *Tab)
3418 int i;
3420 Tab->numAsOriginator = 0;
3421 Tab->numAsRecipient = 0;
3422 NdisAllocateSpinLock(&pAd->BATabLock);
3423 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3425 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3426 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3428 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3430 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3433 #endif // DOT11_N_SUPPORT //
3435 /*! \brief search the BSS table by SSID
3436 * \param p_tab pointer to the bss table
3437 * \param ssid SSID string
3438 * \return index of the table, BSS_NOT_FOUND if not in the table
3439 * \pre
3440 * \post
3441 * \note search by sequential search
3443 IRQL = DISPATCH_LEVEL
3446 ULONG BssTableSearch(
3447 IN BSS_TABLE *Tab,
3448 IN PUCHAR pBssid,
3449 IN UCHAR Channel)
3451 UCHAR i;
3453 for (i = 0; i < Tab->BssNr; i++)
3456 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3457 // We should distinguish this case.
3459 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3460 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3461 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3463 return i;
3466 return (ULONG)BSS_NOT_FOUND;
3469 ULONG BssSsidTableSearch(
3470 IN BSS_TABLE *Tab,
3471 IN PUCHAR pBssid,
3472 IN PUCHAR pSsid,
3473 IN UCHAR SsidLen,
3474 IN UCHAR Channel)
3476 UCHAR i;
3478 for (i = 0; i < Tab->BssNr; i++)
3481 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3482 // We should distinguish this case.
3484 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3485 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3486 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3487 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3489 return i;
3492 return (ULONG)BSS_NOT_FOUND;
3495 ULONG BssTableSearchWithSSID(
3496 IN BSS_TABLE *Tab,
3497 IN PUCHAR Bssid,
3498 IN PUCHAR pSsid,
3499 IN UCHAR SsidLen,
3500 IN UCHAR Channel)
3502 UCHAR i;
3504 for (i = 0; i < Tab->BssNr; i++)
3506 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3507 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3508 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3509 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3510 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3511 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3513 return i;
3516 return (ULONG)BSS_NOT_FOUND;
3519 // IRQL = DISPATCH_LEVEL
3520 VOID BssTableDeleteEntry(
3521 IN OUT BSS_TABLE *Tab,
3522 IN PUCHAR pBssid,
3523 IN UCHAR Channel)
3525 UCHAR i, j;
3527 for (i = 0; i < Tab->BssNr; i++)
3529 if ((Tab->BssEntry[i].Channel == Channel) &&
3530 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3532 for (j = i; j < Tab->BssNr - 1; j++)
3534 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3536 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3537 Tab->BssNr -= 1;
3538 return;
3543 #ifdef DOT11_N_SUPPORT
3545 ========================================================================
3546 Routine Description:
3547 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3549 Arguments:
3550 // IRQL = DISPATCH_LEVEL
3551 ========================================================================
3553 VOID BATableDeleteORIEntry(
3554 IN OUT PRTMP_ADAPTER pAd,
3555 IN BA_ORI_ENTRY *pBAORIEntry)
3558 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3560 NdisAcquireSpinLock(&pAd->BATabLock);
3561 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3563 pAd->BATable.numAsOriginator -= 1;
3564 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3565 // Erase Bitmap flag.
3567 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3568 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3569 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3570 pBAORIEntry->Token = 1;
3571 // Not clear Sequence here.
3572 NdisReleaseSpinLock(&pAd->BATabLock);
3575 #endif // DOT11_N_SUPPORT //
3577 /*! \brief
3578 * \param
3579 * \return
3580 * \pre
3581 * \post
3583 IRQL = DISPATCH_LEVEL
3586 VOID BssEntrySet(
3587 IN PRTMP_ADAPTER pAd,
3588 OUT BSS_ENTRY *pBss,
3589 IN PUCHAR pBssid,
3590 IN CHAR Ssid[],
3591 IN UCHAR SsidLen,
3592 IN UCHAR BssType,
3593 IN USHORT BeaconPeriod,
3594 IN PCF_PARM pCfParm,
3595 IN USHORT AtimWin,
3596 IN USHORT CapabilityInfo,
3597 IN UCHAR SupRate[],
3598 IN UCHAR SupRateLen,
3599 IN UCHAR ExtRate[],
3600 IN UCHAR ExtRateLen,
3601 IN HT_CAPABILITY_IE *pHtCapability,
3602 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3603 IN UCHAR HtCapabilityLen,
3604 IN UCHAR AddHtInfoLen,
3605 IN UCHAR NewExtChanOffset,
3606 IN UCHAR Channel,
3607 IN CHAR Rssi,
3608 IN LARGE_INTEGER TimeStamp,
3609 IN UCHAR CkipFlag,
3610 IN PEDCA_PARM pEdcaParm,
3611 IN PQOS_CAPABILITY_PARM pQosCapability,
3612 IN PQBSS_LOAD_PARM pQbssLoad,
3613 IN USHORT LengthVIE,
3614 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3616 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3617 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3618 pBss->Hidden = 1;
3619 if (SsidLen > 0)
3621 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3622 // Or send beacon /probe response with SSID len matching real SSID length,
3623 // but SSID is all zero. such as "00-00-00-00" with length 4.
3624 // We have to prevent this case overwrite correct table
3625 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3627 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3628 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3629 pBss->SsidLen = SsidLen;
3630 pBss->Hidden = 0;
3633 else
3634 pBss->SsidLen = 0;
3635 pBss->BssType = BssType;
3636 pBss->BeaconPeriod = BeaconPeriod;
3637 if (BssType == BSS_INFRA)
3639 if (pCfParm->bValid)
3641 pBss->CfpCount = pCfParm->CfpCount;
3642 pBss->CfpPeriod = pCfParm->CfpPeriod;
3643 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3644 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3647 else
3649 pBss->AtimWin = AtimWin;
3652 pBss->CapabilityInfo = CapabilityInfo;
3653 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3654 // Combine with AuthMode, they will decide the connection methods.
3655 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3656 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3657 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3658 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3659 else
3660 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3661 pBss->SupRateLen = SupRateLen;
3662 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3663 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3664 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3665 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3666 pBss->NewExtChanOffset = NewExtChanOffset;
3667 pBss->ExtRateLen = ExtRateLen;
3668 pBss->Channel = Channel;
3669 pBss->CentralChannel = Channel;
3670 pBss->Rssi = Rssi;
3671 // Update CkipFlag. if not exists, the value is 0x0
3672 pBss->CkipFlag = CkipFlag;
3674 // New for microsoft Fixed IEs
3675 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3676 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3677 pBss->FixIEs.Capabilities = CapabilityInfo;
3679 // New for microsoft Variable IEs
3680 if (LengthVIE != 0)
3682 pBss->VarIELen = LengthVIE;
3683 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3685 else
3687 pBss->VarIELen = 0;
3690 pBss->AddHtInfoLen = 0;
3691 pBss->HtCapabilityLen = 0;
3692 #ifdef DOT11_N_SUPPORT
3693 if (HtCapabilityLen> 0)
3695 pBss->HtCapabilityLen = HtCapabilityLen;
3696 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3697 if (AddHtInfoLen > 0)
3699 pBss->AddHtInfoLen = AddHtInfoLen;
3700 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3702 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3704 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3706 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3708 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3712 #endif // DOT11_N_SUPPORT //
3714 BssCipherParse(pBss);
3716 // new for QOS
3717 if (pEdcaParm)
3718 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3719 else
3720 pBss->EdcaParm.bValid = FALSE;
3721 if (pQosCapability)
3722 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3723 else
3724 pBss->QosCapability.bValid = FALSE;
3725 if (pQbssLoad)
3726 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3727 else
3728 pBss->QbssLoad.bValid = FALSE;
3730 #ifdef CONFIG_STA_SUPPORT
3731 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3733 PEID_STRUCT pEid;
3734 USHORT Length = 0;
3737 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3738 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3739 #ifdef EXT_BUILD_CHANNEL_LIST
3740 NdisZeroMemory(&pBss->CountryString[0], 3);
3741 pBss->bHasCountryIE = FALSE;
3742 #endif // EXT_BUILD_CHANNEL_LIST //
3743 pEid = (PEID_STRUCT) pVIE;
3744 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3746 switch(pEid->Eid)
3748 case IE_WPA:
3749 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3751 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3753 pBss->WpaIE.IELen = 0;
3754 break;
3756 pBss->WpaIE.IELen = pEid->Len + 2;
3757 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3759 break;
3760 case IE_RSN:
3761 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3763 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3765 pBss->RsnIE.IELen = 0;
3766 break;
3768 pBss->RsnIE.IELen = pEid->Len + 2;
3769 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3771 break;
3772 #ifdef EXT_BUILD_CHANNEL_LIST
3773 case IE_COUNTRY:
3774 NdisMoveMemory(&pBss->CountryString[0], pEid->Octet, 3);
3775 pBss->bHasCountryIE = TRUE;
3776 break;
3777 #endif // EXT_BUILD_CHANNEL_LIST //
3779 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3780 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3783 #endif // CONFIG_STA_SUPPORT //
3787 * \brief insert an entry into the bss table
3788 * \param p_tab The BSS table
3789 * \param Bssid BSSID
3790 * \param ssid SSID
3791 * \param ssid_len Length of SSID
3792 * \param bss_type
3793 * \param beacon_period
3794 * \param timestamp
3795 * \param p_cf
3796 * \param atim_win
3797 * \param cap
3798 * \param rates
3799 * \param rates_len
3800 * \param channel_idx
3801 * \return none
3802 * \pre
3803 * \post
3804 * \note If SSID is identical, the old entry will be replaced by the new one
3806 IRQL = DISPATCH_LEVEL
3809 ULONG BssTableSetEntry(
3810 IN PRTMP_ADAPTER pAd,
3811 OUT BSS_TABLE *Tab,
3812 IN PUCHAR pBssid,
3813 IN CHAR Ssid[],
3814 IN UCHAR SsidLen,
3815 IN UCHAR BssType,
3816 IN USHORT BeaconPeriod,
3817 IN CF_PARM *CfParm,
3818 IN USHORT AtimWin,
3819 IN USHORT CapabilityInfo,
3820 IN UCHAR SupRate[],
3821 IN UCHAR SupRateLen,
3822 IN UCHAR ExtRate[],
3823 IN UCHAR ExtRateLen,
3824 IN HT_CAPABILITY_IE *pHtCapability,
3825 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3826 IN UCHAR HtCapabilityLen,
3827 IN UCHAR AddHtInfoLen,
3828 IN UCHAR NewExtChanOffset,
3829 IN UCHAR ChannelNo,
3830 IN CHAR Rssi,
3831 IN LARGE_INTEGER TimeStamp,
3832 IN UCHAR CkipFlag,
3833 IN PEDCA_PARM pEdcaParm,
3834 IN PQOS_CAPABILITY_PARM pQosCapability,
3835 IN PQBSS_LOAD_PARM pQbssLoad,
3836 IN USHORT LengthVIE,
3837 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3839 ULONG Idx;
3841 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3842 if (Idx == BSS_NOT_FOUND)
3844 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3847 // It may happen when BSS Table was full.
3848 // The desired AP will not be added into BSS Table
3849 // In this case, if we found the desired AP then overwrite BSS Table.
3851 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3853 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3854 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3856 Idx = Tab->BssOverlapNr;
3857 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3858 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3859 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3860 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3862 return Idx;
3864 else
3866 return BSS_NOT_FOUND;
3869 Idx = Tab->BssNr;
3870 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3871 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3872 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3873 Tab->BssNr++;
3875 else
3877 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3878 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3879 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3882 return Idx;
3885 #ifdef CONFIG_STA_SUPPORT
3886 #ifdef DOT11_N_SUPPORT
3887 #ifdef DOT11N_DRAFT3
3888 VOID TriEventInit(
3889 IN PRTMP_ADAPTER pAd)
3891 UCHAR i;
3893 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3894 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3896 pAd->CommonCfg.TriggerEventTab.EventANo = 0;
3897 pAd->CommonCfg.TriggerEventTab.EventBCountDown = 0;
3900 ULONG TriEventTableSetEntry(
3901 IN PRTMP_ADAPTER pAd,
3902 OUT TRIGGER_EVENT_TAB *Tab,
3903 IN PUCHAR pBssid,
3904 IN HT_CAPABILITY_IE *pHtCapability,
3905 IN UCHAR HtCapabilityLen,
3906 IN UCHAR RegClass,
3907 IN UCHAR ChannelNo)
3909 // Event A
3910 if (HtCapabilityLen == 0)
3912 if (Tab->EventANo < MAX_TRIGGER_EVENT)
3914 RTMPMoveMemory(Tab->EventA[Tab->EventANo].BSSID, pBssid, 6);
3915 Tab->EventA[Tab->EventANo].bValid = TRUE;
3916 Tab->EventA[Tab->EventANo].Channel = ChannelNo;
3917 Tab->EventA[Tab->EventANo].CDCounter = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3918 if (RegClass != 0)
3920 // Beacon has Regulatory class IE. So use beacon's
3921 Tab->EventA[Tab->EventANo].RegClass = RegClass;
3923 else
3925 // Use Station's Regulatory class instead.
3926 if (pAd->StaActive.SupportedHtPhy.bHtEnable == TRUE)
3928 if (pAd->CommonCfg.CentralChannel > pAd->CommonCfg.Channel)
3930 Tab->EventA[Tab->EventANo].RegClass = 32;
3932 else if (pAd->CommonCfg.CentralChannel < pAd->CommonCfg.Channel)
3933 Tab->EventA[Tab->EventANo].RegClass = 33;
3935 else
3936 Tab->EventA[Tab->EventANo].RegClass = ??;
3940 Tab->EventANo ++;
3943 else if (pHtCapability->HtCapInfo.Intolerant40)
3945 Tab->EventBCountDown = pAd->CommonCfg.Dot11BssWidthChanTranDelay;
3951 ========================================================================
3952 Routine Description:
3953 Trigger Event table Maintainence called once every second.
3955 Arguments:
3956 // IRQL = DISPATCH_LEVEL
3957 ========================================================================
3959 VOID TriEventCounterMaintenance(
3960 IN PRTMP_ADAPTER pAd)
3962 UCHAR i;
3963 BOOLEAN bNotify = FALSE;
3964 for (i = 0;i < MAX_TRIGGER_EVENT;i++)
3966 if (pAd->CommonCfg.TriggerEventTab.EventA[i].bValid && (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter > 0))
3968 pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter--;
3969 if (pAd->CommonCfg.TriggerEventTab.EventA[i].CDCounter == 0)
3971 pAd->CommonCfg.TriggerEventTab.EventA[i].bValid = FALSE;
3972 pAd->CommonCfg.TriggerEventTab.EventANo --;
3973 // Need to send 20/40 Coexistence Notify frame if has status change.
3974 bNotify = TRUE;
3978 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown > 0)
3980 pAd->CommonCfg.TriggerEventTab.EventBCountDown--;
3981 if (pAd->CommonCfg.TriggerEventTab.EventBCountDown == 0)
3982 bNotify = TRUE;
3985 if (bNotify == TRUE)
3986 Update2040CoexistFrameAndNotify(pAd, BSSID_WCID, TRUE);
3988 #endif // DOT11N_DRAFT3 //
3989 #endif // DOT11_N_SUPPORT //
3991 // IRQL = DISPATCH_LEVEL
3992 VOID BssTableSsidSort(
3993 IN PRTMP_ADAPTER pAd,
3994 OUT BSS_TABLE *OutTab,
3995 IN CHAR Ssid[],
3996 IN UCHAR SsidLen)
3998 INT i;
3999 BssTableInit(OutTab);
4001 for (i = 0; i < pAd->ScanTab.BssNr; i++)
4003 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
4004 BOOLEAN bIsHiddenApIncluded = FALSE;
4006 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
4007 (pAd->MlmeAux.Channel > 14) &&
4008 RadarChannelCheck(pAd, pInBss->Channel))
4009 #ifdef CARRIER_DETECTION_SUPPORT // Roger sync Carrier
4010 || (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
4011 #endif // CARRIER_DETECTION_SUPPORT //
4014 if (pInBss->Hidden)
4015 bIsHiddenApIncluded = TRUE;
4018 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
4019 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
4021 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4024 #ifdef EXT_BUILD_CHANNEL_LIST
4025 // If no Country IE exists no Connection will be established when IEEE80211dClientMode is strict.
4026 if ((pAd->StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict) &&
4027 (pInBss->bHasCountryIE == FALSE))
4029 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.IEEE80211dClientMode == Rt802_11_D_Strict, but this AP doesn't have country IE.\n"));
4030 continue;
4032 #endif // EXT_BUILD_CHANNEL_LIST //
4034 #ifdef DOT11_N_SUPPORT
4035 // 2.4G/5G N only mode
4036 if ((pInBss->HtCapabilityLen == 0) &&
4037 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4039 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4040 continue;
4042 #endif // DOT11_N_SUPPORT //
4044 // New for WPA2
4045 // Check the Authmode first
4046 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4048 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4049 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4050 // None matched
4051 continue;
4053 // Check cipher suite, AP must have more secured cipher than station setting
4054 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4056 // If it's not mixed mode, we should only let BSS pass with the same encryption
4057 if (pInBss->WPA.bMixMode == FALSE)
4058 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4059 continue;
4061 // check group cipher
4062 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4063 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4064 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
4065 continue;
4067 // check pairwise cipher, skip if none matched
4068 // If profile set to AES, let it pass without question.
4069 // If profile set to TKIP, we must find one mateched
4070 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4071 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4072 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4073 continue;
4075 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4077 // If it's not mixed mode, we should only let BSS pass with the same encryption
4078 if (pInBss->WPA2.bMixMode == FALSE)
4079 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4080 continue;
4082 // check group cipher
4083 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
4084 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
4085 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
4086 continue;
4088 // check pairwise cipher, skip if none matched
4089 // If profile set to AES, let it pass without question.
4090 // If profile set to TKIP, we must find one mateched
4091 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4092 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4093 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4094 continue;
4097 // Bss Type matched, SSID matched.
4098 // We will check wepstatus for qualification Bss
4099 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4101 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
4103 // For the SESv2 case, we will not qualify WepStatus.
4105 if (!pInBss->bSES)
4106 continue;
4109 // Since the AP is using hidden SSID, and we are trying to connect to ANY
4110 // It definitely will fail. So, skip it.
4111 // CCX also require not even try to connect it!!
4112 if (SsidLen == 0)
4113 continue;
4115 #ifdef DOT11_N_SUPPORT
4116 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4117 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4118 if ((pInBss->CentralChannel != pInBss->Channel) &&
4119 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4121 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4123 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4124 SetCommonHT(pAd);
4125 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4127 else
4129 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
4131 SetCommonHT(pAd);
4135 #endif // DOT11_N_SUPPORT //
4137 // copy matching BSS from InTab to OutTab
4138 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4140 OutTab->BssNr++;
4142 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
4144 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
4147 #ifdef DOT11_N_SUPPORT
4148 // 2.4G/5G N only mode
4149 if ((pInBss->HtCapabilityLen == 0) &&
4150 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
4152 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
4153 continue;
4155 #endif // DOT11_N_SUPPORT //
4157 // New for WPA2
4158 // Check the Authmode first
4159 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
4161 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
4162 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
4163 // None matched
4164 continue;
4166 // Check cipher suite, AP must have more secured cipher than station setting
4167 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
4169 // If it's not mixed mode, we should only let BSS pass with the same encryption
4170 if (pInBss->WPA.bMixMode == FALSE)
4171 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
4172 continue;
4174 // check group cipher
4175 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
4176 continue;
4178 // check pairwise cipher, skip if none matched
4179 // If profile set to AES, let it pass without question.
4180 // If profile set to TKIP, we must find one mateched
4181 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4182 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
4183 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
4184 continue;
4186 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
4188 // If it's not mixed mode, we should only let BSS pass with the same encryption
4189 if (pInBss->WPA2.bMixMode == FALSE)
4190 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
4191 continue;
4193 // check group cipher
4194 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
4195 continue;
4197 // check pairwise cipher, skip if none matched
4198 // If profile set to AES, let it pass without question.
4199 // If profile set to TKIP, we must find one mateched
4200 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
4201 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
4202 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
4203 continue;
4206 // Bss Type matched, SSID matched.
4207 // We will check wepstatus for qualification Bss
4208 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
4209 continue;
4211 #ifdef DOT11_N_SUPPORT
4212 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
4213 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
4214 if ((pInBss->CentralChannel != pInBss->Channel) &&
4215 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
4217 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
4219 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
4220 SetCommonHT(pAd);
4221 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
4224 #endif // DOT11_N_SUPPORT //
4226 // copy matching BSS from InTab to OutTab
4227 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
4229 OutTab->BssNr++;
4232 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
4233 break;
4236 BssTableSortByRssi(OutTab);
4240 // IRQL = DISPATCH_LEVEL
4241 VOID BssTableSortByRssi(
4242 IN OUT BSS_TABLE *OutTab)
4244 INT i, j;
4245 BSS_ENTRY TmpBss;
4247 for (i = 0; i < OutTab->BssNr - 1; i++)
4249 for (j = i+1; j < OutTab->BssNr; j++)
4251 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4253 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4254 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4255 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4260 #endif // CONFIG_STA_SUPPORT //
4263 VOID BssCipherParse(
4264 IN OUT PBSS_ENTRY pBss)
4266 PEID_STRUCT pEid;
4267 PUCHAR pTmp;
4268 PRSN_IE_HEADER_STRUCT pRsnHeader;
4269 PCIPHER_SUITE_STRUCT pCipher;
4270 PAKM_SUITE_STRUCT pAKM;
4271 USHORT Count;
4272 INT Length;
4273 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4276 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4278 if (pBss->Privacy)
4280 pBss->WepStatus = Ndis802_11WEPEnabled;
4282 else
4284 pBss->WepStatus = Ndis802_11WEPDisabled;
4286 // Set default to disable & open authentication before parsing variable IE
4287 pBss->AuthMode = Ndis802_11AuthModeOpen;
4288 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4290 // Init WPA setting
4291 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4292 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4293 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4294 pBss->WPA.RsnCapability = 0;
4295 pBss->WPA.bMixMode = FALSE;
4297 // Init WPA2 setting
4298 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4299 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4300 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4301 pBss->WPA2.RsnCapability = 0;
4302 pBss->WPA2.bMixMode = FALSE;
4305 Length = (INT) pBss->VarIELen;
4307 while (Length > 0)
4309 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4310 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4311 pEid = (PEID_STRUCT) pTmp;
4312 switch (pEid->Eid)
4314 case IE_WPA:
4315 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4316 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4318 pTmp += 11;
4319 switch (*pTmp)
4321 case 1:
4322 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4323 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4324 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4325 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4326 break;
4327 case 2:
4328 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4329 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4330 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4331 break;
4332 case 4:
4333 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4334 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4335 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4336 break;
4337 default:
4338 break;
4341 // if Cisco IE_WPA, break
4342 break;
4344 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4346 pBss->bSES = TRUE;
4347 break;
4349 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4351 // if unsupported vendor specific IE
4352 break;
4354 // Skip OUI, version, and multicast suite
4355 // This part should be improved in the future when AP supported multiple cipher suite.
4356 // For now, it's OK since almost all APs have fixed cipher suite supported.
4357 // pTmp = (PUCHAR) pEid->Octet;
4358 pTmp += 11;
4360 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4361 // Value Meaning
4362 // 0 None
4363 // 1 WEP-40
4364 // 2 Tkip
4365 // 3 WRAP
4366 // 4 AES
4367 // 5 WEP-104
4368 // Parse group cipher
4369 switch (*pTmp)
4371 case 1:
4372 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4373 break;
4374 case 5:
4375 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4376 break;
4377 case 2:
4378 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4379 break;
4380 case 4:
4381 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4382 break;
4383 default:
4384 break;
4386 // number of unicast suite
4387 pTmp += 1;
4389 // skip all unicast cipher suites
4390 //Count = *(PUSHORT) pTmp;
4391 Count = (pTmp[1]<<8) + pTmp[0];
4392 pTmp += sizeof(USHORT);
4394 // Parsing all unicast cipher suite
4395 while (Count > 0)
4397 // Skip OUI
4398 pTmp += 3;
4399 TmpCipher = Ndis802_11WEPDisabled;
4400 switch (*pTmp)
4402 case 1:
4403 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4404 TmpCipher = Ndis802_11Encryption1Enabled;
4405 break;
4406 case 2:
4407 TmpCipher = Ndis802_11Encryption2Enabled;
4408 break;
4409 case 4:
4410 TmpCipher = Ndis802_11Encryption3Enabled;
4411 break;
4412 default:
4413 break;
4415 if (TmpCipher > pBss->WPA.PairCipher)
4417 // Move the lower cipher suite to PairCipherAux
4418 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4419 pBss->WPA.PairCipher = TmpCipher;
4421 else
4423 pBss->WPA.PairCipherAux = TmpCipher;
4425 pTmp++;
4426 Count--;
4429 // 4. get AKM suite counts
4430 //Count = *(PUSHORT) pTmp;
4431 Count = (pTmp[1]<<8) + pTmp[0];
4432 pTmp += sizeof(USHORT);
4433 pTmp += 3;
4435 switch (*pTmp)
4437 case 1:
4438 // Set AP support WPA mode
4439 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4440 pBss->AuthMode = Ndis802_11AuthModeWPA;
4441 else
4442 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4443 break;
4444 case 2:
4445 // Set AP support WPA mode
4446 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4447 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4448 else
4449 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4450 break;
4451 default:
4452 break;
4454 pTmp += 1;
4456 // Fixed for WPA-None
4457 if (pBss->BssType == BSS_ADHOC)
4459 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4460 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4461 pBss->WepStatus = pBss->WPA.GroupCipher;
4462 // Patched bugs for old driver
4463 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4464 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4466 else
4467 pBss->WepStatus = pBss->WPA.PairCipher;
4469 // Check the Pair & Group, if different, turn on mixed mode flag
4470 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4471 pBss->WPA.bMixMode = TRUE;
4473 break;
4475 case IE_RSN:
4476 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4478 // 0. Version must be 1
4479 if (le2cpu16(pRsnHeader->Version) != 1)
4480 break;
4481 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4483 // 1. Check group cipher
4484 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4485 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4486 break;
4488 // Parse group cipher
4489 switch (pCipher->Type)
4491 case 1:
4492 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4493 break;
4494 case 5:
4495 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4496 break;
4497 case 2:
4498 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4499 break;
4500 case 4:
4501 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4502 break;
4503 default:
4504 break;
4506 // set to correct offset for next parsing
4507 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4509 // 2. Get pairwise cipher counts
4510 //Count = *(PUSHORT) pTmp;
4511 Count = (pTmp[1]<<8) + pTmp[0];
4512 pTmp += sizeof(USHORT);
4514 // 3. Get pairwise cipher
4515 // Parsing all unicast cipher suite
4516 while (Count > 0)
4518 // Skip OUI
4519 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4520 TmpCipher = Ndis802_11WEPDisabled;
4521 switch (pCipher->Type)
4523 case 1:
4524 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4525 TmpCipher = Ndis802_11Encryption1Enabled;
4526 break;
4527 case 2:
4528 TmpCipher = Ndis802_11Encryption2Enabled;
4529 break;
4530 case 4:
4531 TmpCipher = Ndis802_11Encryption3Enabled;
4532 break;
4533 default:
4534 break;
4536 if (TmpCipher > pBss->WPA2.PairCipher)
4538 // Move the lower cipher suite to PairCipherAux
4539 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4540 pBss->WPA2.PairCipher = TmpCipher;
4542 else
4544 pBss->WPA2.PairCipherAux = TmpCipher;
4546 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4547 Count--;
4550 // 4. get AKM suite counts
4551 //Count = *(PUSHORT) pTmp;
4552 Count = (pTmp[1]<<8) + pTmp[0];
4553 pTmp += sizeof(USHORT);
4555 // 5. Get AKM ciphers
4556 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4557 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4558 break;
4560 switch (pAKM->Type)
4562 case 1:
4563 // Set AP support WPA mode
4564 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4565 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4566 else
4567 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4568 break;
4569 case 2:
4570 // Set AP support WPA mode
4571 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4572 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4573 else
4574 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4575 break;
4576 default:
4577 break;
4579 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4581 // Fixed for WPA-None
4582 if (pBss->BssType == BSS_ADHOC)
4584 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4585 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4586 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4587 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4588 pBss->WepStatus = pBss->WPA.GroupCipher;
4589 // Patched bugs for old driver
4590 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4591 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4593 pBss->WepStatus = pBss->WPA2.PairCipher;
4595 // 6. Get RSN capability
4596 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4597 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4598 pTmp += sizeof(USHORT);
4600 // Check the Pair & Group, if different, turn on mixed mode flag
4601 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4602 pBss->WPA2.bMixMode = TRUE;
4604 break;
4605 default:
4606 break;
4608 Length -= (pEid->Len + 2);
4612 // ===========================================================================================
4613 // mac_table.c
4614 // ===========================================================================================
4616 /*! \brief generates a random mac address value for IBSS BSSID
4617 * \param Addr the bssid location
4618 * \return none
4619 * \pre
4620 * \post
4622 VOID MacAddrRandomBssid(
4623 IN PRTMP_ADAPTER pAd,
4624 OUT PUCHAR pAddr)
4626 INT i;
4628 for (i = 0; i < MAC_ADDR_LEN; i++)
4630 pAddr[i] = RandomByte(pAd);
4633 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4636 /*! \brief init the management mac frame header
4637 * \param p_hdr mac header
4638 * \param subtype subtype of the frame
4639 * \param p_ds destination address, don't care if it is a broadcast address
4640 * \return none
4641 * \pre the station has the following information in the pAd->StaCfg
4642 * - bssid
4643 * - station address
4644 * \post
4645 * \note this function initializes the following field
4647 IRQL = PASSIVE_LEVEL
4648 IRQL = DISPATCH_LEVEL
4651 VOID MgtMacHeaderInit(
4652 IN PRTMP_ADAPTER pAd,
4653 IN OUT PHEADER_802_11 pHdr80211,
4654 IN UCHAR SubType,
4655 IN UCHAR ToDs,
4656 IN PUCHAR pDA,
4657 IN PUCHAR pBssid)
4659 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4661 pHdr80211->FC.Type = BTYPE_MGMT;
4662 pHdr80211->FC.SubType = SubType;
4663 // if (SubType == SUBTYPE_ACK) // sample, no use, it will conflict with ACTION frame sub type
4664 // pHdr80211->FC.Type = BTYPE_CNTL;
4665 pHdr80211->FC.ToDs = ToDs;
4666 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4667 #ifdef CONFIG_STA_SUPPORT
4668 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4669 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4670 #endif // CONFIG_STA_SUPPORT //
4671 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4674 // ===========================================================================================
4675 // mem_mgmt.c
4676 // ===========================================================================================
4678 /*!***************************************************************************
4679 * This routine build an outgoing frame, and fill all information specified
4680 * in argument list to the frame body. The actual frame size is the summation
4681 * of all arguments.
4682 * input params:
4683 * Buffer - pointer to a pre-allocated memory segment
4684 * args - a list of <int arg_size, arg> pairs.
4685 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4686 * function will FAIL!!!
4687 * return:
4688 * Size of the buffer
4689 * usage:
4690 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4692 IRQL = PASSIVE_LEVEL
4693 IRQL = DISPATCH_LEVEL
4695 ****************************************************************************/
4696 ULONG MakeOutgoingFrame(
4697 OUT CHAR *Buffer,
4698 OUT ULONG *FrameLen, ...)
4700 CHAR *p;
4701 int leng;
4702 ULONG TotLeng;
4703 va_list Args;
4705 // calculates the total length
4706 TotLeng = 0;
4707 va_start(Args, FrameLen);
4710 leng = va_arg(Args, int);
4711 if (leng == END_OF_ARGS)
4713 break;
4715 p = va_arg(Args, PVOID);
4716 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4717 TotLeng = TotLeng + leng;
4718 } while(TRUE);
4720 va_end(Args); /* clean up */
4721 *FrameLen = TotLeng;
4722 return TotLeng;
4725 // ===========================================================================================
4726 // mlme_queue.c
4727 // ===========================================================================================
4729 /*! \brief Initialize The MLME Queue, used by MLME Functions
4730 * \param *Queue The MLME Queue
4731 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4732 * \pre
4733 * \post
4734 * \note Because this is done only once (at the init stage), no need to be locked
4736 IRQL = PASSIVE_LEVEL
4739 NDIS_STATUS MlmeQueueInit(
4740 IN MLME_QUEUE *Queue)
4742 INT i;
4744 NdisAllocateSpinLock(&Queue->Lock);
4746 Queue->Num = 0;
4747 Queue->Head = 0;
4748 Queue->Tail = 0;
4750 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4752 Queue->Entry[i].Occupied = FALSE;
4753 Queue->Entry[i].MsgLen = 0;
4754 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4757 return NDIS_STATUS_SUCCESS;
4760 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4761 * \param *Queue The MLME Queue
4762 * \param Machine The State Machine Id
4763 * \param MsgType The Message Type
4764 * \param MsgLen The Message length
4765 * \param *Msg The message pointer
4766 * \return TRUE if enqueue is successful, FALSE if the queue is full
4767 * \pre
4768 * \post
4769 * \note The message has to be initialized
4771 IRQL = PASSIVE_LEVEL
4772 IRQL = DISPATCH_LEVEL
4775 BOOLEAN MlmeEnqueue(
4776 IN PRTMP_ADAPTER pAd,
4777 IN ULONG Machine,
4778 IN ULONG MsgType,
4779 IN ULONG MsgLen,
4780 IN VOID *Msg)
4782 INT Tail;
4783 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4785 // Do nothing if the driver is starting halt state.
4786 // This might happen when timer already been fired before cancel timer with mlmehalt
4787 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4788 return FALSE;
4790 // First check the size, it MUST not exceed the mlme queue size
4791 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4793 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4794 return FALSE;
4797 if (MlmeQueueFull(Queue))
4799 return FALSE;
4802 NdisAcquireSpinLock(&(Queue->Lock));
4803 Tail = Queue->Tail;
4804 Queue->Tail++;
4805 Queue->Num++;
4806 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4808 Queue->Tail = 0;
4811 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4812 Queue->Entry[Tail].Occupied = TRUE;
4813 Queue->Entry[Tail].Machine = Machine;
4814 Queue->Entry[Tail].MsgType = MsgType;
4815 Queue->Entry[Tail].MsgLen = MsgLen;
4817 if (Msg != NULL)
4819 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4822 NdisReleaseSpinLock(&(Queue->Lock));
4823 return TRUE;
4826 /*! \brief This function is used when Recv gets a MLME message
4827 * \param *Queue The MLME Queue
4828 * \param TimeStampHigh The upper 32 bit of timestamp
4829 * \param TimeStampLow The lower 32 bit of timestamp
4830 * \param Rssi The receiving RSSI strength
4831 * \param MsgLen The length of the message
4832 * \param *Msg The message pointer
4833 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4834 * \pre
4835 * \post
4837 IRQL = DISPATCH_LEVEL
4840 BOOLEAN MlmeEnqueueForRecv(
4841 IN PRTMP_ADAPTER pAd,
4842 IN ULONG Wcid,
4843 IN ULONG TimeStampHigh,
4844 IN ULONG TimeStampLow,
4845 IN UCHAR Rssi0,
4846 IN UCHAR Rssi1,
4847 IN UCHAR Rssi2,
4848 IN ULONG MsgLen,
4849 IN VOID *Msg,
4850 IN UCHAR Signal)
4852 INT Tail, Machine;
4853 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4854 INT MsgType;
4855 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4857 #ifdef RALINK_ATE
4858 /* Nothing to do in ATE mode */
4859 if(ATE_ON(pAd))
4860 return FALSE;
4861 #endif // RALINK_ATE //
4863 // Do nothing if the driver is starting halt state.
4864 // This might happen when timer already been fired before cancel timer with mlmehalt
4865 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4867 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4868 return FALSE;
4871 // First check the size, it MUST not exceed the mlme queue size
4872 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4874 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4875 return FALSE;
4878 if (MlmeQueueFull(Queue))
4880 return FALSE;
4883 #ifdef CONFIG_STA_SUPPORT
4884 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4886 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4888 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4889 return FALSE;
4892 #endif // CONFIG_STA_SUPPORT //
4894 // OK, we got all the informations, it is time to put things into queue
4895 NdisAcquireSpinLock(&(Queue->Lock));
4896 Tail = Queue->Tail;
4897 Queue->Tail++;
4898 Queue->Num++;
4899 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4901 Queue->Tail = 0;
4903 Queue->Entry[Tail].Occupied = TRUE;
4904 Queue->Entry[Tail].Machine = Machine;
4905 Queue->Entry[Tail].MsgType = MsgType;
4906 Queue->Entry[Tail].MsgLen = MsgLen;
4907 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4908 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4909 Queue->Entry[Tail].Rssi0 = Rssi0;
4910 Queue->Entry[Tail].Rssi1 = Rssi1;
4911 Queue->Entry[Tail].Rssi2 = Rssi2;
4912 Queue->Entry[Tail].Signal = Signal;
4913 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4915 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4917 if (Msg != NULL)
4919 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4922 NdisReleaseSpinLock(&(Queue->Lock));
4924 RT28XX_MLME_HANDLER(pAd);
4926 return TRUE;
4930 /*! \brief Dequeue a message from the MLME Queue
4931 * \param *Queue The MLME Queue
4932 * \param *Elem The message dequeued from MLME Queue
4933 * \return TRUE if the Elem contains something, FALSE otherwise
4934 * \pre
4935 * \post
4937 IRQL = DISPATCH_LEVEL
4940 BOOLEAN MlmeDequeue(
4941 IN MLME_QUEUE *Queue,
4942 OUT MLME_QUEUE_ELEM **Elem)
4944 NdisAcquireSpinLock(&(Queue->Lock));
4945 *Elem = &(Queue->Entry[Queue->Head]);
4946 Queue->Num--;
4947 Queue->Head++;
4948 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4950 Queue->Head = 0;
4952 NdisReleaseSpinLock(&(Queue->Lock));
4953 return TRUE;
4956 // IRQL = DISPATCH_LEVEL
4957 VOID MlmeRestartStateMachine(
4958 IN PRTMP_ADAPTER pAd)
4960 #ifdef CONFIG_STA_SUPPORT
4961 BOOLEAN Cancelled;
4962 #endif // CONFIG_STA_SUPPORT //
4964 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4967 #ifdef CONFIG_STA_SUPPORT
4968 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4970 #ifdef QOS_DLS_SUPPORT
4971 UCHAR i;
4972 #endif // QOS_DLS_SUPPORT //
4973 // Cancel all timer events
4974 // Be careful to cancel new added timer
4975 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4976 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4977 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4978 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4979 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4980 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4982 #ifdef QOS_DLS_SUPPORT
4983 for (i=0; i<MAX_NUM_OF_DLS_ENTRY; i++)
4985 RTMPCancelTimer(&pAd->StaCfg.DLSEntry[i].Timer, &Cancelled);
4987 #endif // QOS_DLS_SUPPORT //
4989 #endif // CONFIG_STA_SUPPORT //
4991 // Change back to original channel in case of doing scan
4992 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4993 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4995 // Resume MSDU which is turned off durning scan
4996 RTMPResumeMsduTransmission(pAd);
4998 #ifdef CONFIG_STA_SUPPORT
4999 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
5001 // Set all state machines back IDLE
5002 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
5003 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
5004 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
5005 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
5006 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
5007 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
5008 #ifdef QOS_DLS_SUPPORT
5009 pAd->Mlme.DlsMachine.CurrState = DLS_IDLE;
5010 #endif // QOS_DLS_SUPPORT //
5012 #endif // CONFIG_STA_SUPPORT //
5016 /*! \brief test if the MLME Queue is empty
5017 * \param *Queue The MLME Queue
5018 * \return TRUE if the Queue is empty, FALSE otherwise
5019 * \pre
5020 * \post
5022 IRQL = DISPATCH_LEVEL
5025 BOOLEAN MlmeQueueEmpty(
5026 IN MLME_QUEUE *Queue)
5028 BOOLEAN Ans;
5030 NdisAcquireSpinLock(&(Queue->Lock));
5031 Ans = (Queue->Num == 0);
5032 NdisReleaseSpinLock(&(Queue->Lock));
5034 return Ans;
5037 /*! \brief test if the MLME Queue is full
5038 * \param *Queue The MLME Queue
5039 * \return TRUE if the Queue is empty, FALSE otherwise
5040 * \pre
5041 * \post
5043 IRQL = PASSIVE_LEVEL
5044 IRQL = DISPATCH_LEVEL
5047 BOOLEAN MlmeQueueFull(
5048 IN MLME_QUEUE *Queue)
5050 BOOLEAN Ans;
5052 NdisAcquireSpinLock(&(Queue->Lock));
5053 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
5054 NdisReleaseSpinLock(&(Queue->Lock));
5056 return Ans;
5059 /*! \brief The destructor of MLME Queue
5060 * \param
5061 * \return
5062 * \pre
5063 * \post
5064 * \note Clear Mlme Queue, Set Queue->Num to Zero.
5066 IRQL = PASSIVE_LEVEL
5069 VOID MlmeQueueDestroy(
5070 IN MLME_QUEUE *pQueue)
5072 NdisAcquireSpinLock(&(pQueue->Lock));
5073 pQueue->Num = 0;
5074 pQueue->Head = 0;
5075 pQueue->Tail = 0;
5076 NdisReleaseSpinLock(&(pQueue->Lock));
5077 NdisFreeSpinLock(&(pQueue->Lock));
5080 /*! \brief To substitute the message type if the message is coming from external
5081 * \param pFrame The frame received
5082 * \param *Machine The state machine
5083 * \param *MsgType the message type for the state machine
5084 * \return TRUE if the substitution is successful, FALSE otherwise
5085 * \pre
5086 * \post
5088 IRQL = DISPATCH_LEVEL
5091 #ifdef CONFIG_STA_SUPPORT
5092 BOOLEAN MsgTypeSubst(
5093 IN PRTMP_ADAPTER pAd,
5094 IN PFRAME_802_11 pFrame,
5095 OUT INT *Machine,
5096 OUT INT *MsgType)
5098 USHORT Seq;
5099 UCHAR EAPType;
5100 PUCHAR pData;
5102 // Pointer to start of data frames including SNAP header
5103 pData = (PUCHAR) pFrame + LENGTH_802_11;
5105 // The only data type will pass to this function is EAPOL frame
5106 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
5108 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
5110 // Cisco Aironet SNAP header
5111 *Machine = AIRONET_STATE_MACHINE;
5112 *MsgType = MT2_AIRONET_MSG;
5113 return (TRUE);
5115 #ifdef LEAP_SUPPORT
5116 if ( pAd->StaCfg.LeapAuthMode == CISCO_AuthModeLEAP ) //LEAP
5118 // LEAP frames
5119 *Machine = LEAP_STATE_MACHINE;
5120 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5121 return (LeapMsgTypeSubst(EAPType, MsgType));
5123 else
5124 #endif // LEAP_SUPPORT //
5126 *Machine = WPA_PSK_STATE_MACHINE;
5127 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
5128 return(WpaMsgTypeSubst(EAPType, MsgType));
5132 switch (pFrame->Hdr.FC.SubType)
5134 case SUBTYPE_ASSOC_REQ:
5135 *Machine = ASSOC_STATE_MACHINE;
5136 *MsgType = MT2_PEER_ASSOC_REQ;
5137 break;
5138 case SUBTYPE_ASSOC_RSP:
5139 *Machine = ASSOC_STATE_MACHINE;
5140 *MsgType = MT2_PEER_ASSOC_RSP;
5141 break;
5142 case SUBTYPE_REASSOC_REQ:
5143 *Machine = ASSOC_STATE_MACHINE;
5144 *MsgType = MT2_PEER_REASSOC_REQ;
5145 break;
5146 case SUBTYPE_REASSOC_RSP:
5147 *Machine = ASSOC_STATE_MACHINE;
5148 *MsgType = MT2_PEER_REASSOC_RSP;
5149 break;
5150 case SUBTYPE_PROBE_REQ:
5151 *Machine = SYNC_STATE_MACHINE;
5152 *MsgType = MT2_PEER_PROBE_REQ;
5153 break;
5154 case SUBTYPE_PROBE_RSP:
5155 *Machine = SYNC_STATE_MACHINE;
5156 *MsgType = MT2_PEER_PROBE_RSP;
5157 break;
5158 case SUBTYPE_BEACON:
5159 *Machine = SYNC_STATE_MACHINE;
5160 *MsgType = MT2_PEER_BEACON;
5161 break;
5162 case SUBTYPE_ATIM:
5163 *Machine = SYNC_STATE_MACHINE;
5164 *MsgType = MT2_PEER_ATIM;
5165 break;
5166 case SUBTYPE_DISASSOC:
5167 *Machine = ASSOC_STATE_MACHINE;
5168 *MsgType = MT2_PEER_DISASSOC_REQ;
5169 break;
5170 case SUBTYPE_AUTH:
5171 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
5172 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
5173 if (Seq == 1 || Seq == 3)
5175 *Machine = AUTH_RSP_STATE_MACHINE;
5176 *MsgType = MT2_PEER_AUTH_ODD;
5178 else if (Seq == 2 || Seq == 4)
5180 *Machine = AUTH_STATE_MACHINE;
5181 *MsgType = MT2_PEER_AUTH_EVEN;
5183 else
5185 return FALSE;
5187 break;
5188 case SUBTYPE_DEAUTH:
5189 *Machine = AUTH_RSP_STATE_MACHINE;
5190 *MsgType = MT2_PEER_DEAUTH;
5191 break;
5192 case SUBTYPE_ACTION:
5193 *Machine = ACTION_STATE_MACHINE;
5194 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
5195 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
5197 *MsgType = MT2_ACT_INVALID;
5199 else
5201 *MsgType = (pFrame->Octet[0]&0x7F);
5203 break;
5204 default:
5205 return FALSE;
5206 break;
5209 return TRUE;
5211 #endif // CONFIG_STA_SUPPORT //
5213 // ===========================================================================================
5214 // state_machine.c
5215 // ===========================================================================================
5217 /*! \brief Initialize the state machine.
5218 * \param *S pointer to the state machine
5219 * \param Trans State machine transition function
5220 * \param StNr number of states
5221 * \param MsgNr number of messages
5222 * \param DefFunc default function, when there is invalid state/message combination
5223 * \param InitState initial state of the state machine
5224 * \param Base StateMachine base, internal use only
5225 * \pre p_sm should be a legal pointer
5226 * \post
5228 IRQL = PASSIVE_LEVEL
5231 VOID StateMachineInit(
5232 IN STATE_MACHINE *S,
5233 IN STATE_MACHINE_FUNC Trans[],
5234 IN ULONG StNr,
5235 IN ULONG MsgNr,
5236 IN STATE_MACHINE_FUNC DefFunc,
5237 IN ULONG InitState,
5238 IN ULONG Base)
5240 ULONG i, j;
5242 // set number of states and messages
5243 S->NrState = StNr;
5244 S->NrMsg = MsgNr;
5245 S->Base = Base;
5247 S->TransFunc = Trans;
5249 // init all state transition to default function
5250 for (i = 0; i < StNr; i++)
5252 for (j = 0; j < MsgNr; j++)
5254 S->TransFunc[i * MsgNr + j] = DefFunc;
5258 // set the starting state
5259 S->CurrState = InitState;
5262 /*! \brief This function fills in the function pointer into the cell in the state machine
5263 * \param *S pointer to the state machine
5264 * \param St state
5265 * \param Msg incoming message
5266 * \param f the function to be executed when (state, message) combination occurs at the state machine
5267 * \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
5268 * \post
5270 IRQL = PASSIVE_LEVEL
5273 VOID StateMachineSetAction(
5274 IN STATE_MACHINE *S,
5275 IN ULONG St,
5276 IN ULONG Msg,
5277 IN STATE_MACHINE_FUNC Func)
5279 ULONG MsgIdx;
5281 MsgIdx = Msg - S->Base;
5283 if (St < S->NrState && MsgIdx < S->NrMsg)
5285 // boundary checking before setting the action
5286 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5290 /*! \brief This function does the state transition
5291 * \param *Adapter the NIC adapter pointer
5292 * \param *S the state machine
5293 * \param *Elem the message to be executed
5294 * \return None
5296 IRQL = DISPATCH_LEVEL
5299 VOID StateMachinePerformAction(
5300 IN PRTMP_ADAPTER pAd,
5301 IN STATE_MACHINE *S,
5302 IN MLME_QUEUE_ELEM *Elem)
5304 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5308 ==========================================================================
5309 Description:
5310 The drop function, when machine executes this, the message is simply
5311 ignored. This function does nothing, the message is freed in
5312 StateMachinePerformAction()
5313 ==========================================================================
5315 VOID Drop(
5316 IN PRTMP_ADAPTER pAd,
5317 IN MLME_QUEUE_ELEM *Elem)
5321 // ===========================================================================================
5322 // lfsr.c
5323 // ===========================================================================================
5326 ==========================================================================
5327 Description:
5329 IRQL = PASSIVE_LEVEL
5331 ==========================================================================
5333 VOID LfsrInit(
5334 IN PRTMP_ADAPTER pAd,
5335 IN ULONG Seed)
5337 if (Seed == 0)
5338 pAd->Mlme.ShiftReg = 1;
5339 else
5340 pAd->Mlme.ShiftReg = Seed;
5344 ==========================================================================
5345 Description:
5346 ==========================================================================
5348 UCHAR RandomByte(
5349 IN PRTMP_ADAPTER pAd)
5351 ULONG i;
5352 UCHAR R, Result;
5354 R = 0;
5356 if (pAd->Mlme.ShiftReg == 0)
5357 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5359 for (i = 0; i < 8; i++)
5361 if (pAd->Mlme.ShiftReg & 0x00000001)
5363 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5364 Result = 1;
5366 else
5368 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5369 Result = 0;
5371 R = (R << 1) | Result;
5374 return R;
5377 VOID AsicUpdateAutoFallBackTable(
5378 IN PRTMP_ADAPTER pAd,
5379 IN PUCHAR pRateTable)
5381 UCHAR i;
5382 HT_FBK_CFG0_STRUC HtCfg0;
5383 HT_FBK_CFG1_STRUC HtCfg1;
5384 LG_FBK_CFG0_STRUC LgCfg0;
5385 LG_FBK_CFG1_STRUC LgCfg1;
5386 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5388 // set to initial value
5389 HtCfg0.word = 0x65432100;
5390 HtCfg1.word = 0xedcba988;
5391 LgCfg0.word = 0xedcba988;
5392 LgCfg1.word = 0x00002100;
5394 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5395 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5397 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5398 switch (pCurrTxRate->Mode)
5400 case 0: //CCK
5401 break;
5402 case 1: //OFDM
5404 switch(pCurrTxRate->CurrMCS)
5406 case 0:
5407 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5408 break;
5409 case 1:
5410 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5411 break;
5412 case 2:
5413 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5414 break;
5415 case 3:
5416 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5417 break;
5418 case 4:
5419 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5420 break;
5421 case 5:
5422 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5423 break;
5424 case 6:
5425 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5426 break;
5427 case 7:
5428 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5429 break;
5432 break;
5433 #ifdef DOT11_N_SUPPORT
5434 case 2: //HT-MIX
5435 case 3: //HT-GF
5437 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5439 switch(pCurrTxRate->CurrMCS)
5441 case 0:
5442 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5443 break;
5444 case 1:
5445 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5446 break;
5447 case 2:
5448 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5449 break;
5450 case 3:
5451 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5452 break;
5453 case 4:
5454 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5455 break;
5456 case 5:
5457 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5458 break;
5459 case 6:
5460 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5461 break;
5462 case 7:
5463 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5464 break;
5465 case 8:
5466 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5467 break;
5468 case 9:
5469 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5470 break;
5471 case 10:
5472 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5473 break;
5474 case 11:
5475 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5476 break;
5477 case 12:
5478 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5479 break;
5480 case 13:
5481 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5482 break;
5483 case 14:
5484 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5485 break;
5486 case 15:
5487 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5488 break;
5489 default:
5490 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5494 break;
5495 #endif // DOT11_N_SUPPORT //
5498 pNextTxRate = pCurrTxRate;
5501 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5502 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5503 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5504 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5508 ========================================================================
5510 Routine Description:
5511 Set MAC register value according operation mode.
5512 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5513 If MM or GF mask is not set, those passing argument doesn't not take effect.
5515 Operation mode meaning:
5516 = 0 : Pure HT, no preotection.
5517 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5518 = 0x10: No Transmission in 40M is protected.
5519 = 0x11: Transmission in both 40M and 20M shall be protected
5520 if (bNonGFExist)
5521 we should choose not to use GF. But still set correct ASIC registers.
5522 ========================================================================
5524 VOID AsicUpdateProtect(
5525 IN PRTMP_ADAPTER pAd,
5526 IN USHORT OperationMode,
5527 IN UCHAR SetMask,
5528 IN BOOLEAN bDisableBGProtect,
5529 IN BOOLEAN bNonGFExist)
5531 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5532 UINT32 Protect[6];
5533 USHORT offset;
5534 UCHAR i;
5535 UINT32 MacReg = 0;
5537 #ifdef RALINK_ATE
5538 if (ATE_ON(pAd))
5539 return;
5540 #endif // RALINK_ATE //
5542 #ifdef DOT11_N_SUPPORT
5543 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5545 return;
5548 if (pAd->BATable.numAsOriginator)
5551 // enable the RTS/CTS to avoid channel collision
5553 SetMask = ALLN_SETPROTECT;
5554 OperationMode = 8;
5556 #endif // DOT11_N_SUPPORT //
5558 // Config ASIC RTS threshold register
5559 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5560 MacReg &= 0xFF0000FF;
5561 #if 0
5562 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5563 #else
5564 // If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5565 if ((
5566 #ifdef DOT11_N_SUPPORT
5567 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5568 #endif // DOT11_N_SUPPORT //
5569 (pAd->CommonCfg.bAggregationCapable == TRUE))
5570 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5572 MacReg |= (0x1000 << 8);
5574 else
5576 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5578 #endif
5580 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5582 // Initial common protection settings
5583 RTMPZeroMemory(Protect, sizeof(Protect));
5584 ProtCfg4.word = 0;
5585 ProtCfg.word = 0;
5586 ProtCfg.field.TxopAllowGF40 = 1;
5587 ProtCfg.field.TxopAllowGF20 = 1;
5588 ProtCfg.field.TxopAllowMM40 = 1;
5589 ProtCfg.field.TxopAllowMM20 = 1;
5590 ProtCfg.field.TxopAllowOfdm = 1;
5591 ProtCfg.field.TxopAllowCck = 1;
5592 ProtCfg.field.RTSThEn = 1;
5593 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5595 // update PHY mode and rate
5596 if (pAd->CommonCfg.Channel > 14)
5597 ProtCfg.field.ProtectRate = 0x4000;
5598 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5600 // Handle legacy(B/G) protection
5601 if (bDisableBGProtect)
5603 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5604 ProtCfg.field.ProtectCtrl = 0;
5605 Protect[0] = ProtCfg.word;
5606 Protect[1] = ProtCfg.word;
5608 else
5610 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5611 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5612 Protect[0] = ProtCfg.word;
5613 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5614 Protect[1] = ProtCfg.word;
5617 #ifdef DOT11_N_SUPPORT
5618 // Decide HT frame protection.
5619 if ((SetMask & ALLN_SETPROTECT) != 0)
5621 switch(OperationMode)
5623 case 0x0:
5624 // NO PROTECT
5625 // 1.All STAs in the BSS are 20/40 MHz HT
5626 // 2. in ai 20/40MHz BSS
5627 // 3. all STAs are 20MHz in a 20MHz BSS
5628 // Pure HT. no protection.
5630 // MM20_PROT_CFG
5631 // Reserved (31:27)
5632 // PROT_TXOP(25:20) -- 010111
5633 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5634 // PROT_CTRL(17:16) -- 00 (None)
5635 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5636 Protect[2] = 0x01744004;
5638 // MM40_PROT_CFG
5639 // Reserved (31:27)
5640 // PROT_TXOP(25:20) -- 111111
5641 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5642 // PROT_CTRL(17:16) -- 00 (None)
5643 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5644 Protect[3] = 0x03f44084;
5646 // CF20_PROT_CFG
5647 // Reserved (31:27)
5648 // PROT_TXOP(25:20) -- 010111
5649 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5650 // PROT_CTRL(17:16) -- 00 (None)
5651 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5652 Protect[4] = 0x01744004;
5654 // CF40_PROT_CFG
5655 // Reserved (31:27)
5656 // PROT_TXOP(25:20) -- 111111
5657 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5658 // PROT_CTRL(17:16) -- 00 (None)
5659 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5660 Protect[5] = 0x03f44084;
5662 if (bNonGFExist)
5664 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5665 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5666 Protect[4] = 0x01754004;
5667 Protect[5] = 0x03f54084;
5669 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5670 break;
5672 case 1:
5673 // This is "HT non-member protection mode."
5674 // If there may be non-HT STAs my BSS
5675 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5676 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5677 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5679 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5680 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5682 //Assign Protection method for 20&40 MHz packets
5683 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5684 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5685 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5686 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5687 Protect[2] = ProtCfg.word;
5688 Protect[3] = ProtCfg4.word;
5689 Protect[4] = ProtCfg.word;
5690 Protect[5] = ProtCfg4.word;
5691 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5692 break;
5694 case 2:
5695 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5696 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5697 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5699 //Assign Protection method for 40MHz packets
5700 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5701 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5702 Protect[2] = ProtCfg.word;
5703 Protect[3] = ProtCfg4.word;
5704 if (bNonGFExist)
5706 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5707 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5709 Protect[4] = ProtCfg.word;
5710 Protect[5] = ProtCfg4.word;
5712 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5713 break;
5715 case 3:
5716 // HT mixed mode. PROTECT ALL!
5717 // Assign Rate
5718 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5719 ProtCfg4.word = 0x03f44084;
5720 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5721 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5723 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5724 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5726 //Assign Protection method for 20&40 MHz packets
5727 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5728 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5729 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5730 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5731 Protect[2] = ProtCfg.word;
5732 Protect[3] = ProtCfg4.word;
5733 Protect[4] = ProtCfg.word;
5734 Protect[5] = ProtCfg4.word;
5735 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5736 break;
5738 case 8:
5739 // Special on for Atheros problem n chip.
5740 Protect[2] = 0x01754004;
5741 Protect[3] = 0x03f54084;
5742 Protect[4] = 0x01754004;
5743 Protect[5] = 0x03f54084;
5744 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5745 break;
5748 #endif // DOT11_N_SUPPORT //
5750 offset = CCK_PROT_CFG;
5751 for (i = 0;i < 6;i++)
5753 if ((SetMask & (1<< i)))
5755 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5761 ==========================================================================
5762 Description:
5764 IRQL = PASSIVE_LEVEL
5765 IRQL = DISPATCH_LEVEL
5767 ==========================================================================
5769 VOID AsicSwitchChannel(
5770 IN PRTMP_ADAPTER pAd,
5771 IN UCHAR Channel,
5772 IN BOOLEAN bScan)
5774 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5775 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5776 UCHAR index;
5777 UINT32 Value = 0; //BbpReg, Value;
5778 RTMP_RF_REGS *RFRegTable;
5780 // Search Tx power value
5781 for (index = 0; index < pAd->ChannelListNum; index++)
5783 if (Channel == pAd->ChannelList[index].Channel)
5785 TxPwer = pAd->ChannelList[index].Power;
5786 TxPwer2 = pAd->ChannelList[index].Power2;
5787 break;
5791 if (index == MAX_NUM_OF_CHANNELS)
5793 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5796 #ifdef RT2870
5797 // The RF programming sequence is difference between 3xxx and 2xxx
5798 if (IS_RT3070(pAd) && ((pAd->RfIcType == RFIC_3020) || (pAd->RfIcType == RFIC_2020)))
5800 /* modify by WY for Read RF Reg. error */
5801 UCHAR RFValue;
5803 for (index = 0; index < NUM_OF_3020_CHNL; index++)
5805 if (Channel == FreqItems3020[index].Channel)
5807 // Programming channel parameters
5808 RT30xxWriteRFRegister(pAd, RF_R02, FreqItems3020[index].N);
5809 RT30xxWriteRFRegister(pAd, RF_R03, FreqItems3020[index].K);
5811 RT30xxReadRFRegister(pAd, RF_R06, (PUCHAR)&RFValue);
5812 RFValue = (RFValue & 0xFC) | FreqItems3020[index].R;
5813 RT30xxWriteRFRegister(pAd, RF_R06, (UCHAR)RFValue);
5815 // Set Tx Power
5816 RT30xxReadRFRegister(pAd, RF_R12, (PUCHAR)&RFValue);
5817 RFValue = (RFValue & 0xE0) | TxPwer;
5818 RT30xxWriteRFRegister(pAd, RF_R12, (UCHAR)RFValue);
5820 // Set RF offset
5821 RT30xxReadRFRegister(pAd, RF_R23, (PUCHAR)&RFValue);
5822 RFValue = (RFValue & 0x80) | pAd->RfFreqOffset;
5823 RT30xxWriteRFRegister(pAd, RF_R23, (UCHAR)RFValue);
5825 // Set BW
5826 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5828 RFValue = pAd->Mlme.CaliBW40RfR24;
5829 //DISABLE_11N_CHECK(pAd);
5831 else
5833 RFValue = pAd->Mlme.CaliBW20RfR24;
5835 RT30xxWriteRFRegister(pAd, RF_R24, (UCHAR)RFValue);
5837 // Enable RF tuning
5838 RT30xxReadRFRegister(pAd, RF_R07, (PUCHAR)&RFValue);
5839 RFValue = RFValue | 0x1;
5840 RT30xxWriteRFRegister(pAd, RF_R07, (UCHAR)RFValue);
5842 // latch channel for future usage.
5843 pAd->LatchRfRegs.Channel = Channel;
5845 break;
5849 DBGPRINT(RT_DEBUG_TRACE, ("SwitchChannel#%d(RF=%d, Pwr0=%d, Pwr1=%d, %dT), N=0x%02X, K=0x%02X, R=0x%02X\n",
5850 Channel,
5851 pAd->RfIcType,
5852 TxPwer,
5853 TxPwer2,
5854 pAd->Antenna.field.TxPath,
5855 FreqItems3020[index].N,
5856 FreqItems3020[index].K,
5857 FreqItems3020[index].R));
5859 else
5860 #endif // RT2870 //
5862 RFRegTable = RF2850RegTable;
5864 switch (pAd->RfIcType)
5866 case RFIC_2820:
5867 case RFIC_2850:
5868 case RFIC_2720:
5869 case RFIC_2750:
5871 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5873 if (Channel == RFRegTable[index].Channel)
5875 R2 = RFRegTable[index].R2;
5876 if (pAd->Antenna.field.TxPath == 1)
5878 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5881 if (pAd->Antenna.field.RxPath == 2)
5883 R2 |= 0x40; // write 1 to off Rxpath.
5885 else if (pAd->Antenna.field.RxPath == 1)
5887 R2 |= 0x20040; // write 1 to off RxPath
5890 if (Channel > 14)
5892 // initialize R3, R4
5893 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5894 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5896 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5897 // R3
5898 if ((TxPwer >= -7) && (TxPwer < 0))
5900 TxPwer = (7+TxPwer);
5901 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5902 R3 |= (TxPwer << 10);
5903 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5905 else
5907 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5908 R3 |= (TxPwer << 10) | (1 << 9);
5911 // R4
5912 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5914 TxPwer2 = (7+TxPwer2);
5915 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5916 R4 |= (TxPwer2 << 7);
5917 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5919 else
5921 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5922 R4 |= (TxPwer2 << 7) | (1 << 6);
5925 else
5927 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5928 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5931 // Based on BBP current mode before changing RF channel.
5932 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5934 R4 |=0x200000;
5937 // Update variables
5938 pAd->LatchRfRegs.Channel = Channel;
5939 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5940 pAd->LatchRfRegs.R2 = R2;
5941 pAd->LatchRfRegs.R3 = R3;
5942 pAd->LatchRfRegs.R4 = R4;
5944 // Set RF value 1's set R3[bit2] = [0]
5945 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5946 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5947 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5948 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5950 RTMPusecDelay(200);
5952 // Set RF value 2's set R3[bit2] = [1]
5953 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5954 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5955 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5956 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5958 RTMPusecDelay(200);
5960 // Set RF value 3's set R3[bit2] = [0]
5961 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5962 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5963 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5964 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5966 break;
5969 break;
5971 default:
5972 break;
5976 // Change BBP setting during siwtch from a->g, g->a
5977 if (Channel <= 14)
5979 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5981 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5982 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5983 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5984 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.
5985 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5987 // Rx High power VGA offset for LNA select
5988 if (pAd->NicConfig2.field.ExternalLNAForG)
5990 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5991 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5993 else
5995 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5996 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5999 // 5G band selection PIN, bit1 and bit2 are complement
6000 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
6001 Value &= (~0x6);
6002 Value |= (0x04);
6003 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
6005 // Turn off unused PA or LNA when only 1T or 1R
6006 if (pAd->Antenna.field.TxPath == 1)
6008 TxPinCfg &= 0xFFFFFFF3;
6010 if (pAd->Antenna.field.RxPath == 1)
6012 TxPinCfg &= 0xFFFFF3FF;
6015 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
6017 else
6019 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
6021 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
6022 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
6023 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
6024 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.
6025 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
6027 // Rx High power VGA offset for LNA select
6028 if (pAd->NicConfig2.field.ExternalLNAForA)
6030 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
6032 else
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);
6039 Value &= (~0x6);
6040 Value |= (0x02);
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);
6056 // R66 should be set according to Channel and use 20MHz when scanning
6057 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
6058 if (bScan)
6059 RTMPSetAGCInitValue(pAd, BW_20);
6060 else
6061 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
6064 // On 11A, We should delay and wait RF/BBP to be stable
6065 // and the appropriate time should be 1000 micro seconds
6066 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
6068 RTMPusecDelay(1000);
6070 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",
6071 Channel,
6072 pAd->RfIcType,
6073 (R3 & 0x00003e00) >> 9,
6074 (R4 & 0x000007c0) >> 6,
6075 pAd->Antenna.field.TxPath,
6076 pAd->LatchRfRegs.R1,
6077 pAd->LatchRfRegs.R2,
6078 pAd->LatchRfRegs.R3,
6079 pAd->LatchRfRegs.R4));
6083 ==========================================================================
6084 Description:
6085 This function is required for 2421 only, and should not be used during
6086 site survey. It's only required after NIC decided to stay at a channel
6087 for a longer period.
6088 When this function is called, it's always after AsicSwitchChannel().
6090 IRQL = PASSIVE_LEVEL
6091 IRQL = DISPATCH_LEVEL
6093 ==========================================================================
6095 VOID AsicLockChannel(
6096 IN PRTMP_ADAPTER pAd,
6097 IN UCHAR Channel)
6102 ==========================================================================
6103 Description:
6105 IRQL = PASSIVE_LEVEL
6106 IRQL = DISPATCH_LEVEL
6108 ==========================================================================
6110 VOID AsicAntennaSelect(
6111 IN PRTMP_ADAPTER pAd,
6112 IN UCHAR Channel)
6117 ========================================================================
6119 Routine Description:
6120 Antenna miscellaneous setting.
6122 Arguments:
6123 pAd Pointer to our adapter
6124 BandState Indicate current Band State.
6126 Return Value:
6127 None
6129 IRQL <= DISPATCH_LEVEL
6131 Note:
6132 1.) Frame End type control
6133 only valid for G only (RF_2527 & RF_2529)
6134 0: means DPDT, set BBP R4 bit 5 to 1
6135 1: means SPDT, set BBP R4 bit 5 to 0
6138 ========================================================================
6140 VOID AsicAntennaSetting(
6141 IN PRTMP_ADAPTER pAd,
6142 IN ABGBAND_STATE BandState)
6146 VOID AsicRfTuningExec(
6147 IN PVOID SystemSpecific1,
6148 IN PVOID FunctionContext,
6149 IN PVOID SystemSpecific2,
6150 IN PVOID SystemSpecific3)
6155 ==========================================================================
6156 Description:
6157 Gives CCK TX rate 2 more dB TX power.
6158 This routine works only in LINK UP in INFRASTRUCTURE mode.
6160 calculate desired Tx power in RF R3.Tx0~5, should consider -
6161 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
6162 1. TxPowerPercentage
6163 2. auto calibration based on TSSI feedback
6164 3. extra 2 db for CCK
6165 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
6167 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
6168 it should be called AFTER MlmeDynamicTxRatSwitching()
6169 ==========================================================================
6171 VOID AsicAdjustTxPower(
6172 IN PRTMP_ADAPTER pAd)
6174 INT i, j;
6175 CHAR DeltaPwr = 0;
6176 BOOLEAN bAutoTxAgc = FALSE;
6177 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
6178 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
6179 PCHAR pTxAgcCompensate;
6180 ULONG TxPwr[5];
6181 CHAR Value;
6183 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
6185 if (pAd->CommonCfg.CentralChannel > 14)
6187 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
6188 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
6189 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
6190 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
6191 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
6193 else
6195 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
6196 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
6197 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
6198 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
6199 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
6202 else
6204 if (pAd->CommonCfg.Channel > 14)
6206 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
6207 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
6208 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
6209 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
6210 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
6212 else
6214 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
6215 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
6216 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
6217 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
6218 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
6222 // TX power compensation for temperature variation based on TSSI. try every 4 second
6223 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
6225 if (pAd->CommonCfg.Channel <= 14)
6227 /* bg channel */
6228 bAutoTxAgc = pAd->bAutoTxAgcG;
6229 TssiRef = pAd->TssiRefG;
6230 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
6231 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
6232 TxAgcStep = pAd->TxAgcStepG;
6233 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6235 else
6237 /* a channel */
6238 bAutoTxAgc = pAd->bAutoTxAgcA;
6239 TssiRef = pAd->TssiRefA;
6240 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
6241 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
6242 TxAgcStep = pAd->TxAgcStepA;
6243 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6246 if (bAutoTxAgc)
6248 /* BbpR1 is unsigned char */
6249 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
6251 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
6252 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
6253 /* step value is defined in pAd->TxAgcStepG for tx power value */
6255 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
6256 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
6257 above value are examined in mass factory production */
6258 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
6260 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
6261 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
6262 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
6264 if (BbpR49 > pTssiMinusBoundary[1])
6266 // Reading is larger than the reference value
6267 // check for how large we need to decrease the Tx power
6268 for (idx = 1; idx < 5; idx++)
6270 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
6271 break;
6273 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
6274 // if (R3 > (ULONG) (TxAgcStep * (idx-1)))
6275 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
6276 // else
6277 // *pTxAgcCompensate = -((UCHAR)R3);
6279 DeltaPwr += (*pTxAgcCompensate);
6280 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
6281 BbpR49, TssiRef, TxAgcStep, idx-1));
6283 else if (BbpR49 < pTssiPlusBoundary[1])
6285 // Reading is smaller than the reference value
6286 // check for how large we need to increase the Tx power
6287 for (idx = 1; idx < 5; idx++)
6289 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
6290 break;
6292 // The index is the step we should increase, idx = 0 means there is nothing to compensate
6293 *pTxAgcCompensate = TxAgcStep * (idx-1);
6294 DeltaPwr += (*pTxAgcCompensate);
6295 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6296 BbpR49, TssiRef, TxAgcStep, idx-1));
6298 else
6300 *pTxAgcCompensate = 0;
6301 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
6302 BbpR49, TssiRef, TxAgcStep, 0));
6306 else
6308 if (pAd->CommonCfg.Channel <= 14)
6310 bAutoTxAgc = pAd->bAutoTxAgcG;
6311 pTxAgcCompensate = &pAd->TxAgcCompensateG;
6313 else
6315 bAutoTxAgc = pAd->bAutoTxAgcA;
6316 pTxAgcCompensate = &pAd->TxAgcCompensateA;
6319 if (bAutoTxAgc)
6320 DeltaPwr += (*pTxAgcCompensate);
6323 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6324 BbpR1 &= 0xFC;
6326 #ifdef SINGLE_SKU
6327 // Handle regulatory max tx power constrain
6330 UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion;
6331 UCHAR AdjustMaxTxPwr[40];
6333 if (pAd->CommonCfg.Channel > 14) // 5G band
6334 TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8);
6335 else // 2.4G band
6336 TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF);
6337 CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
6339 // error handling, range check
6340 if ((TxPwrInEEPROM > 0x50) || (CountryTxPwr > 0x50))
6342 DBGPRINT(RT_DEBUG_ERROR,("AsicAdjustTxPower - Invalid max tx power (=0x%02x), CountryTxPwr=%d\n", TxPwrInEEPROM, CountryTxPwr));
6343 break;
6346 criterion = *((PUCHAR)TxPwr + 2) & 0xF; // FAE use OFDM 6M as criterion
6348 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d)\n", criterion, TxPwrInEEPROM, CountryTxPwr));
6350 // Adjust max tx power according to the relationship of tx power in E2PROM
6351 for (i=0; i<5; i++)
6353 // CCK will have 4dBm larger than OFDM
6354 // Therefore, we should separate to parse the tx power field
6355 if (i == 0)
6357 for (j=0; j<8; j++)
6359 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6361 if (j < 4)
6363 // CCK will have 4dBm larger than OFDM
6364 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4;
6366 else
6368 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6370 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6373 else
6375 for (j=0; j<8; j++)
6377 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6379 AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion);
6380 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6385 // Adjust tx power according to the relationship
6386 for (i=0; i<5; i++)
6388 if (TxPwr[i] != 0xffffffff)
6390 for (j=0; j<8; j++)
6392 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F);
6394 // The system tx power is larger than the regulatory, the power should be restrain
6395 if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr)
6397 // decrease to zero and don't need to take care BBPR1
6398 if ((Value - (AdjustMaxTxPwr[i*8+j] - CountryTxPwr)) > 0)
6399 Value -= (AdjustMaxTxPwr[i*8+j] - CountryTxPwr);
6400 else
6401 Value = 0;
6403 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6405 else
6406 DBGPRINT_RAW(RT_DEBUG_TRACE,("AsicAdjustTxPower (i/j=%d/%d, Value=%d, %d, no change)\n", i, j, Value, AdjustMaxTxPwr[i*8+j]));
6408 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6412 } while (FALSE);
6413 #endif // SINGLE_SKU //
6415 /* calculate delta power based on the percentage specified from UI */
6416 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6417 // We lower TX power here according to the percentage specified from UI
6418 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6420 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6422 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6424 DeltaPwr -= 1;
6426 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6428 DeltaPwr -= 3;
6430 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6432 BbpR1 |= 0x01;
6434 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6436 BbpR1 |= 0x01;
6437 DeltaPwr -= 3;
6439 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6441 BbpR1 |= 0x02;
6444 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6446 /* reset different new tx power for different TX rate */
6447 for(i=0; i<5; i++)
6449 if (TxPwr[i] != 0xffffffff)
6451 for (j=0; j<8; j++)
6453 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6455 if ((Value + DeltaPwr) < 0)
6457 Value = 0; /* min */
6459 else if ((Value + DeltaPwr) > 0xF)
6461 Value = 0xF; /* max */
6463 else
6465 Value += DeltaPwr; /* temperature compensation */
6468 /* fill new value to CSR offset */
6469 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6472 /* write tx power value to CSR */
6473 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6474 TX power for OFDM 6M/9M
6475 TX power for CCK5.5M/11M
6476 TX power for CCK1M/2M */
6477 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6478 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6484 #ifdef CONFIG_STA_SUPPORT
6486 ==========================================================================
6487 Description:
6488 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6489 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6490 the wakeup timer timeout. Driver has to issue a separate command to wake
6491 PHY up.
6493 IRQL = DISPATCH_LEVEL
6495 ==========================================================================
6497 VOID AsicSleepThenAutoWakeup(
6498 IN PRTMP_ADAPTER pAd,
6499 IN USHORT TbttNumToNextWakeUp)
6501 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6505 ==========================================================================
6506 Description:
6507 AsicForceWakeup() is used whenever manual wakeup is required
6508 AsicForceSleep() should only be used when not in INFRA BSS. When
6509 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6510 ==========================================================================
6512 VOID AsicForceSleep(
6513 IN PRTMP_ADAPTER pAd)
6519 ==========================================================================
6520 Description:
6521 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6522 expired.
6524 IRQL = PASSIVE_LEVEL
6525 IRQL = DISPATCH_LEVEL
6526 ==========================================================================
6528 VOID AsicForceWakeup(
6529 IN PRTMP_ADAPTER pAd,
6530 IN BOOLEAN bFromTx)
6532 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6533 RT28XX_STA_FORCE_WAKEUP(pAd, bFromTx);
6535 #endif // CONFIG_STA_SUPPORT //
6537 ==========================================================================
6538 Description:
6539 Set My BSSID
6541 IRQL = DISPATCH_LEVEL
6543 ==========================================================================
6545 VOID AsicSetBssid(
6546 IN PRTMP_ADAPTER pAd,
6547 IN PUCHAR pBssid)
6549 ULONG Addr4;
6550 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6551 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6553 Addr4 = (ULONG)(pBssid[0]) |
6554 (ULONG)(pBssid[1] << 8) |
6555 (ULONG)(pBssid[2] << 16) |
6556 (ULONG)(pBssid[3] << 24);
6557 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6559 Addr4 = 0;
6560 // always one BSSID in STA mode
6561 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6563 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6566 VOID AsicSetMcastWC(
6567 IN PRTMP_ADAPTER pAd)
6569 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6570 USHORT offset;
6572 pEntry->Sst = SST_ASSOC;
6573 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6574 pEntry->PsMode = PWR_ACTIVE;
6575 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6576 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6580 ==========================================================================
6581 Description:
6583 IRQL = DISPATCH_LEVEL
6585 ==========================================================================
6587 VOID AsicDelWcidTab(
6588 IN PRTMP_ADAPTER pAd,
6589 IN UCHAR Wcid)
6591 ULONG Addr0 = 0x0, Addr1 = 0x0;
6592 ULONG offset;
6594 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6595 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6596 RTMP_IO_WRITE32(pAd, offset, Addr0);
6597 offset += 4;
6598 RTMP_IO_WRITE32(pAd, offset, Addr1);
6602 ==========================================================================
6603 Description:
6605 IRQL = DISPATCH_LEVEL
6607 ==========================================================================
6609 VOID AsicEnableRDG(
6610 IN PRTMP_ADAPTER pAd)
6612 TX_LINK_CFG_STRUC TxLinkCfg;
6613 UINT32 Data = 0;
6615 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6616 TxLinkCfg.field.TxRDGEn = 1;
6617 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6619 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6620 Data &= 0xFFFFFF00;
6621 Data |= 0x80;
6622 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6624 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6628 ==========================================================================
6629 Description:
6631 IRQL = DISPATCH_LEVEL
6633 ==========================================================================
6635 VOID AsicDisableRDG(
6636 IN PRTMP_ADAPTER pAd)
6638 TX_LINK_CFG_STRUC TxLinkCfg;
6639 UINT32 Data = 0;
6642 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6643 TxLinkCfg.field.TxRDGEn = 0;
6644 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6646 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6648 Data &= 0xFFFFFF00;
6649 //Data |= 0x20;
6650 #ifndef WIFI_TEST
6651 //if ( pAd->CommonCfg.bEnableTxBurst )
6652 // Data |= 0x60; // for performance issue not set the TXOP to 0
6653 #endif
6654 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6655 #ifdef DOT11_N_SUPPORT
6656 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6657 #endif // DOT11_N_SUPPORT //
6660 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6661 if (pAd->CommonCfg.bEnableTxBurst)
6662 Data |= 0x20;
6664 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6668 ==========================================================================
6669 Description:
6671 IRQL = PASSIVE_LEVEL
6672 IRQL = DISPATCH_LEVEL
6674 ==========================================================================
6676 VOID AsicDisableSync(
6677 IN PRTMP_ADAPTER pAd)
6679 BCN_TIME_CFG_STRUC csr;
6681 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6683 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6684 // that NIC will never wakes up because TSF stops and no more
6685 // TBTT interrupts
6686 pAd->TbttTickCount = 0;
6687 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6688 csr.field.bBeaconGen = 0;
6689 csr.field.bTBTTEnable = 0;
6690 csr.field.TsfSyncMode = 0;
6691 csr.field.bTsfTicking = 0;
6692 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6697 ==========================================================================
6698 Description:
6700 IRQL = DISPATCH_LEVEL
6702 ==========================================================================
6704 VOID AsicEnableBssSync(
6705 IN PRTMP_ADAPTER pAd)
6707 BCN_TIME_CFG_STRUC csr;
6709 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6711 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6712 // RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, 0x00000000);
6713 #ifdef CONFIG_STA_SUPPORT
6714 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6716 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6717 csr.field.bTsfTicking = 1;
6718 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6719 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6720 csr.field.bTBTTEnable = 1;
6722 #endif // CONFIG_STA_SUPPORT //
6723 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6727 ==========================================================================
6728 Description:
6729 Note:
6730 BEACON frame in shared memory should be built ok before this routine
6731 can be called. Otherwise, a garbage frame maybe transmitted out every
6732 Beacon period.
6734 IRQL = DISPATCH_LEVEL
6736 ==========================================================================
6738 VOID AsicEnableIbssSync(
6739 IN PRTMP_ADAPTER pAd)
6741 BCN_TIME_CFG_STRUC csr9;
6742 PUCHAR ptr;
6743 UINT i;
6745 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6747 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6748 csr9.field.bBeaconGen = 0;
6749 csr9.field.bTBTTEnable = 0;
6750 csr9.field.bTsfTicking = 0;
6751 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6754 #ifdef RT2870
6755 // move BEACON TXD and frame content to on-chip memory
6756 ptr = (PUCHAR)&pAd->BeaconTxWI;
6757 for (i=0; i<TXWI_SIZE; i+=2) // 16-byte TXWI field
6759 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6760 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6761 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + i, ptr, 2);
6762 ptr += 2;
6765 // start right after the 16-byte TXWI field
6766 ptr = pAd->BeaconBuf;
6767 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=2)
6769 //UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6770 //RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6771 RTUSBMultiWrite(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, ptr, 2);
6772 ptr +=2;
6774 #endif // RT2870 //
6777 // For Wi-Fi faily generated beacons between participating stations.
6778 // Set TBTT phase adaptive adjustment step to 8us (default 16us)
6779 // don't change settings 2006-5- by Jerry
6780 //RTMP_IO_WRITE32(pAd, TBTT_SYNC_CFG, 0x00001010);
6782 // start sending BEACON
6783 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6784 csr9.field.bTsfTicking = 1;
6785 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6786 csr9.field.bTBTTEnable = 1;
6787 csr9.field.bBeaconGen = 1;
6788 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6792 ==========================================================================
6793 Description:
6795 IRQL = PASSIVE_LEVEL
6796 IRQL = DISPATCH_LEVEL
6798 ==========================================================================
6800 VOID AsicSetEdcaParm(
6801 IN PRTMP_ADAPTER pAd,
6802 IN PEDCA_PARM pEdcaParm)
6804 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6805 AC_TXOP_CSR0_STRUC csr0;
6806 AC_TXOP_CSR1_STRUC csr1;
6807 AIFSN_CSR_STRUC AifsnCsr;
6808 CWMIN_CSR_STRUC CwminCsr;
6809 CWMAX_CSR_STRUC CwmaxCsr;
6810 int i;
6812 Ac0Cfg.word = 0;
6813 Ac1Cfg.word = 0;
6814 Ac2Cfg.word = 0;
6815 Ac3Cfg.word = 0;
6816 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6818 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6819 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6820 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6822 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6823 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6826 //========================================================
6827 // MAC Register has a copy .
6828 //========================================================
6829 //#ifndef WIFI_TEST
6830 if( pAd->CommonCfg.bEnableTxBurst )
6832 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6833 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6835 else
6836 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6837 //#else
6838 // Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6839 //#endif
6840 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6841 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6842 Ac0Cfg.field.Aifsn = 2;
6843 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6845 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6846 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6847 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6848 Ac1Cfg.field.Aifsn = 2;
6849 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6851 if (pAd->CommonCfg.PhyMode == PHY_11B)
6853 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6854 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6856 else
6858 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6859 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6861 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6862 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6863 Ac2Cfg.field.Aifsn = 2;
6864 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6865 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6866 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6867 Ac3Cfg.field.Aifsn = 2;
6868 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6870 //========================================================
6871 // DMA Register has a copy too.
6872 //========================================================
6873 csr0.field.Ac0Txop = 0; // QID_AC_BE
6874 csr0.field.Ac1Txop = 0; // QID_AC_BK
6875 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6876 if (pAd->CommonCfg.PhyMode == PHY_11B)
6878 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6879 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6881 else
6883 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6884 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6886 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6888 CwminCsr.word = 0;
6889 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6890 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6891 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6892 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6893 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6895 CwmaxCsr.word = 0;
6896 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6897 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6898 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6899 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6900 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6902 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6904 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6906 else
6908 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6909 //========================================================
6910 // MAC Register has a copy.
6911 //========================================================
6913 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6914 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6916 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6918 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6919 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6920 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6921 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6923 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6924 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6925 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6926 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6928 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6929 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6930 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6931 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6932 #ifdef CONFIG_STA_SUPPORT
6933 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6935 // Tuning for Wi-Fi WMM S06
6936 if (pAd->CommonCfg.bWiFiTest &&
6937 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6938 Ac2Cfg.field.Aifsn -= 1;
6940 // Tuning for TGn Wi-Fi 5.2.32
6941 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6942 if (STA_TGN_WIFI_ON(pAd) &&
6943 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6945 Ac0Cfg.field.Aifsn = 3;
6946 Ac2Cfg.field.AcTxop = 5;
6949 #endif // CONFIG_STA_SUPPORT //
6951 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6952 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6953 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6954 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6956 //#ifdef WIFI_TEST
6957 if (pAd->CommonCfg.bWiFiTest)
6959 if (Ac3Cfg.field.AcTxop == 102)
6961 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6962 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6963 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6964 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6965 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6966 } /* End of if */
6968 //#endif // WIFI_TEST //
6970 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6971 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6972 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6973 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6976 //========================================================
6977 // DMA Register has a copy too.
6978 //========================================================
6979 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6980 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6981 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6983 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6984 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6985 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6987 CwminCsr.word = 0;
6988 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6989 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6990 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6991 #ifdef CONFIG_STA_SUPPORT
6992 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6993 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6994 #endif // CONFIG_STA_SUPPORT //
6995 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6997 CwmaxCsr.word = 0;
6998 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6999 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
7000 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
7001 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
7002 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
7004 AifsnCsr.word = 0;
7005 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
7006 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
7007 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
7008 #ifdef CONFIG_STA_SUPPORT
7009 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7011 // Tuning for Wi-Fi WMM S06
7012 if (pAd->CommonCfg.bWiFiTest &&
7013 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7014 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
7016 // Tuning for TGn Wi-Fi 5.2.32
7017 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
7018 if (STA_TGN_WIFI_ON(pAd) &&
7019 pEdcaParm->Aifsn[QID_AC_VI] == 10)
7021 AifsnCsr.field.Aifsn0 = 3;
7022 AifsnCsr.field.Aifsn2 = 7;
7025 if (INFRA_ON(pAd))
7026 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[BSSID_WCID], fCLIENT_STATUS_WMM_CAPABLE);
7028 #endif // CONFIG_STA_SUPPORT //
7030 #ifdef CONFIG_STA_SUPPORT
7031 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7032 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
7033 #endif // CONFIG_STA_SUPPORT //
7034 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
7036 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
7037 if (!ADHOC_ON(pAd))
7039 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
7040 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
7041 pEdcaParm->Aifsn[0],
7042 pEdcaParm->Cwmin[0],
7043 pEdcaParm->Cwmax[0],
7044 pEdcaParm->Txop[0]<<5,
7045 pEdcaParm->bACM[0]));
7046 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
7047 pEdcaParm->Aifsn[1],
7048 pEdcaParm->Cwmin[1],
7049 pEdcaParm->Cwmax[1],
7050 pEdcaParm->Txop[1]<<5,
7051 pEdcaParm->bACM[1]));
7052 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
7053 pEdcaParm->Aifsn[2],
7054 pEdcaParm->Cwmin[2],
7055 pEdcaParm->Cwmax[2],
7056 pEdcaParm->Txop[2]<<5,
7057 pEdcaParm->bACM[2]));
7058 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
7059 pEdcaParm->Aifsn[3],
7060 pEdcaParm->Cwmin[3],
7061 pEdcaParm->Cwmax[3],
7062 pEdcaParm->Txop[3]<<5,
7063 pEdcaParm->bACM[3]));
7069 ==========================================================================
7070 Description:
7072 IRQL = PASSIVE_LEVEL
7073 IRQL = DISPATCH_LEVEL
7075 ==========================================================================
7077 VOID AsicSetSlotTime(
7078 IN PRTMP_ADAPTER pAd,
7079 IN BOOLEAN bUseShortSlotTime)
7081 ULONG SlotTime;
7082 UINT32 RegValue = 0;
7084 #ifdef CONFIG_STA_SUPPORT
7085 if (pAd->CommonCfg.Channel > 14)
7086 bUseShortSlotTime = TRUE;
7087 #endif // CONFIG_STA_SUPPORT //
7089 if (bUseShortSlotTime)
7090 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7091 else
7092 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
7094 SlotTime = (bUseShortSlotTime)? 9 : 20;
7096 #ifdef CONFIG_STA_SUPPORT
7097 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7099 // force using short SLOT time for FAE to demo performance when TxBurst is ON
7100 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
7101 #ifdef DOT11_N_SUPPORT
7102 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
7103 #endif // DOT11_N_SUPPORT //
7106 // In this case, we will think it is doing Wi-Fi test
7107 // And we will not set to short slot when bEnableTxBurst is TRUE.
7109 else if (pAd->CommonCfg.bEnableTxBurst)
7110 SlotTime = 9;
7112 #endif // CONFIG_STA_SUPPORT //
7115 // For some reasons, always set it to short slot time.
7117 // ToDo: Should consider capability with 11B
7119 #ifdef CONFIG_STA_SUPPORT
7120 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7122 if (pAd->StaCfg.BssType == BSS_ADHOC)
7123 SlotTime = 20;
7125 #endif // CONFIG_STA_SUPPORT //
7127 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
7128 RegValue = RegValue & 0xFFFFFF00;
7130 RegValue |= SlotTime;
7132 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
7136 ========================================================================
7137 Description:
7138 Add Shared key information into ASIC.
7139 Update shared key, TxMic and RxMic to Asic Shared key table
7140 Update its cipherAlg to Asic Shared key Mode.
7142 Return:
7143 ========================================================================
7145 VOID AsicAddSharedKeyEntry(
7146 IN PRTMP_ADAPTER pAd,
7147 IN UCHAR BssIndex,
7148 IN UCHAR KeyIdx,
7149 IN UCHAR CipherAlg,
7150 IN PUCHAR pKey,
7151 IN PUCHAR pTxMic,
7152 IN PUCHAR pRxMic)
7154 ULONG offset; //, csr0;
7155 SHAREDKEY_MODE_STRUC csr1;
7157 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
7158 //============================================================================================
7160 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
7161 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7162 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]));
7163 if (pRxMic)
7165 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7166 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7168 if (pTxMic)
7170 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7171 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7173 //============================================================================================
7175 // fill key material - key + TX MIC + RX MIC
7178 #ifdef RT2870
7180 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
7181 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_SHARE_KEY);
7183 offset += MAX_LEN_OF_SHARE_KEY;
7184 if (pTxMic)
7186 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7189 offset += 8;
7190 if (pRxMic)
7192 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7195 #endif // RT2870 //
7198 // Update cipher algorithm. WSTA always use BSS0
7200 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7201 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
7202 if ((BssIndex%2) == 0)
7204 if (KeyIdx == 0)
7205 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7206 else if (KeyIdx == 1)
7207 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7208 else if (KeyIdx == 2)
7209 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7210 else
7211 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7213 else
7215 if (KeyIdx == 0)
7216 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7217 else if (KeyIdx == 1)
7218 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7219 else if (KeyIdx == 2)
7220 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7221 else
7222 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7224 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7225 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7229 // IRQL = DISPATCH_LEVEL
7230 VOID AsicRemoveSharedKeyEntry(
7231 IN PRTMP_ADAPTER pAd,
7232 IN UCHAR BssIndex,
7233 IN UCHAR KeyIdx)
7235 //ULONG SecCsr0;
7236 SHAREDKEY_MODE_STRUC csr1;
7238 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
7240 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
7241 if ((BssIndex%2) == 0)
7243 if (KeyIdx == 0)
7244 csr1.field.Bss0Key0CipherAlg = 0;
7245 else if (KeyIdx == 1)
7246 csr1.field.Bss0Key1CipherAlg = 0;
7247 else if (KeyIdx == 2)
7248 csr1.field.Bss0Key2CipherAlg = 0;
7249 else
7250 csr1.field.Bss0Key3CipherAlg = 0;
7252 else
7254 if (KeyIdx == 0)
7255 csr1.field.Bss1Key0CipherAlg = 0;
7256 else if (KeyIdx == 1)
7257 csr1.field.Bss1Key1CipherAlg = 0;
7258 else if (KeyIdx == 2)
7259 csr1.field.Bss1Key2CipherAlg = 0;
7260 else
7261 csr1.field.Bss1Key3CipherAlg = 0;
7263 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
7264 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
7265 ASSERT(BssIndex < 4);
7266 ASSERT(KeyIdx < 4);
7271 VOID AsicUpdateWCIDAttribute(
7272 IN PRTMP_ADAPTER pAd,
7273 IN USHORT WCID,
7274 IN UCHAR BssIndex,
7275 IN UCHAR CipherAlg,
7276 IN BOOLEAN bUsePairewiseKeyTable)
7278 ULONG WCIDAttri = 0, offset;
7281 // Update WCID attribute.
7282 // Only TxKey could update WCID attribute.
7284 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
7285 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
7286 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7289 VOID AsicUpdateWCIDIVEIV(
7290 IN PRTMP_ADAPTER pAd,
7291 IN USHORT WCID,
7292 IN ULONG uIV,
7293 IN ULONG uEIV)
7295 ULONG offset;
7297 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
7299 RTMP_IO_WRITE32(pAd, offset, uIV);
7300 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
7303 VOID AsicUpdateRxWCIDTable(
7304 IN PRTMP_ADAPTER pAd,
7305 IN USHORT WCID,
7306 IN PUCHAR pAddr)
7308 ULONG offset;
7309 ULONG Addr;
7311 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
7312 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
7313 RTMP_IO_WRITE32(pAd, offset, Addr);
7314 Addr = pAddr[4] + (pAddr[5] << 8);
7315 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
7320 ========================================================================
7322 Routine Description:
7323 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
7325 Arguments:
7326 pAd Pointer to our adapter
7327 WCID WCID Entry number.
7328 BssIndex BSSID index, station or none multiple BSSID support
7329 this value should be 0.
7330 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
7331 pCipherKey Pointer to Cipher Key.
7332 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
7333 otherwise PairewiseKey table
7334 bTxKey This is the transmit key if enabled.
7336 Return Value:
7337 None
7339 Note:
7340 This routine will set the relative key stuff to Asic including WCID attribute,
7341 Cipher Key, Cipher algorithm and IV/EIV.
7343 IV/EIV will be update if this CipherKey is the transmission key because
7344 ASIC will base on IV's KeyID value to select Cipher Key.
7346 If bTxKey sets to FALSE, this is not the TX key, but it could be
7347 RX key
7349 For AP mode bTxKey must be always set to TRUE.
7350 ========================================================================
7352 VOID AsicAddKeyEntry(
7353 IN PRTMP_ADAPTER pAd,
7354 IN USHORT WCID,
7355 IN UCHAR BssIndex,
7356 IN UCHAR KeyIdx,
7357 IN PCIPHER_KEY pCipherKey,
7358 IN BOOLEAN bUsePairewiseKeyTable,
7359 IN BOOLEAN bTxKey)
7361 ULONG offset;
7362 // ULONG WCIDAttri = 0;
7363 UCHAR IV4 = 0;
7364 PUCHAR pKey = pCipherKey->Key;
7365 // ULONG KeyLen = pCipherKey->KeyLen;
7366 PUCHAR pTxMic = pCipherKey->TxMic;
7367 PUCHAR pRxMic = pCipherKey->RxMic;
7368 PUCHAR pTxtsc = pCipherKey->TxTsc;
7369 UCHAR CipherAlg = pCipherKey->CipherAlg;
7370 SHAREDKEY_MODE_STRUC csr1;
7372 // ASSERT(KeyLen <= MAX_LEN_OF_PEER_KEY);
7374 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
7376 // 1.) decide key table offset
7378 if (bUsePairewiseKeyTable)
7379 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7380 else
7381 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
7384 // 2.) Set Key to Asic
7386 //for (i = 0; i < KeyLen; i++)
7388 #ifdef RT2870
7389 RTUSBMultiWrite(pAd, offset, pKey, MAX_LEN_OF_PEER_KEY);
7390 offset += MAX_LEN_OF_PEER_KEY;
7393 // 3.) Set MIC key if available
7395 if (pTxMic)
7397 RTUSBMultiWrite(pAd, offset, pTxMic, 8);
7399 offset += LEN_TKIP_TXMICK;
7401 if (pRxMic)
7403 RTUSBMultiWrite(pAd, offset, pRxMic, 8);
7405 #endif // RT2870 //
7408 // 4.) Modify IV/EIV if needs
7409 // This will force Asic to use this key ID by setting IV.
7411 if (bTxKey)
7414 #ifdef RT2870
7415 UINT32 tmpVal;
7418 // Write IV
7420 IV4 = (KeyIdx << 6);
7421 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
7422 IV4 |= 0x20; // turn on extension bit means EIV existence
7424 tmpVal = pTxtsc[1] + (((pTxtsc[1] | 0x20) & 0x7f) << 8) + (pTxtsc[0] << 16) + (IV4 << 24);
7425 RTMP_IO_WRITE32(pAd, offset, tmpVal);
7428 // Write EIV
7430 offset += 4;
7431 RTMP_IO_WRITE32(pAd, offset, *(PUINT32)&pCipherKey->TxTsc[2]);
7432 #endif // RT2870 //
7433 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7436 if (!bUsePairewiseKeyTable)
7439 // Only update the shared key security mode
7441 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7442 if ((BssIndex % 2) == 0)
7444 if (KeyIdx == 0)
7445 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7446 else if (KeyIdx == 1)
7447 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7448 else if (KeyIdx == 2)
7449 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7450 else
7451 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7453 else
7455 if (KeyIdx == 0)
7456 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7457 else if (KeyIdx == 1)
7458 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7459 else if (KeyIdx == 2)
7460 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7461 else
7462 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7464 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7467 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7472 ========================================================================
7473 Description:
7474 Add Pair-wise key material into ASIC.
7475 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7477 Return:
7478 ========================================================================
7480 VOID AsicAddPairwiseKeyEntry(
7481 IN PRTMP_ADAPTER pAd,
7482 IN PUCHAR pAddr,
7483 IN UCHAR WCID,
7484 IN CIPHER_KEY *pCipherKey)
7486 INT i;
7487 ULONG offset;
7488 PUCHAR pKey = pCipherKey->Key;
7489 PUCHAR pTxMic = pCipherKey->TxMic;
7490 PUCHAR pRxMic = pCipherKey->RxMic;
7491 #ifdef DBG
7492 UCHAR CipherAlg = pCipherKey->CipherAlg;
7493 #endif // DBG //
7495 // EKEY
7496 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7497 #ifdef RT2870
7498 RTUSBMultiWrite(pAd, offset, &pCipherKey->Key[0], MAX_LEN_OF_PEER_KEY);
7499 #endif // RT2870 //
7500 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7502 UINT32 Value;
7503 RTMP_IO_READ32(pAd, offset + i, &Value);
7506 offset += MAX_LEN_OF_PEER_KEY;
7508 // MIC KEY
7509 if (pTxMic)
7511 #ifdef RT2870
7512 RTUSBMultiWrite(pAd, offset, &pCipherKey->TxMic[0], 8);
7513 #endif // RT2870 //
7515 offset += 8;
7516 if (pRxMic)
7518 #ifdef RT2870
7519 RTUSBMultiWrite(pAd, offset, &pCipherKey->RxMic[0], 8);
7520 #endif // RT2870 //
7523 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7524 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7525 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]));
7526 if (pRxMic)
7528 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7529 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7531 if (pTxMic)
7533 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7534 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7538 ========================================================================
7539 Description:
7540 Remove Pair-wise key material from ASIC.
7542 Return:
7543 ========================================================================
7545 VOID AsicRemovePairwiseKeyEntry(
7546 IN PRTMP_ADAPTER pAd,
7547 IN UCHAR BssIdx,
7548 IN UCHAR Wcid)
7550 ULONG WCIDAttri;
7551 USHORT offset;
7553 // re-set the entry's WCID attribute as OPEN-NONE.
7554 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7555 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7556 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7559 BOOLEAN AsicSendCommandToMcu(
7560 IN PRTMP_ADAPTER pAd,
7561 IN UCHAR Command,
7562 IN UCHAR Token,
7563 IN UCHAR Arg0,
7564 IN UCHAR Arg1)
7566 HOST_CMD_CSR_STRUC H2MCmd;
7567 H2M_MAILBOX_STRUC H2MMailbox;
7568 ULONG i = 0;
7571 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7572 if (H2MMailbox.field.Owner == 0)
7573 break;
7575 RTMPusecDelay(2);
7576 } while(i++ < 100);
7578 if (i >= 100)
7581 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7583 return FALSE;
7587 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7588 H2MMailbox.field.CmdToken = Token;
7589 H2MMailbox.field.HighByte = Arg1;
7590 H2MMailbox.field.LowByte = Arg0;
7591 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7593 H2MCmd.word = 0;
7594 H2MCmd.field.HostCommand = Command;
7595 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7597 if (Command != 0x80)
7601 return TRUE;
7606 ========================================================================
7608 Routine Description:
7609 Verify the support rate for different PHY type
7611 Arguments:
7612 pAd Pointer to our adapter
7614 Return Value:
7615 None
7617 IRQL = PASSIVE_LEVEL
7619 ========================================================================
7621 VOID RTMPCheckRates(
7622 IN PRTMP_ADAPTER pAd,
7623 IN OUT UCHAR SupRate[],
7624 IN OUT UCHAR *SupRateLen)
7626 UCHAR RateIdx, i, j;
7627 UCHAR NewRate[12], NewRateLen;
7629 NewRateLen = 0;
7631 if (pAd->CommonCfg.PhyMode == PHY_11B)
7632 RateIdx = 4;
7633 else
7634 RateIdx = 12;
7636 // Check for support rates exclude basic rate bit
7637 for (i = 0; i < *SupRateLen; i++)
7638 for (j = 0; j < RateIdx; j++)
7639 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7640 NewRate[NewRateLen++] = SupRate[i];
7642 *SupRateLen = NewRateLen;
7643 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7646 #ifdef CONFIG_STA_SUPPORT
7647 #ifdef DOT11_N_SUPPORT
7648 BOOLEAN RTMPCheckChannel(
7649 IN PRTMP_ADAPTER pAd,
7650 IN UCHAR CentralChannel,
7651 IN UCHAR Channel)
7653 UCHAR k;
7654 UCHAR UpperChannel = 0, LowerChannel = 0;
7655 UCHAR NoEffectChannelinList = 0;
7657 // Find upper and lower channel according to 40MHz current operation.
7658 if (CentralChannel < Channel)
7660 UpperChannel = Channel;
7661 if (CentralChannel > 2)
7662 LowerChannel = CentralChannel - 2;
7663 else
7664 return FALSE;
7666 else if (CentralChannel > Channel)
7668 UpperChannel = CentralChannel + 2;
7669 LowerChannel = Channel;
7672 for (k = 0;k < pAd->ChannelListNum;k++)
7674 if (pAd->ChannelList[k].Channel == UpperChannel)
7676 NoEffectChannelinList ++;
7678 if (pAd->ChannelList[k].Channel == LowerChannel)
7680 NoEffectChannelinList ++;
7684 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7685 if (NoEffectChannelinList == 2)
7686 return TRUE;
7687 else
7688 return FALSE;
7692 ========================================================================
7694 Routine Description:
7695 Verify the support rate for HT phy type
7697 Arguments:
7698 pAd Pointer to our adapter
7700 Return Value:
7701 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7703 IRQL = PASSIVE_LEVEL
7705 ========================================================================
7707 BOOLEAN RTMPCheckHt(
7708 IN PRTMP_ADAPTER pAd,
7709 IN UCHAR Wcid,
7710 IN HT_CAPABILITY_IE *pHtCapability,
7711 IN ADD_HT_INFO_IE *pAddHtInfo)
7713 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7714 return FALSE;
7716 // If use AMSDU, set flag.
7717 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7718 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7719 // Save Peer Capability
7720 if (pHtCapability->HtCapInfo.ShortGIfor20)
7721 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7722 if (pHtCapability->HtCapInfo.ShortGIfor40)
7723 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7724 if (pHtCapability->HtCapInfo.TxSTBC)
7725 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7726 if (pHtCapability->HtCapInfo.RxSTBC)
7727 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7728 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7730 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7733 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7735 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7738 // Will check ChannelWidth for MCSSet[4] below
7739 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7740 switch (pAd->CommonCfg.RxStream)
7742 case 1:
7743 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7744 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7745 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7746 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7747 break;
7748 case 2:
7749 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7750 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7751 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7752 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7753 break;
7754 case 3:
7755 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7756 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7757 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7758 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7759 break;
7762 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7764 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7765 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7766 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7768 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7770 // Send Assoc Req with my HT capability.
7771 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7772 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7773 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7774 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7775 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7776 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7777 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7778 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7779 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7780 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7781 if (pAd->CommonCfg.bRdg)
7783 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7784 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7787 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7788 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7790 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7791 return TRUE;
7793 #endif // DOT11_N_SUPPORT //
7794 #endif // CONFIG_STA_SUPPORT //
7797 ========================================================================
7799 Routine Description:
7800 Verify the support rate for different PHY type
7802 Arguments:
7803 pAd Pointer to our adapter
7805 Return Value:
7806 None
7808 IRQL = PASSIVE_LEVEL
7810 ========================================================================
7812 VOID RTMPUpdateMlmeRate(
7813 IN PRTMP_ADAPTER pAd)
7815 UCHAR MinimumRate;
7816 UCHAR ProperMlmeRate; //= RATE_54;
7817 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7818 BOOLEAN bMatch = FALSE;
7820 switch (pAd->CommonCfg.PhyMode)
7822 case PHY_11B:
7823 ProperMlmeRate = RATE_11;
7824 MinimumRate = RATE_1;
7825 break;
7826 case PHY_11BG_MIXED:
7827 #ifdef DOT11_N_SUPPORT
7828 case PHY_11ABGN_MIXED:
7829 case PHY_11BGN_MIXED:
7830 #endif // DOT11_N_SUPPORT //
7831 if ((pAd->MlmeAux.SupRateLen == 4) &&
7832 (pAd->MlmeAux.ExtRateLen == 0))
7833 // B only AP
7834 ProperMlmeRate = RATE_11;
7835 else
7836 ProperMlmeRate = RATE_24;
7838 if (pAd->MlmeAux.Channel <= 14)
7839 MinimumRate = RATE_1;
7840 else
7841 MinimumRate = RATE_6;
7842 break;
7843 case PHY_11A:
7844 #ifdef DOT11_N_SUPPORT
7845 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7846 case PHY_11GN_MIXED:
7847 case PHY_11AGN_MIXED:
7848 case PHY_11AN_MIXED:
7849 case PHY_11N_5G:
7850 #endif // DOT11_N_SUPPORT //
7851 ProperMlmeRate = RATE_24;
7852 MinimumRate = RATE_6;
7853 break;
7854 case PHY_11ABG_MIXED:
7855 ProperMlmeRate = RATE_24;
7856 if (pAd->MlmeAux.Channel <= 14)
7857 MinimumRate = RATE_1;
7858 else
7859 MinimumRate = RATE_6;
7860 break;
7861 default: // error
7862 ProperMlmeRate = RATE_1;
7863 MinimumRate = RATE_1;
7864 break;
7867 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7869 for (j = 0; j < RateIdx; j++)
7871 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7873 if (j == ProperMlmeRate)
7875 bMatch = TRUE;
7876 break;
7881 if (bMatch)
7882 break;
7885 if (bMatch == FALSE)
7887 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7889 for (j = 0; j < RateIdx; j++)
7891 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7893 if (j == ProperMlmeRate)
7895 bMatch = TRUE;
7896 break;
7901 if (bMatch)
7902 break;
7906 if (bMatch == FALSE)
7908 ProperMlmeRate = MinimumRate;
7911 pAd->CommonCfg.MlmeRate = MinimumRate;
7912 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7913 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7915 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7916 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7917 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7918 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7920 else
7922 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7923 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7924 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7925 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7928 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7931 CHAR RTMPMaxRssi(
7932 IN PRTMP_ADAPTER pAd,
7933 IN CHAR Rssi0,
7934 IN CHAR Rssi1,
7935 IN CHAR Rssi2)
7937 CHAR larger = -127;
7939 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7941 larger = Rssi0;
7944 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7946 larger = max(Rssi0, Rssi1);
7949 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7951 larger = max(larger, Rssi2);
7954 if (larger == -127)
7955 larger = 0;
7957 return larger;
7961 ========================================================================
7962 Routine Description:
7963 Periodic evaluate antenna link status
7965 Arguments:
7966 pAd - Adapter pointer
7968 Return Value:
7969 None
7971 ========================================================================
7973 VOID AsicEvaluateRxAnt(
7974 IN PRTMP_ADAPTER pAd)
7976 UCHAR BBPR3 = 0;
7978 #ifdef RALINK_ATE
7979 if (ATE_ON(pAd))
7980 return;
7981 #endif // RALINK_ATE //
7984 #ifdef CONFIG_STA_SUPPORT
7985 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7987 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7988 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7989 fRTMP_ADAPTER_RADIO_OFF |
7990 fRTMP_ADAPTER_NIC_NOT_EXIST |
7991 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7992 return;
7994 if (pAd->StaCfg.Psm == PWR_SAVE)
7995 return;
7997 #endif // CONFIG_STA_SUPPORT //
7999 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8000 BBPR3 &= (~0x18);
8001 if(pAd->Antenna.field.RxPath == 3)
8003 BBPR3 |= (0x10);
8005 else if(pAd->Antenna.field.RxPath == 2)
8007 BBPR3 |= (0x8);
8009 else if(pAd->Antenna.field.RxPath == 1)
8011 BBPR3 |= (0x0);
8013 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8014 #ifdef CONFIG_STA_SUPPORT
8015 #endif // CONFIG_STA_SUPPORT //
8016 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8019 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
8020 pAd->RalinkCounters.OneSecTxRetryOkCount +
8021 pAd->RalinkCounters.OneSecTxFailCount;
8023 if (TxTotalCnt > 50)
8025 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
8026 pAd->Mlme.bLowThroughput = FALSE;
8028 else
8030 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
8031 pAd->Mlme.bLowThroughput = TRUE;
8037 ========================================================================
8038 Routine Description:
8039 After evaluation, check antenna link status
8041 Arguments:
8042 pAd - Adapter pointer
8044 Return Value:
8045 None
8047 ========================================================================
8049 VOID AsicRxAntEvalTimeout(
8050 IN PVOID SystemSpecific1,
8051 IN PVOID FunctionContext,
8052 IN PVOID SystemSpecific2,
8053 IN PVOID SystemSpecific3)
8055 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8056 #ifdef CONFIG_STA_SUPPORT
8057 UCHAR BBPR3 = 0;
8058 CHAR larger = -127, rssi0, rssi1, rssi2;
8059 #endif // CONFIG_STA_SUPPORT //
8061 #ifdef RALINK_ATE
8062 if (ATE_ON(pAd))
8063 return;
8064 #endif // RALINK_ATE //
8067 #ifdef CONFIG_STA_SUPPORT
8068 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8070 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
8071 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
8072 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
8073 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
8074 return;
8076 if (pAd->StaCfg.Psm == PWR_SAVE)
8077 return;
8080 // if the traffic is low, use average rssi as the criteria
8081 if (pAd->Mlme.bLowThroughput == TRUE)
8083 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
8084 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
8085 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
8087 else
8089 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
8090 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
8091 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
8094 if(pAd->Antenna.field.RxPath == 3)
8096 larger = max(rssi0, rssi1);
8098 if (larger > (rssi2 + 20))
8099 pAd->Mlme.RealRxPath = 2;
8100 else
8101 pAd->Mlme.RealRxPath = 3;
8103 else if(pAd->Antenna.field.RxPath == 2)
8105 if (rssi0 > (rssi1 + 20))
8106 pAd->Mlme.RealRxPath = 1;
8107 else
8108 pAd->Mlme.RealRxPath = 2;
8111 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
8112 BBPR3 &= (~0x18);
8113 if(pAd->Mlme.RealRxPath == 3)
8115 BBPR3 |= (0x10);
8117 else if(pAd->Mlme.RealRxPath == 2)
8119 BBPR3 |= (0x8);
8121 else if(pAd->Mlme.RealRxPath == 1)
8123 BBPR3 |= (0x0);
8125 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
8128 #endif // CONFIG_STA_SUPPORT //
8134 VOID APSDPeriodicExec(
8135 IN PVOID SystemSpecific1,
8136 IN PVOID FunctionContext,
8137 IN PVOID SystemSpecific2,
8138 IN PVOID SystemSpecific3)
8140 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
8142 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
8143 return;
8145 pAd->CommonCfg.TriggerTimerCount++;
8147 // Driver should not send trigger frame, it should be send by application layer
8149 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable
8150 && (pAd->CommonCfg.bNeedSendTriggerFrame ||
8151 (((pAd->CommonCfg.TriggerTimerCount%20) == 19) && (!pAd->CommonCfg.bAPSDAC_BE || !pAd->CommonCfg.bAPSDAC_BK || !pAd->CommonCfg.bAPSDAC_VI || !pAd->CommonCfg.bAPSDAC_VO))))
8153 DBGPRINT(RT_DEBUG_TRACE,("Sending trigger frame and enter service period when support APSD\n"));
8154 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
8155 pAd->CommonCfg.bNeedSendTriggerFrame = FALSE;
8156 pAd->CommonCfg.TriggerTimerCount = 0;
8157 pAd->CommonCfg.bInServicePeriod = TRUE;
8162 ========================================================================
8163 Routine Description:
8164 Set/reset MAC registers according to bPiggyBack parameter
8166 Arguments:
8167 pAd - Adapter pointer
8168 bPiggyBack - Enable / Disable Piggy-Back
8170 Return Value:
8171 None
8173 ========================================================================
8175 VOID RTMPSetPiggyBack(
8176 IN PRTMP_ADAPTER pAd,
8177 IN BOOLEAN bPiggyBack)
8179 TX_LINK_CFG_STRUC TxLinkCfg;
8181 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
8183 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
8184 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
8188 ========================================================================
8189 Routine Description:
8190 check if this entry need to switch rate automatically
8192 Arguments:
8194 pEntry
8196 Return Value:
8197 TURE
8198 FALSE
8200 ========================================================================
8202 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
8203 IN PRTMP_ADAPTER pAd,
8204 IN PMAC_TABLE_ENTRY pEntry)
8206 BOOLEAN result = TRUE;
8209 #ifdef CONFIG_STA_SUPPORT
8210 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8212 // only associated STA counts
8213 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
8215 result = pAd->StaCfg.bAutoTxRateSwitch;
8217 else
8218 result = FALSE;
8220 #ifdef QOS_DLS_SUPPORT
8221 if (pEntry && (pEntry->ValidAsDls))
8222 result = pAd->StaCfg.bAutoTxRateSwitch;
8223 #endif // QOS_DLS_SUPPORT //
8225 #endif // CONFIG_STA_SUPPORT //
8229 return result;
8233 BOOLEAN RTMPAutoRateSwitchCheck(
8234 IN PRTMP_ADAPTER pAd)
8237 #ifdef CONFIG_STA_SUPPORT
8238 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8240 if (pAd->StaCfg.bAutoTxRateSwitch)
8241 return TRUE;
8243 #endif // CONFIG_STA_SUPPORT //
8244 return FALSE;
8249 ========================================================================
8250 Routine Description:
8251 check if this entry need to fix tx legacy rate
8253 Arguments:
8255 pEntry
8257 Return Value:
8258 TURE
8259 FALSE
8261 ========================================================================
8263 UCHAR RTMPStaFixedTxMode(
8264 IN PRTMP_ADAPTER pAd,
8265 IN PMAC_TABLE_ENTRY pEntry)
8267 UCHAR tx_mode = FIXED_TXMODE_HT;
8270 #ifdef CONFIG_STA_SUPPORT
8271 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
8273 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
8275 #endif // CONFIG_STA_SUPPORT //
8277 return tx_mode;
8281 ========================================================================
8282 Routine Description:
8283 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
8285 Arguments:
8287 pEntry
8289 Return Value:
8290 TURE
8291 FALSE
8293 ========================================================================
8295 VOID RTMPUpdateLegacyTxSetting(
8296 UCHAR fixed_tx_mode,
8297 PMAC_TABLE_ENTRY pEntry)
8299 HTTRANSMIT_SETTING TransmitSetting;
8301 if (fixed_tx_mode == FIXED_TXMODE_HT)
8302 return;
8304 TransmitSetting.word = 0;
8306 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
8307 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
8309 if (fixed_tx_mode == FIXED_TXMODE_CCK)
8311 TransmitSetting.field.MODE = MODE_CCK;
8312 // CCK mode allow MCS 0~3
8313 if (TransmitSetting.field.MCS > MCS_3)
8314 TransmitSetting.field.MCS = MCS_3;
8316 else
8318 TransmitSetting.field.MODE = MODE_OFDM;
8319 // OFDM mode allow MCS 0~7
8320 if (TransmitSetting.field.MCS > MCS_7)
8321 TransmitSetting.field.MCS = MCS_7;
8324 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
8326 pEntry->HTPhyMode.word = TransmitSetting.word;
8327 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
8328 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
8332 #ifdef CONFIG_STA_SUPPORT
8334 ==========================================================================
8335 Description:
8336 dynamic tune BBP R66 to find a balance between sensibility and
8337 noise isolation
8339 IRQL = DISPATCH_LEVEL
8341 ==========================================================================
8343 VOID AsicStaBbpTuning(
8344 IN PRTMP_ADAPTER pAd)
8346 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
8347 CHAR Rssi;
8349 // 2860C did not support Fase CCA, therefore can't tune
8350 if (pAd->MACVersion == 0x28600100)
8351 return;
8354 // work as a STA
8356 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
8357 return;
8359 if ((pAd->OpMode == OPMODE_STA)
8360 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
8362 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
8365 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
8366 R66 = OrigR66Value;
8368 if (pAd->Antenna.field.RxPath > 1)
8369 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
8370 else
8371 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
8373 if (pAd->LatchRfRegs.Channel <= 14)
8374 { //BG band
8375 #ifdef RT2870
8376 // RT3070 is a no LNA solution, it should have different control regarding to AGC gain control
8377 // Otherwise, it will have some throughput side effect when low RSSI
8378 if (IS_RT3070(pAd))
8380 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8382 R66 = 0x1C + 2*GET_LNA_GAIN(pAd) + 0x20;
8383 if (OrigR66Value != R66)
8385 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8388 else
8390 R66 = 0x1C + 2*GET_LNA_GAIN(pAd);
8391 if (OrigR66Value != R66)
8393 RTUSBWriteBBPRegister(pAd, BBP_R66, R66);
8397 else
8398 #endif // RT2870 //
8400 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8402 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
8403 if (OrigR66Value != R66)
8405 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8408 else
8410 R66 = 0x2E + GET_LNA_GAIN(pAd);
8411 if (OrigR66Value != R66)
8413 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8418 else
8419 { //A band
8420 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8422 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8424 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8425 if (OrigR66Value != R66)
8427 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8430 else
8432 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8433 if (OrigR66Value != R66)
8435 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8439 else
8441 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8443 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8444 if (OrigR66Value != R66)
8446 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8449 else
8451 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8452 if (OrigR66Value != R66)
8454 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8463 #endif // CONFIG_STA_SUPPORT //
8465 VOID RTMPSetAGCInitValue(
8466 IN PRTMP_ADAPTER pAd,
8467 IN UCHAR BandWidth)
8469 UCHAR R66 = 0x30;
8471 if (pAd->LatchRfRegs.Channel <= 14)
8472 { // BG band
8473 R66 = 0x2E + GET_LNA_GAIN(pAd);
8474 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8476 else
8477 { //A band
8478 if (BandWidth == BW_20)
8480 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8481 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8483 #ifdef DOT11_N_SUPPORT
8484 else
8486 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8487 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8489 #endif // DOT11_N_SUPPORT //
8494 VOID AsicTurnOffRFClk(
8495 IN PRTMP_ADAPTER pAd,
8496 IN UCHAR Channel)
8499 // RF R2 bit 18 = 0
8500 UINT32 R1 = 0, R2 = 0, R3 = 0;
8501 UCHAR index;
8502 RTMP_RF_REGS *RFRegTable;
8504 RFRegTable = RF2850RegTable;
8506 switch (pAd->RfIcType)
8508 case RFIC_2820:
8509 case RFIC_2850:
8510 case RFIC_2720:
8511 case RFIC_2750:
8513 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8515 if (Channel == RFRegTable[index].Channel)
8517 R1 = RFRegTable[index].R1 & 0xffffdfff;
8518 R2 = RFRegTable[index].R2 & 0xfffbffff;
8519 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8521 RTMP_RF_IO_WRITE32(pAd, R1);
8522 RTMP_RF_IO_WRITE32(pAd, R2);
8524 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8525 // Set RF R2 bit18=0, R3 bit[18:19]=0
8526 //if (pAd->StaCfg.bRadio == FALSE)
8527 if (1)
8529 RTMP_RF_IO_WRITE32(pAd, R3);
8531 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8532 Channel, pAd->RfIcType, R2, R3));
8534 else
8535 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8536 Channel, pAd->RfIcType, R2));
8537 break;
8540 break;
8542 default:
8543 break;
8548 VOID AsicTurnOnRFClk(
8549 IN PRTMP_ADAPTER pAd,
8550 IN UCHAR Channel)
8553 // RF R2 bit 18 = 0
8554 UINT32 R1 = 0, R2 = 0, R3 = 0;
8555 UCHAR index;
8556 RTMP_RF_REGS *RFRegTable;
8558 RFRegTable = RF2850RegTable;
8560 switch (pAd->RfIcType)
8562 case RFIC_2820:
8563 case RFIC_2850:
8564 case RFIC_2720:
8565 case RFIC_2750:
8567 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8569 if (Channel == RFRegTable[index].Channel)
8571 R3 = pAd->LatchRfRegs.R3;
8572 R3 &= 0xfff3ffff;
8573 R3 |= 0x00080000;
8574 RTMP_RF_IO_WRITE32(pAd, R3);
8576 R1 = RFRegTable[index].R1;
8577 RTMP_RF_IO_WRITE32(pAd, R1);
8579 R2 = RFRegTable[index].R2;
8580 if (pAd->Antenna.field.TxPath == 1)
8582 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8585 if (pAd->Antenna.field.RxPath == 2)
8587 R2 |= 0x40; // write 1 to off Rxpath.
8589 else if (pAd->Antenna.field.RxPath == 1)
8591 R2 |= 0x20040; // write 1 to off RxPath
8593 RTMP_RF_IO_WRITE32(pAd, R2);
8595 break;
8598 break;
8600 default:
8601 break;
8604 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
8605 Channel,
8606 pAd->RfIcType,
8607 R2));