Staging: rt2860: remove NATIVE_WPA_SUPPLICANT_SUPPORT ifdefs
[linux-2.6.git] / drivers / staging / rt2860 / common / mlme.c
blobff810e3c942d0cbd853fbd8ffb7b971461f37b9b
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 DOT11_N_SUPPORT
54 UCHAR PRE_N_HT_OUI[] = {0x00, 0x90, 0x4c};
55 #endif // DOT11_N_SUPPORT //
57 UCHAR RateSwitchTable[] = {
58 // 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)
59 0x11, 0x00, 0, 0, 0, // Initial used item after association
60 0x00, 0x00, 0, 40, 101,
61 0x01, 0x00, 1, 40, 50,
62 0x02, 0x00, 2, 35, 45,
63 0x03, 0x00, 3, 20, 45,
64 0x04, 0x21, 0, 30, 50,
65 0x05, 0x21, 1, 20, 50,
66 0x06, 0x21, 2, 20, 50,
67 0x07, 0x21, 3, 15, 50,
68 0x08, 0x21, 4, 15, 30,
69 0x09, 0x21, 5, 10, 25,
70 0x0a, 0x21, 6, 8, 25,
71 0x0b, 0x21, 7, 8, 25,
72 0x0c, 0x20, 12, 15, 30,
73 0x0d, 0x20, 13, 8, 20,
74 0x0e, 0x20, 14, 8, 20,
75 0x0f, 0x20, 15, 8, 25,
76 0x10, 0x22, 15, 8, 25,
77 0x11, 0x00, 0, 0, 0,
78 0x12, 0x00, 0, 0, 0,
79 0x13, 0x00, 0, 0, 0,
80 0x14, 0x00, 0, 0, 0,
81 0x15, 0x00, 0, 0, 0,
82 0x16, 0x00, 0, 0, 0,
83 0x17, 0x00, 0, 0, 0,
84 0x18, 0x00, 0, 0, 0,
85 0x19, 0x00, 0, 0, 0,
86 0x1a, 0x00, 0, 0, 0,
87 0x1b, 0x00, 0, 0, 0,
88 0x1c, 0x00, 0, 0, 0,
89 0x1d, 0x00, 0, 0, 0,
90 0x1e, 0x00, 0, 0, 0,
91 0x1f, 0x00, 0, 0, 0,
94 UCHAR RateSwitchTable11B[] = {
95 // 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)
96 0x04, 0x03, 0, 0, 0, // Initial used item after association
97 0x00, 0x00, 0, 40, 101,
98 0x01, 0x00, 1, 40, 50,
99 0x02, 0x00, 2, 35, 45,
100 0x03, 0x00, 3, 20, 45,
103 UCHAR RateSwitchTable11BG[] = {
104 // 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)
105 0x0a, 0x00, 0, 0, 0, // Initial used item after association
106 0x00, 0x00, 0, 40, 101,
107 0x01, 0x00, 1, 40, 50,
108 0x02, 0x00, 2, 35, 45,
109 0x03, 0x00, 3, 20, 45,
110 0x04, 0x10, 2, 20, 35,
111 0x05, 0x10, 3, 16, 35,
112 0x06, 0x10, 4, 10, 25,
113 0x07, 0x10, 5, 16, 25,
114 0x08, 0x10, 6, 10, 25,
115 0x09, 0x10, 7, 10, 13,
118 UCHAR RateSwitchTable11G[] = {
119 // 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)
120 0x08, 0x00, 0, 0, 0, // Initial used item after association
121 0x00, 0x10, 0, 20, 101,
122 0x01, 0x10, 1, 20, 35,
123 0x02, 0x10, 2, 20, 35,
124 0x03, 0x10, 3, 16, 35,
125 0x04, 0x10, 4, 10, 25,
126 0x05, 0x10, 5, 16, 25,
127 0x06, 0x10, 6, 10, 25,
128 0x07, 0x10, 7, 10, 13,
131 #ifdef DOT11_N_SUPPORT
132 UCHAR RateSwitchTable11N1S[] = {
133 // 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)
134 0x09, 0x00, 0, 0, 0, // Initial used item after association
135 0x00, 0x21, 0, 30, 101,
136 0x01, 0x21, 1, 20, 50,
137 0x02, 0x21, 2, 20, 50,
138 0x03, 0x21, 3, 15, 50,
139 0x04, 0x21, 4, 15, 30,
140 0x05, 0x21, 5, 10, 25,
141 0x06, 0x21, 6, 8, 14,
142 0x07, 0x21, 7, 8, 14,
143 0x08, 0x23, 7, 8, 14,
146 UCHAR RateSwitchTable11N2S[] = {
147 // 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)
148 0x0a, 0x00, 0, 0, 0, // Initial used item after association
149 0x00, 0x21, 0, 30, 101,
150 0x01, 0x21, 1, 20, 50,
151 0x02, 0x21, 2, 20, 50,
152 0x03, 0x21, 3, 15, 50,
153 0x04, 0x21, 4, 15, 30,
154 0x05, 0x20, 12, 15, 30,
155 0x06, 0x20, 13, 8, 20,
156 0x07, 0x20, 14, 8, 20,
157 0x08, 0x20, 15, 8, 25,
158 0x09, 0x22, 15, 8, 25,
161 UCHAR RateSwitchTable11N3S[] = {
162 // 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)
163 0x0a, 0x00, 0, 0, 0, // Initial used item after association
164 0x00, 0x21, 0, 30, 101,
165 0x01, 0x21, 1, 20, 50,
166 0x02, 0x21, 2, 20, 50,
167 0x03, 0x21, 3, 15, 50,
168 0x04, 0x21, 4, 15, 30,
169 0x05, 0x20, 12, 15, 30,
170 0x06, 0x20, 13, 8, 20,
171 0x07, 0x20, 14, 8, 20,
172 0x08, 0x20, 15, 8, 25,
173 0x09, 0x22, 15, 8, 25,
176 UCHAR RateSwitchTable11N2SForABand[] = {
177 // 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)
178 0x0b, 0x09, 0, 0, 0, // Initial used item after association
179 0x00, 0x21, 0, 30, 101,
180 0x01, 0x21, 1, 20, 50,
181 0x02, 0x21, 2, 20, 50,
182 0x03, 0x21, 3, 15, 50,
183 0x04, 0x21, 4, 15, 30,
184 0x05, 0x21, 5, 15, 30,
185 0x06, 0x20, 12, 15, 30,
186 0x07, 0x20, 13, 8, 20,
187 0x08, 0x20, 14, 8, 20,
188 0x09, 0x20, 15, 8, 25,
189 0x0a, 0x22, 15, 8, 25,
192 UCHAR RateSwitchTable11N3SForABand[] = { // 3*3
193 // 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)
194 0x0b, 0x09, 0, 0, 0, // Initial used item after association
195 0x00, 0x21, 0, 30, 101,
196 0x01, 0x21, 1, 20, 50,
197 0x02, 0x21, 2, 20, 50,
198 0x03, 0x21, 3, 15, 50,
199 0x04, 0x21, 4, 15, 30,
200 0x05, 0x21, 5, 15, 30,
201 0x06, 0x20, 12, 15, 30,
202 0x07, 0x20, 13, 8, 20,
203 0x08, 0x20, 14, 8, 20,
204 0x09, 0x20, 15, 8, 25,
205 0x0a, 0x22, 15, 8, 25,
208 UCHAR RateSwitchTable11BGN1S[] = {
209 // 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)
210 0x0d, 0x00, 0, 0, 0, // Initial used item after association
211 0x00, 0x00, 0, 40, 101,
212 0x01, 0x00, 1, 40, 50,
213 0x02, 0x00, 2, 35, 45,
214 0x03, 0x00, 3, 20, 45,
215 0x04, 0x21, 0, 30,101, //50
216 0x05, 0x21, 1, 20, 50,
217 0x06, 0x21, 2, 20, 50,
218 0x07, 0x21, 3, 15, 50,
219 0x08, 0x21, 4, 15, 30,
220 0x09, 0x21, 5, 10, 25,
221 0x0a, 0x21, 6, 8, 14,
222 0x0b, 0x21, 7, 8, 14,
223 0x0c, 0x23, 7, 8, 14,
226 UCHAR RateSwitchTable11BGN2S[] = {
227 // 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)
228 0x0a, 0x00, 0, 0, 0, // Initial used item after association
229 0x00, 0x21, 0, 30,101, //50
230 0x01, 0x21, 1, 20, 50,
231 0x02, 0x21, 2, 20, 50,
232 0x03, 0x21, 3, 15, 50,
233 0x04, 0x21, 4, 15, 30,
234 0x05, 0x20, 12, 15, 30,
235 0x06, 0x20, 13, 8, 20,
236 0x07, 0x20, 14, 8, 20,
237 0x08, 0x20, 15, 8, 25,
238 0x09, 0x22, 15, 8, 25,
241 UCHAR RateSwitchTable11BGN3S[] = { // 3*3
242 // 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)
243 0x0a, 0x00, 0, 0, 0, // Initial used item after association
244 0x00, 0x21, 0, 30,101, //50
245 0x01, 0x21, 1, 20, 50,
246 0x02, 0x21, 2, 20, 50,
247 0x03, 0x21, 3, 20, 50,
248 0x04, 0x21, 4, 15, 50,
249 0x05, 0x20, 20, 15, 30,
250 0x06, 0x20, 21, 8, 20,
251 0x07, 0x20, 22, 8, 20,
252 0x08, 0x20, 23, 8, 25,
253 0x09, 0x22, 23, 8, 25,
256 UCHAR RateSwitchTable11BGN2SForABand[] = {
257 // 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)
258 0x0b, 0x09, 0, 0, 0, // Initial used item after association
259 0x00, 0x21, 0, 30,101, //50
260 0x01, 0x21, 1, 20, 50,
261 0x02, 0x21, 2, 20, 50,
262 0x03, 0x21, 3, 15, 50,
263 0x04, 0x21, 4, 15, 30,
264 0x05, 0x21, 5, 15, 30,
265 0x06, 0x20, 12, 15, 30,
266 0x07, 0x20, 13, 8, 20,
267 0x08, 0x20, 14, 8, 20,
268 0x09, 0x20, 15, 8, 25,
269 0x0a, 0x22, 15, 8, 25,
272 UCHAR RateSwitchTable11BGN3SForABand[] = { // 3*3
273 // 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)
274 0x0c, 0x09, 0, 0, 0, // Initial used item after association
275 0x00, 0x21, 0, 30,101, //50
276 0x01, 0x21, 1, 20, 50,
277 0x02, 0x21, 2, 20, 50,
278 0x03, 0x21, 3, 15, 50,
279 0x04, 0x21, 4, 15, 30,
280 0x05, 0x21, 5, 15, 30,
281 0x06, 0x21, 12, 15, 30,
282 0x07, 0x20, 20, 15, 30,
283 0x08, 0x20, 21, 8, 20,
284 0x09, 0x20, 22, 8, 20,
285 0x0a, 0x20, 23, 8, 25,
286 0x0b, 0x22, 23, 8, 25,
288 #endif // DOT11_N_SUPPORT //
290 PUCHAR ReasonString[] = {
291 /* 0 */ "Reserved",
292 /* 1 */ "Unspecified Reason",
293 /* 2 */ "Previous Auth no longer valid",
294 /* 3 */ "STA is leaving / has left",
295 /* 4 */ "DIS-ASSOC due to inactivity",
296 /* 5 */ "AP unable to hanle all associations",
297 /* 6 */ "class 2 error",
298 /* 7 */ "class 3 error",
299 /* 8 */ "STA is leaving / has left",
300 /* 9 */ "require auth before assoc/re-assoc",
301 /* 10 */ "Reserved",
302 /* 11 */ "Reserved",
303 /* 12 */ "Reserved",
304 /* 13 */ "invalid IE",
305 /* 14 */ "MIC error",
306 /* 15 */ "4-way handshake timeout",
307 /* 16 */ "2-way (group key) handshake timeout",
308 /* 17 */ "4-way handshake IE diff among AssosReq/Rsp/Beacon",
309 /* 18 */
312 extern UCHAR OfdmRateToRxwiMCS[];
313 // since RT61 has better RX sensibility, we have to limit TX ACK rate not to exceed our normal data TX rate.
314 // otherwise the WLAN peer may not be able to receive the ACK thus downgrade its data TX rate
315 ULONG BasicRateMask[12] = {0xfffff001 /* 1-Mbps */, 0xfffff003 /* 2 Mbps */, 0xfffff007 /* 5.5 */, 0xfffff00f /* 11 */,
316 0xfffff01f /* 6 */ , 0xfffff03f /* 9 */ , 0xfffff07f /* 12 */ , 0xfffff0ff /* 18 */,
317 0xfffff1ff /* 24 */ , 0xfffff3ff /* 36 */ , 0xfffff7ff /* 48 */ , 0xffffffff /* 54 */};
319 UCHAR MULTICAST_ADDR[MAC_ADDR_LEN] = {0x1, 0x00, 0x00, 0x00, 0x00, 0x00};
320 UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
321 UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
323 // e.g. RssiSafeLevelForTxRate[RATE_36]" means if the current RSSI is greater than
324 // this value, then it's quaranteed capable of operating in 36 mbps TX rate in
325 // clean environment.
326 // TxRate: 1 2 5.5 11 6 9 12 18 24 36 48 54 72 100
327 CHAR RssiSafeLevelForTxRate[] ={ -92, -91, -90, -87, -88, -86, -85, -83, -81, -78, -72, -71, -40, -40 };
329 UCHAR RateIdToMbps[] = { 1, 2, 5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 72, 100};
330 USHORT RateIdTo500Kbps[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 144, 200};
332 UCHAR SsidIe = IE_SSID;
333 UCHAR SupRateIe = IE_SUPP_RATES;
334 UCHAR ExtRateIe = IE_EXT_SUPP_RATES;
335 #ifdef DOT11_N_SUPPORT
336 UCHAR HtCapIe = IE_HT_CAP;
337 UCHAR AddHtInfoIe = IE_ADD_HT;
338 UCHAR NewExtChanIe = IE_SECONDARY_CH_OFFSET;
339 #endif // DOT11_N_SUPPORT //
340 UCHAR ErpIe = IE_ERP;
341 UCHAR DsIe = IE_DS_PARM;
342 UCHAR TimIe = IE_TIM;
343 UCHAR WpaIe = IE_WPA;
344 UCHAR Wpa2Ie = IE_WPA2;
345 UCHAR IbssIe = IE_IBSS_PARM;
346 UCHAR Ccx2Ie = IE_CCX_V2;
348 extern UCHAR WPA_OUI[];
350 UCHAR SES_OUI[] = {0x00, 0x90, 0x4c};
352 UCHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
353 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
355 // Reset the RFIC setting to new series
356 RTMP_RF_REGS RF2850RegTable[] = {
357 // ch R1 R2 R3(TX0~4=0) R4
358 {1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b},
359 {2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f},
360 {3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b},
361 {4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f},
362 {5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b},
363 {6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f},
364 {7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b},
365 {8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f},
366 {9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b},
367 {10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f},
368 {11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b},
369 {12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f},
370 {13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b},
371 {14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193},
373 // 802.11 UNI / HyperLan 2
374 {36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3},
375 {38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193},
376 {40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183},
377 {44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3},
378 {46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b},
379 {48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b},
380 {52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193},
381 {54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3},
382 {56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b},
383 {60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183},
384 {62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193},
385 {64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3}, // Plugfest#4, Day4, change RFR3 left4th 9->5.
387 // 802.11 HyperLan 2
388 {100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783},
390 // 2008.04.30 modified
391 // The system team has AN to improve the EVM value
392 // for channel 102 to 108 for the RT2850/RT2750 dual band solution.
393 {102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793},
394 {104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3},
395 {108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193},
397 {110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183},
398 {112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b},
399 {116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3},
400 {118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193},
401 {120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183},
402 {124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193},
403 {126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b}, // 0x980ed1bb->0x980ed15b required by Rory 20070927
404 {128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3},
405 {132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b},
406 {134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193},
407 {136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b},
408 {140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183},
410 // 802.11 UNII
411 {149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7},
412 {151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187},
413 {153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f},
414 {157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f},
415 {159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7},
416 {161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187},
417 {165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197},
419 // Japan
420 {184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b},
421 {188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13},
422 {192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b},
423 {196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23},
424 {208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13},
425 {212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b},
426 {216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23},
428 // still lack of MMAC(Japan) ch 34,38,42,46
430 UCHAR NUM_OF_2850_CHNL = (sizeof(RF2850RegTable) / sizeof(RTMP_RF_REGS));
432 FREQUENCY_ITEM FreqItems3020[] =
434 /**************************************************/
435 // ISM : 2.4 to 2.483 GHz //
436 /**************************************************/
437 // 11g
438 /**************************************************/
439 //-CH---N-------R---K-----------
440 {1, 241, 2, 2},
441 {2, 241, 2, 7},
442 {3, 242, 2, 2},
443 {4, 242, 2, 7},
444 {5, 243, 2, 2},
445 {6, 243, 2, 7},
446 {7, 244, 2, 2},
447 {8, 244, 2, 7},
448 {9, 245, 2, 2},
449 {10, 245, 2, 7},
450 {11, 246, 2, 2},
451 {12, 246, 2, 7},
452 {13, 247, 2, 2},
453 {14, 248, 2, 4},
455 #define NUM_OF_3020_CHNL (sizeof(FreqItems3020) / sizeof(FREQUENCY_ITEM))
458 ==========================================================================
459 Description:
460 initialize the MLME task and its data structure (queue, spinlock,
461 timer, state machines).
463 IRQL = PASSIVE_LEVEL
465 Return:
466 always return NDIS_STATUS_SUCCESS
468 ==========================================================================
470 NDIS_STATUS MlmeInit(
471 IN PRTMP_ADAPTER pAd)
473 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
475 DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n"));
479 Status = MlmeQueueInit(&pAd->Mlme.Queue);
480 if(Status != NDIS_STATUS_SUCCESS)
481 break;
483 pAd->Mlme.bRunning = FALSE;
484 NdisAllocateSpinLock(&pAd->Mlme.TaskLock);
486 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
488 BssTableInit(&pAd->ScanTab);
490 // init STA state machines
491 AssocStateMachineInit(pAd, &pAd->Mlme.AssocMachine, pAd->Mlme.AssocFunc);
492 AuthStateMachineInit(pAd, &pAd->Mlme.AuthMachine, pAd->Mlme.AuthFunc);
493 AuthRspStateMachineInit(pAd, &pAd->Mlme.AuthRspMachine, pAd->Mlme.AuthRspFunc);
494 SyncStateMachineInit(pAd, &pAd->Mlme.SyncMachine, pAd->Mlme.SyncFunc);
495 WpaPskStateMachineInit(pAd, &pAd->Mlme.WpaPskMachine, pAd->Mlme.WpaPskFunc);
496 AironetStateMachineInit(pAd, &pAd->Mlme.AironetMachine, pAd->Mlme.AironetFunc);
498 // Since we are using switch/case to implement it, the init is different from the above
499 // state machine init
500 MlmeCntlInit(pAd, &pAd->Mlme.CntlMachine, NULL);
503 ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc);
505 // Init mlme periodic timer
506 RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExec), pAd, TRUE);
508 // Set mlme periodic timer
509 RTMPSetTimer(&pAd->Mlme.PeriodicTimer, MLME_TASK_EXEC_INTV);
511 // software-based RX Antenna diversity
512 RTMPInitTimer(pAd, &pAd->Mlme.RxAntEvalTimer, GET_TIMER_FUNCTION(AsicRxAntEvalTimeout), pAd, FALSE);
514 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
516 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
518 // only PCIe cards need these two timers
519 RTMPInitTimer(pAd, &pAd->Mlme.PsPollTimer, GET_TIMER_FUNCTION(PsPollWakeExec), pAd, FALSE);
520 RTMPInitTimer(pAd, &pAd->Mlme.RadioOnOffTimer, GET_TIMER_FUNCTION(RadioOnExec), pAd, FALSE);
523 } while (FALSE);
525 DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n"));
527 return Status;
531 ==========================================================================
532 Description:
533 main loop of the MLME
534 Pre:
535 Mlme has to be initialized, and there are something inside the queue
536 Note:
537 This function is invoked from MPSetInformation and MPReceive;
538 This task guarantee only one MlmeHandler will run.
540 IRQL = DISPATCH_LEVEL
542 ==========================================================================
544 VOID MlmeHandler(
545 IN PRTMP_ADAPTER pAd)
547 MLME_QUEUE_ELEM *Elem = NULL;
549 // Only accept MLME and Frame from peer side, no other (control/data) frame should
550 // get into this state machine
552 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
553 if(pAd->Mlme.bRunning)
555 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
556 return;
558 else
560 pAd->Mlme.bRunning = TRUE;
562 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
564 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
566 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) ||
567 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
568 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
570 DBGPRINT(RT_DEBUG_TRACE, ("Device Halted or Removed or MlmeRest, exit MlmeHandler! (queue num = %ld)\n", pAd->Mlme.Queue.Num));
571 break;
574 //From message type, determine which state machine I should drive
575 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
578 // if dequeue success
579 switch (Elem->Machine)
581 // STA state machines
582 case ASSOC_STATE_MACHINE:
583 StateMachinePerformAction(pAd, &pAd->Mlme.AssocMachine, Elem);
584 break;
585 case AUTH_STATE_MACHINE:
586 StateMachinePerformAction(pAd, &pAd->Mlme.AuthMachine, Elem);
587 break;
588 case AUTH_RSP_STATE_MACHINE:
589 StateMachinePerformAction(pAd, &pAd->Mlme.AuthRspMachine, Elem);
590 break;
591 case SYNC_STATE_MACHINE:
592 StateMachinePerformAction(pAd, &pAd->Mlme.SyncMachine, Elem);
593 break;
594 case MLME_CNTL_STATE_MACHINE:
595 MlmeCntlMachinePerformAction(pAd, &pAd->Mlme.CntlMachine, Elem);
596 break;
597 case WPA_PSK_STATE_MACHINE:
598 StateMachinePerformAction(pAd, &pAd->Mlme.WpaPskMachine, Elem);
599 break;
600 case AIRONET_STATE_MACHINE:
601 StateMachinePerformAction(pAd, &pAd->Mlme.AironetMachine, Elem);
602 break;
603 case ACTION_STATE_MACHINE:
604 StateMachinePerformAction(pAd, &pAd->Mlme.ActMachine, Elem);
605 break;
610 default:
611 DBGPRINT(RT_DEBUG_TRACE, ("ERROR: Illegal machine %ld in MlmeHandler()\n", Elem->Machine));
612 break;
613 } // end of switch
615 // free MLME element
616 Elem->Occupied = FALSE;
617 Elem->MsgLen = 0;
620 else {
621 DBGPRINT_ERR(("MlmeHandler: MlmeQueue empty\n"));
625 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
626 pAd->Mlme.bRunning = FALSE;
627 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
631 ==========================================================================
632 Description:
633 Destructor of MLME (Destroy queue, state machine, spin lock and timer)
634 Parameters:
635 Adapter - NIC Adapter pointer
636 Post:
637 The MLME task will no longer work properly
639 IRQL = PASSIVE_LEVEL
641 ==========================================================================
643 VOID MlmeHalt(
644 IN PRTMP_ADAPTER pAd)
646 BOOLEAN Cancelled;
648 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n"));
650 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
652 // disable BEACON generation and other BEACON related hardware timers
653 AsicDisableSync(pAd);
656 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
658 // Cancel pending timers
659 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
660 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
661 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
662 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
663 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
664 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
665 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE))
667 RTMPCancelTimer(&pAd->Mlme.PsPollTimer, &Cancelled);
668 RTMPCancelTimer(&pAd->Mlme.RadioOnOffTimer, &Cancelled);
672 RTMPCancelTimer(&pAd->Mlme.PeriodicTimer, &Cancelled);
673 RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled);
677 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
679 // Set LED
680 RTMPSetLED(pAd, LED_HALT);
681 RTMPSetSignalLED(pAd, -100); // Force signal strength Led to be turned off, firmware is not done it.
684 RTMPusecDelay(5000); // 5 msec to gurantee Ant Diversity timer canceled
686 MlmeQueueDestroy(&pAd->Mlme.Queue);
687 NdisFreeSpinLock(&pAd->Mlme.TaskLock);
689 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n"));
692 VOID MlmeResetRalinkCounters(
693 IN PRTMP_ADAPTER pAd)
695 pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt;
696 // clear all OneSecxxx counters.
697 pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
698 pAd->RalinkCounters.OneSecFalseCCACnt = 0;
699 pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
700 pAd->RalinkCounters.OneSecRxOkCnt = 0;
701 pAd->RalinkCounters.OneSecTxFailCount = 0;
702 pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
703 pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
704 pAd->RalinkCounters.OneSecRxOkDataCnt = 0;
706 // TODO: for debug only. to be removed
707 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
708 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
709 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
710 pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
711 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
712 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
713 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
714 pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
715 pAd->RalinkCounters.OneSecTxDoneCount = 0;
716 pAd->RalinkCounters.OneSecRxCount = 0;
717 pAd->RalinkCounters.OneSecTxAggregationCount = 0;
718 pAd->RalinkCounters.OneSecRxAggregationCount = 0;
720 return;
723 unsigned long rx_AMSDU;
724 unsigned long rx_Total;
727 ==========================================================================
728 Description:
729 This routine is executed periodically to -
730 1. Decide if it's a right time to turn on PwrMgmt bit of all
731 outgoiing frames
732 2. Calculate ChannelQuality based on statistics of the last
733 period, so that TX rate won't toggling very frequently between a
734 successful TX and a failed TX.
735 3. If the calculated ChannelQuality indicated current connection not
736 healthy, then a ROAMing attempt is tried here.
738 IRQL = DISPATCH_LEVEL
740 ==========================================================================
742 #define ADHOC_BEACON_LOST_TIME (8*OS_HZ) // 8 sec
743 VOID MlmePeriodicExec(
744 IN PVOID SystemSpecific1,
745 IN PVOID FunctionContext,
746 IN PVOID SystemSpecific2,
747 IN PVOID SystemSpecific3)
749 ULONG TxTotalCnt;
750 PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
752 //Baron 2008/07/10
753 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
754 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
755 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
756 if(pAd->StaCfg.WepStatus<2)
758 pAd->StaCfg.WpaSupplicantUP = 0;
760 else
762 pAd->StaCfg.WpaSupplicantUP = 1;
765 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
767 // If Hardware controlled Radio enabled, we have to check GPIO pin2 every 2 second.
768 // Move code to here, because following code will return when radio is off
769 if ((pAd->Mlme.PeriodicRound % (MLME_TASK_EXEC_MULTIPLE * 2) == 0) &&
770 (pAd->StaCfg.bHardwareRadio == TRUE) &&
771 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
772 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) &&
773 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)))
775 UINT32 data = 0;
777 // Read GPIO pin2 as Hardware controlled radio state
778 RTMP_IO_FORCE_READ32(pAd, GPIO_CTRL_CFG, &data);
779 if (data & 0x04)
781 pAd->StaCfg.bHwRadio = TRUE;
783 else
785 pAd->StaCfg.bHwRadio = FALSE;
787 if (pAd->StaCfg.bRadio != (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio))
789 pAd->StaCfg.bRadio = (pAd->StaCfg.bHwRadio && pAd->StaCfg.bSwRadio);
790 if (pAd->StaCfg.bRadio == TRUE)
792 MlmeRadioOn(pAd);
793 // Update extra information
794 pAd->ExtraInfo = EXTRA_INFO_CLEAR;
796 else
798 MlmeRadioOff(pAd);
799 // Update extra information
800 pAd->ExtraInfo = HW_RADIO_OFF;
806 // Do nothing if the driver is starting halt state.
807 // This might happen when timer already been fired before cancel timer with mlmehalt
808 if ((RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_HALT_IN_PROGRESS |
809 fRTMP_ADAPTER_RADIO_OFF |
810 fRTMP_ADAPTER_RADIO_MEASUREMENT |
811 fRTMP_ADAPTER_RESET_IN_PROGRESS))))
812 return;
814 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
816 if ((pAd->RalinkCounters.LastReceivedByteCount == pAd->RalinkCounters.ReceivedByteCount) && (pAd->StaCfg.bRadio == TRUE))
818 // If ReceiveByteCount doesn't change, increase SameRxByteCount by 1.
819 pAd->SameRxByteCount++;
821 else
822 pAd->SameRxByteCount = 0;
824 // If after BBP, still not work...need to check to reset PBF&MAC.
825 if (pAd->SameRxByteCount == 702)
827 pAd->SameRxByteCount = 0;
828 AsicResetPBF(pAd);
829 AsicResetMAC(pAd);
832 // If SameRxByteCount keeps happens for 2 second in infra mode, or for 60 seconds in idle mode.
833 if (((INFRA_ON(pAd)) && (pAd->SameRxByteCount > 20)) || ((IDLE_ON(pAd)) && (pAd->SameRxByteCount > 600)))
835 if ((pAd->StaCfg.bRadio == TRUE) && (pAd->SameRxByteCount < 700))
837 DBGPRINT(RT_DEBUG_TRACE, ("---> SameRxByteCount = %lu !!!!!!!!!!!!!!! \n", pAd->SameRxByteCount));
838 pAd->SameRxByteCount = 700;
839 AsicResetBBP(pAd);
843 // Update lastReceiveByteCount.
844 pAd->RalinkCounters.LastReceivedByteCount = pAd->RalinkCounters.ReceivedByteCount;
846 if ((pAd->CheckDmaBusyCount > 3) && (IDLE_ON(pAd)))
848 pAd->CheckDmaBusyCount = 0;
849 AsicResetFromDMABusy(pAd);
853 RT28XX_MLME_PRE_SANITY_CHECK(pAd);
855 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
857 // Do nothing if monitor mode is on
858 if (MONITOR_ON(pAd))
859 return;
861 if (pAd->Mlme.PeriodicRound & 0x1)
863 // This is the fix for wifi 11n extension channel overlapping test case. for 2860D
864 if (((pAd->MACVersion & 0xffff) == 0x0101) &&
865 (STA_TGN_WIFI_ON(pAd)) &&
866 (pAd->CommonCfg.IOTestParm.bToggle == FALSE))
869 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x24Bf);
870 pAd->CommonCfg.IOTestParm.bToggle = TRUE;
872 else if ((STA_TGN_WIFI_ON(pAd)) &&
873 ((pAd->MACVersion & 0xffff) == 0x0101))
875 RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, 0x243f);
876 pAd->CommonCfg.IOTestParm.bToggle = FALSE;
881 pAd->bUpdateBcnCntDone = FALSE;
883 // RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);
884 pAd->Mlme.PeriodicRound ++;
886 // execute every 500ms
887 if ((pAd->Mlme.PeriodicRound % 5 == 0) && RTMPAutoRateSwitchCheck(pAd)/*(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED))*/)
889 // perform dynamic tx rate switching based on past TX history
890 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
892 if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
894 && (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)))
895 MlmeDynamicTxRateSwitching(pAd);
899 // Normal 1 second Mlme PeriodicExec.
900 if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0)
902 pAd->Mlme.OneSecPeriodicRound ++;
904 if (rx_Total)
907 // reset counters
908 rx_AMSDU = 0;
909 rx_Total = 0;
912 // Media status changed, report to NDIS
913 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE))
915 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MEDIA_STATE_CHANGE);
916 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
918 pAd->IndicateMediaState = NdisMediaStateConnected;
919 RTMP_IndicateMediaState(pAd);
922 else
924 pAd->IndicateMediaState = NdisMediaStateDisconnected;
925 RTMP_IndicateMediaState(pAd);
929 NdisGetSystemUpTime(&pAd->Mlme.Now32);
931 // add the most up-to-date h/w raw counters into software variable, so that
932 // the dynamic tuning mechanism below are based on most up-to-date information
933 NICUpdateRawCounters(pAd);
936 #ifdef DOT11_N_SUPPORT
937 // Need statistics after read counter. So put after NICUpdateRawCounters
938 ORIBATimerTimeout(pAd);
939 #endif // DOT11_N_SUPPORT //
942 // The time period for checking antenna is according to traffic
943 if (pAd->Mlme.bEnableAutoAntennaCheck)
945 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
946 pAd->RalinkCounters.OneSecTxRetryOkCount +
947 pAd->RalinkCounters.OneSecTxFailCount;
949 if (TxTotalCnt > 50)
951 if (pAd->Mlme.OneSecPeriodicRound % 10 == 0)
953 AsicEvaluateRxAnt(pAd);
956 else
958 if (pAd->Mlme.OneSecPeriodicRound % 3 == 0)
960 AsicEvaluateRxAnt(pAd);
965 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
966 STAMlmePeriodicExec(pAd);
968 MlmeResetRalinkCounters(pAd);
970 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
972 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) && (pAd->bPCIclkOff == FALSE))
974 // When Adhoc beacon is enabled and RTS/CTS is enabled, there is a chance that hardware MAC FSM will run into a deadlock
975 // and sending CTS-to-self over and over.
976 // Software Patch Solution:
977 // 1. Polling debug state register 0x10F4 every one second.
978 // 2. If in 0x10F4 the ((bit29==1) && (bit7==1)) OR ((bit29==1) && (bit5==1)), it means the deadlock has occurred.
979 // 3. If the deadlock occurred, reset MAC/BBP by setting 0x1004 to 0x0001 for a while then setting it back to 0x000C again.
981 UINT32 MacReg = 0;
983 RTMP_IO_READ32(pAd, 0x10F4, &MacReg);
984 if (((MacReg & 0x20000000) && (MacReg & 0x80)) || ((MacReg & 0x20000000) && (MacReg & 0x20)))
986 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1);
987 RTMPusecDelay(1);
988 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xC);
990 DBGPRINT(RT_DEBUG_WARN,("Warning, MAC specific condition occurs \n"));
995 RT28XX_MLME_HANDLER(pAd);
999 pAd->bUpdateBcnCntDone = FALSE;
1002 VOID STAMlmePeriodicExec(
1003 PRTMP_ADAPTER pAd)
1005 ULONG TxTotalCnt;
1007 #ifdef WPA_SUPPLICANT_SUPPORT
1008 if (pAd->StaCfg.WpaSupplicantUP == WPA_SUPPLICANT_DISABLE)
1009 #endif // WPA_SUPPLICANT_SUPPORT //
1011 // WPA MIC error should block association attempt for 60 seconds
1012 if (pAd->StaCfg.bBlockAssoc && (pAd->StaCfg.LastMicErrorTime + (60 * OS_HZ) < pAd->Mlme.Now32))
1013 pAd->StaCfg.bBlockAssoc = FALSE;
1016 //Baron 2008/07/10
1017 //printk("Baron_Test:\t%s", RTMPGetRalinkEncryModeStr(pAd->StaCfg.WepStatus));
1018 //If the STA security setting is OPEN or WEP, pAd->StaCfg.WpaSupplicantUP = 0.
1019 //If the STA security setting is WPAPSK or WPA2PSK, pAd->StaCfg.WpaSupplicantUP = 1.
1020 if(pAd->StaCfg.WepStatus<2)
1022 pAd->StaCfg.WpaSupplicantUP = 0;
1024 else
1026 pAd->StaCfg.WpaSupplicantUP = 1;
1029 if ((pAd->PreMediaState != pAd->IndicateMediaState) && (pAd->CommonCfg.bWirelessEvent))
1031 if (pAd->IndicateMediaState == NdisMediaStateConnected)
1033 RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1035 pAd->PreMediaState = pAd->IndicateMediaState;
1038 if ((pAd->OpMode == OPMODE_STA) && (IDLE_ON(pAd)) &&
1039 (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE)) &&
1040 (pAd->Mlme.SyncMachine.CurrState == SYNC_IDLE) &&
1041 (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1042 (RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP)) &&
1043 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)))
1045 RT28xxPciAsicRadioOff(pAd, GUI_IDLE_POWER_SAVE, 0);
1050 AsicStaBbpTuning(pAd);
1052 TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
1053 pAd->RalinkCounters.OneSecTxRetryOkCount +
1054 pAd->RalinkCounters.OneSecTxFailCount;
1056 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
1058 // update channel quality for Roaming and UI LinkQuality display
1059 MlmeCalculateChannelQuality(pAd, pAd->Mlme.Now32);
1062 // must be AFTER MlmeDynamicTxRateSwitching() because it needs to know if
1063 // Radio is currently in noisy environment
1064 if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
1065 AsicAdjustTxPower(pAd);
1067 if (INFRA_ON(pAd))
1069 // Is PSM bit consistent with user power management policy?
1070 // This is the only place that will set PSM bit ON.
1071 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
1072 MlmeCheckPsmChange(pAd, pAd->Mlme.Now32);
1074 pAd->RalinkCounters.LastOneSecTotalTxCount = TxTotalCnt;
1076 if ((pAd->StaCfg.LastBeaconRxTime + 1*OS_HZ < pAd->Mlme.Now32) &&
1077 (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) &&
1078 ((TxTotalCnt + pAd->RalinkCounters.OneSecRxOkCnt < 600)))
1080 RTMPSetAGCInitValue(pAd, BW_20);
1081 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. restore R66 to the low bound(%d) \n", (0x2E + GET_LNA_GAIN(pAd))));
1085 if (pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable)
1087 // When APSD is enabled, the period changes as 20 sec
1088 if ((pAd->Mlme.OneSecPeriodicRound % 20) == 8)
1089 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1091 else
1093 // Send out a NULL frame every 10 sec to inform AP that STA is still alive (Avoid being age out)
1094 if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8)
1096 if (pAd->CommonCfg.bWmmCapable)
1097 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
1098 else
1099 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
1104 if (CQI_IS_DEAD(pAd->Mlme.ChannelQuality))
1106 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - No BEACON. Dead CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1107 pAd->StaCfg.CCXAdjacentAPReportFlag = TRUE;
1108 pAd->StaCfg.CCXAdjacentAPLinkDownTime = pAd->StaCfg.LastBeaconRxTime;
1110 // Lost AP, send disconnect & link down event
1111 LinkDown(pAd, FALSE);
1114 union iwreq_data wrqu;
1115 memset(wrqu.ap_addr.sa_data, 0, MAC_ADDR_LEN);
1116 wireless_send_event(pAd->net_dev, SIOCGIWAP, &wrqu, NULL);
1119 MlmeAutoReconnectLastSSID(pAd);
1121 else if (CQI_IS_BAD(pAd->Mlme.ChannelQuality))
1123 pAd->RalinkCounters.BadCQIAutoRecoveryCount ++;
1124 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Bad CQI. Auto Recovery attempt #%ld\n", pAd->RalinkCounters.BadCQIAutoRecoveryCount));
1125 MlmeAutoReconnectLastSSID(pAd);
1128 // Add auto seamless roaming
1129 if (pAd->StaCfg.bFastRoaming)
1131 SHORT dBmToRoam = (SHORT)pAd->StaCfg.dBmToRoam;
1133 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));
1135 if (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) <= (CHAR)dBmToRoam)
1137 MlmeCheckForFastRoaming(pAd, pAd->Mlme.Now32);
1141 else if (ADHOC_ON(pAd))
1143 // 2003-04-17 john. this is a patch that driver forces a BEACON out if ASIC fails
1144 // the "TX BEACON competition" for the entire past 1 sec.
1145 // So that even when ASIC's BEACONgen engine been blocked
1146 // by peer's BEACON due to slower system clock, this STA still can send out
1147 // minimum BEACON to tell the peer I'm alive.
1148 // drawback is that this BEACON won't be well aligned at TBTT boundary.
1149 // EnqueueBeaconFrame(pAd); // software send BEACON
1151 // if all 11b peers leave this BSS more than 5 seconds, update Tx rate,
1152 // restore outgoing BEACON to support B/G-mixed mode
1153 if ((pAd->CommonCfg.Channel <= 14) &&
1154 (pAd->CommonCfg.MaxTxRate <= RATE_11) &&
1155 (pAd->CommonCfg.MaxDesiredRate > RATE_11) &&
1156 ((pAd->StaCfg.Last11bBeaconRxTime + 5*OS_HZ) < pAd->Mlme.Now32))
1158 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11B peer left, update Tx rates\n"));
1159 NdisMoveMemory(pAd->StaActive.SupRate, pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES);
1160 pAd->StaActive.SupRateLen = pAd->CommonCfg.SupRateLen;
1161 MlmeUpdateTxRates(pAd, FALSE, 0);
1162 MakeIbssBeacon(pAd); // re-build BEACON frame
1163 AsicEnableIbssSync(pAd); // copy to on-chip memory
1164 pAd->StaCfg.AdhocBOnlyJoined = FALSE;
1167 #ifdef DOT11_N_SUPPORT
1168 if (pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED)
1170 if ((pAd->StaCfg.AdhocBGJoined) &&
1171 ((pAd->StaCfg.Last11gBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1173 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 11G peer left\n"));
1174 pAd->StaCfg.AdhocBGJoined = FALSE;
1177 if ((pAd->StaCfg.Adhoc20NJoined) &&
1178 ((pAd->StaCfg.Last20NBeaconRxTime + 5 * OS_HZ) < pAd->Mlme.Now32))
1180 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - last 20MHz N peer left\n"));
1181 pAd->StaCfg.Adhoc20NJoined = FALSE;
1184 #endif // DOT11_N_SUPPORT //
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 else // no INFRA nor ADHOC connection
1213 if (pAd->StaCfg.bScanReqIsFromWebUI &&
1214 ((pAd->StaCfg.LastScanTime + 30 * OS_HZ) > pAd->Mlme.Now32))
1215 goto SKIP_AUTO_SCAN_CONN;
1216 else
1217 pAd->StaCfg.bScanReqIsFromWebUI = FALSE;
1219 if ((pAd->StaCfg.bAutoReconnect == TRUE)
1220 && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)
1221 && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1223 if ((pAd->ScanTab.BssNr==0) && (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE))
1225 MLME_SCAN_REQ_STRUCT ScanReq;
1227 if ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32)
1229 DBGPRINT(RT_DEBUG_TRACE, ("STAMlmePeriodicExec():CNTL - ScanTab.BssNr==0, start a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid));
1230 ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE);
1231 MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq);
1232 pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN;
1233 // Reset Missed scan number
1234 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1236 else if (pAd->StaCfg.BssType == BSS_ADHOC) // Quit the forever scan when in a very clean room
1237 MlmeAutoReconnectLastSSID(pAd);
1239 else if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1241 if ((pAd->Mlme.OneSecPeriodicRound % 7) == 0)
1243 MlmeAutoScan(pAd);
1244 pAd->StaCfg.LastScanTime = pAd->Mlme.Now32;
1246 else
1248 MlmeAutoReconnectLastSSID(pAd);
1254 SKIP_AUTO_SCAN_CONN:
1256 #ifdef DOT11_N_SUPPORT
1257 if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap !=0) && (pAd->MacTab.fAnyBASession == FALSE))
1259 pAd->MacTab.fAnyBASession = TRUE;
1260 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, FALSE, FALSE);
1262 else if ((pAd->MacTab.Content[BSSID_WCID].TXBAbitmap ==0) && (pAd->MacTab.fAnyBASession == TRUE))
1264 pAd->MacTab.fAnyBASession = FALSE;
1265 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, FALSE);
1267 #endif // DOT11_N_SUPPORT //
1269 return;
1272 // Link down report
1273 VOID LinkDownExec(
1274 IN PVOID SystemSpecific1,
1275 IN PVOID FunctionContext,
1276 IN PVOID SystemSpecific2,
1277 IN PVOID SystemSpecific3)
1280 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
1282 pAd->IndicateMediaState = NdisMediaStateDisconnected;
1283 RTMP_IndicateMediaState(pAd);
1284 pAd->ExtraInfo = GENERAL_LINK_DOWN;
1287 // IRQL = DISPATCH_LEVEL
1288 VOID MlmeAutoScan(
1289 IN PRTMP_ADAPTER pAd)
1291 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1292 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1294 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Driver auto scan\n"));
1295 MlmeEnqueue(pAd,
1296 MLME_CNTL_STATE_MACHINE,
1297 OID_802_11_BSSID_LIST_SCAN,
1299 NULL);
1300 RT28XX_MLME_HANDLER(pAd);
1304 // IRQL = DISPATCH_LEVEL
1305 VOID MlmeAutoReconnectLastSSID(
1306 IN PRTMP_ADAPTER pAd)
1310 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1311 if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) &&
1312 (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE))
1314 NDIS_802_11_SSID OidSsid;
1315 OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen;
1316 NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);
1318 DBGPRINT(RT_DEBUG_TRACE, ("Driver auto reconnect to last OID_802_11_SSID setting - %s, len - %d\n", pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen));
1319 MlmeEnqueue(pAd,
1320 MLME_CNTL_STATE_MACHINE,
1321 OID_802_11_SSID,
1322 sizeof(NDIS_802_11_SSID),
1323 &OidSsid);
1324 RT28XX_MLME_HANDLER(pAd);
1329 ==========================================================================
1330 Validate SSID for connection try and rescan purpose
1331 Valid SSID will have visible chars only.
1332 The valid length is from 0 to 32.
1333 IRQL = DISPATCH_LEVEL
1334 ==========================================================================
1336 BOOLEAN MlmeValidateSSID(
1337 IN PUCHAR pSsid,
1338 IN UCHAR SsidLen)
1340 int index;
1342 if (SsidLen > MAX_LEN_OF_SSID)
1343 return (FALSE);
1345 // Check each character value
1346 for (index = 0; index < SsidLen; index++)
1348 if (pSsid[index] < 0x20)
1349 return (FALSE);
1352 // All checked
1353 return (TRUE);
1356 VOID MlmeSelectTxRateTable(
1357 IN PRTMP_ADAPTER pAd,
1358 IN PMAC_TABLE_ENTRY pEntry,
1359 IN PUCHAR *ppTable,
1360 IN PUCHAR pTableSize,
1361 IN PUCHAR pInitTxRateIdx)
1365 // decide the rate table for tuning
1366 if (pAd->CommonCfg.TxRateTableSize > 0)
1368 *ppTable = RateSwitchTable;
1369 *pTableSize = RateSwitchTable[0];
1370 *pInitTxRateIdx = RateSwitchTable[1];
1372 break;
1375 if ((pAd->OpMode == OPMODE_STA) && ADHOC_ON(pAd))
1377 #ifdef DOT11_N_SUPPORT
1378 if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1379 !pAd->StaCfg.AdhocBOnlyJoined &&
1380 !pAd->StaCfg.AdhocBGJoined &&
1381 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1382 ((pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1)))
1383 {// 11N 1S Adhoc
1384 *ppTable = RateSwitchTable11N1S;
1385 *pTableSize = RateSwitchTable11N1S[0];
1386 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1389 else if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) &&
1390 !pAd->StaCfg.AdhocBOnlyJoined &&
1391 !pAd->StaCfg.AdhocBGJoined &&
1392 (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0xff) &&
1393 (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0xff) &&
1394 (pAd->Antenna.field.TxPath == 2))
1395 {// 11N 2S Adhoc
1396 if (pAd->LatchRfRegs.Channel <= 14)
1398 *ppTable = RateSwitchTable11N2S;
1399 *pTableSize = RateSwitchTable11N2S[0];
1400 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1402 else
1404 *ppTable = RateSwitchTable11N2SForABand;
1405 *pTableSize = RateSwitchTable11N2SForABand[0];
1406 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1410 else
1411 #endif // DOT11_N_SUPPORT //
1412 if (pAd->CommonCfg.PhyMode == PHY_11B)
1414 *ppTable = RateSwitchTable11B;
1415 *pTableSize = RateSwitchTable11B[0];
1416 *pInitTxRateIdx = RateSwitchTable11B[1];
1419 else if((pAd->LatchRfRegs.Channel <= 14) && (pAd->StaCfg.AdhocBOnlyJoined == TRUE))
1421 // USe B Table when Only b-only Station in my IBSS .
1422 *ppTable = RateSwitchTable11B;
1423 *pTableSize = RateSwitchTable11B[0];
1424 *pInitTxRateIdx = RateSwitchTable11B[1];
1427 else if (pAd->LatchRfRegs.Channel <= 14)
1429 *ppTable = RateSwitchTable11BG;
1430 *pTableSize = RateSwitchTable11BG[0];
1431 *pInitTxRateIdx = RateSwitchTable11BG[1];
1434 else
1436 *ppTable = RateSwitchTable11G;
1437 *pTableSize = RateSwitchTable11G[0];
1438 *pInitTxRateIdx = RateSwitchTable11G[1];
1441 break;
1444 #ifdef DOT11_N_SUPPORT
1445 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1446 ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1447 {// 11BGN 1S AP
1448 *ppTable = RateSwitchTable11BGN1S;
1449 *pTableSize = RateSwitchTable11BGN1S[0];
1450 *pInitTxRateIdx = RateSwitchTable11BGN1S[1];
1452 break;
1455 if ((pEntry->RateLen == 12) && (pEntry->HTCapability.MCSSet[0] == 0xff) &&
1456 (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1457 {// 11BGN 2S AP
1458 if (pAd->LatchRfRegs.Channel <= 14)
1460 *ppTable = RateSwitchTable11BGN2S;
1461 *pTableSize = RateSwitchTable11BGN2S[0];
1462 *pInitTxRateIdx = RateSwitchTable11BGN2S[1];
1465 else
1467 *ppTable = RateSwitchTable11BGN2SForABand;
1468 *pTableSize = RateSwitchTable11BGN2SForABand[0];
1469 *pInitTxRateIdx = RateSwitchTable11BGN2SForABand[1];
1472 break;
1475 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && ((pEntry->HTCapability.MCSSet[1] == 0x00) || (pAd->CommonCfg.TxStream == 1)))
1476 {// 11N 1S AP
1477 *ppTable = RateSwitchTable11N1S;
1478 *pTableSize = RateSwitchTable11N1S[0];
1479 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1481 break;
1484 if ((pEntry->HTCapability.MCSSet[0] == 0xff) && (pEntry->HTCapability.MCSSet[1] == 0xff) && (pAd->CommonCfg.TxStream == 2))
1485 {// 11N 2S AP
1486 if (pAd->LatchRfRegs.Channel <= 14)
1488 *ppTable = RateSwitchTable11N2S;
1489 *pTableSize = RateSwitchTable11N2S[0];
1490 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1492 else
1494 *ppTable = RateSwitchTable11N2SForABand;
1495 *pTableSize = RateSwitchTable11N2SForABand[0];
1496 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1499 break;
1501 #endif // DOT11_N_SUPPORT //
1502 //else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1503 if ((pEntry->RateLen == 4)
1504 #ifdef DOT11_N_SUPPORT
1505 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1506 #endif // DOT11_N_SUPPORT //
1508 {// B only AP
1509 *ppTable = RateSwitchTable11B;
1510 *pTableSize = RateSwitchTable11B[0];
1511 *pInitTxRateIdx = RateSwitchTable11B[1];
1513 break;
1516 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1517 if ((pEntry->RateLen > 8)
1518 #ifdef DOT11_N_SUPPORT
1519 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1520 #endif // DOT11_N_SUPPORT //
1522 {// B/G mixed AP
1523 *ppTable = RateSwitchTable11BG;
1524 *pTableSize = RateSwitchTable11BG[0];
1525 *pInitTxRateIdx = RateSwitchTable11BG[1];
1527 break;
1530 //else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1531 if ((pEntry->RateLen == 8)
1532 #ifdef DOT11_N_SUPPORT
1533 && (pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0)
1534 #endif // DOT11_N_SUPPORT //
1536 {// G only AP
1537 *ppTable = RateSwitchTable11G;
1538 *pTableSize = RateSwitchTable11G[0];
1539 *pInitTxRateIdx = RateSwitchTable11G[1];
1541 break;
1543 #ifdef DOT11_N_SUPPORT
1544 #endif // DOT11_N_SUPPORT //
1546 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1548 #ifdef DOT11_N_SUPPORT
1549 //else if ((pAd->StaActive.SupportedPhyInfo.MCSSet[0] == 0) && (pAd->StaActive.SupportedPhyInfo.MCSSet[1] == 0))
1550 if ((pEntry->HTCapability.MCSSet[0] == 0) && (pEntry->HTCapability.MCSSet[1] == 0))
1551 #endif // DOT11_N_SUPPORT //
1552 { // Legacy mode
1553 if (pAd->CommonCfg.MaxTxRate <= RATE_11)
1555 *ppTable = RateSwitchTable11B;
1556 *pTableSize = RateSwitchTable11B[0];
1557 *pInitTxRateIdx = RateSwitchTable11B[1];
1559 else if ((pAd->CommonCfg.MaxTxRate > RATE_11) && (pAd->CommonCfg.MinTxRate > RATE_11))
1561 *ppTable = RateSwitchTable11G;
1562 *pTableSize = RateSwitchTable11G[0];
1563 *pInitTxRateIdx = RateSwitchTable11G[1];
1566 else
1568 *ppTable = RateSwitchTable11BG;
1569 *pTableSize = RateSwitchTable11BG[0];
1570 *pInitTxRateIdx = RateSwitchTable11BG[1];
1572 break;
1574 #ifdef DOT11_N_SUPPORT
1575 if (pAd->LatchRfRegs.Channel <= 14)
1577 if (pAd->CommonCfg.TxStream == 1)
1579 *ppTable = RateSwitchTable11N1S;
1580 *pTableSize = RateSwitchTable11N1S[0];
1581 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1582 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1584 else
1586 *ppTable = RateSwitchTable11N2S;
1587 *pTableSize = RateSwitchTable11N2S[0];
1588 *pInitTxRateIdx = RateSwitchTable11N2S[1];
1589 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1592 else
1594 if (pAd->CommonCfg.TxStream == 1)
1596 *ppTable = RateSwitchTable11N1S;
1597 *pTableSize = RateSwitchTable11N1S[0];
1598 *pInitTxRateIdx = RateSwitchTable11N1S[1];
1599 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 1S AP \n"));
1601 else
1603 *ppTable = RateSwitchTable11N2SForABand;
1604 *pTableSize = RateSwitchTable11N2SForABand[0];
1605 *pInitTxRateIdx = RateSwitchTable11N2SForABand[1];
1606 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode,default use 11N 2S AP \n"));
1609 #endif // DOT11_N_SUPPORT //
1610 DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode (SupRateLen=%d, ExtRateLen=%d, MCSSet[0]=0x%x, MCSSet[1]=0x%x)\n",
1611 pAd->StaActive.SupRateLen, pAd->StaActive.ExtRateLen, pAd->StaActive.SupportedPhyInfo.MCSSet[0], pAd->StaActive.SupportedPhyInfo.MCSSet[1]));
1613 } while(FALSE);
1617 ==========================================================================
1618 Description:
1619 This routine checks if there're other APs out there capable for
1620 roaming. Caller should call this routine only when Link up in INFRA mode
1621 and channel quality is below CQI_GOOD_THRESHOLD.
1623 IRQL = DISPATCH_LEVEL
1625 Output:
1626 ==========================================================================
1628 VOID MlmeCheckForRoaming(
1629 IN PRTMP_ADAPTER pAd,
1630 IN ULONG Now32)
1632 USHORT i;
1633 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1634 BSS_ENTRY *pBss;
1636 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForRoaming\n"));
1637 // put all roaming candidates into RoamTab, and sort in RSSI order
1638 BssTableInit(pRoamTab);
1639 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1641 pBss = &pAd->ScanTab.BssEntry[i];
1643 if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32)
1644 continue; // AP disappear
1645 if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING)
1646 continue; // RSSI too weak. forget it.
1647 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1648 continue; // skip current AP
1649 if (pBss->Rssi < (pAd->StaCfg.RssiSample.LastRssi0 + RSSI_DELTA))
1650 continue; // only AP with stronger RSSI is eligible for roaming
1652 // AP passing all above rules is put into roaming candidate table
1653 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1654 pRoamTab->BssNr += 1;
1657 if (pRoamTab->BssNr > 0)
1659 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1660 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1662 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1663 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1664 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1665 RT28XX_MLME_HANDLER(pAd);
1668 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr));
1672 ==========================================================================
1673 Description:
1674 This routine checks if there're other APs out there capable for
1675 roaming. Caller should call this routine only when link up in INFRA mode
1676 and channel quality is below CQI_GOOD_THRESHOLD.
1678 IRQL = DISPATCH_LEVEL
1680 Output:
1681 ==========================================================================
1683 VOID MlmeCheckForFastRoaming(
1684 IN PRTMP_ADAPTER pAd,
1685 IN ULONG Now)
1687 USHORT i;
1688 BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab;
1689 BSS_ENTRY *pBss;
1691 DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n"));
1692 // put all roaming candidates into RoamTab, and sort in RSSI order
1693 BssTableInit(pRoamTab);
1694 for (i = 0; i < pAd->ScanTab.BssNr; i++)
1696 pBss = &pAd->ScanTab.BssEntry[i];
1698 if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel))
1699 continue; // RSSI too weak. forget it.
1700 if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid))
1701 continue; // skip current AP
1702 if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen))
1703 continue; // skip different SSID
1704 if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA))
1705 continue; // skip AP without better RSSI
1707 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));
1708 // AP passing all above rules is put into roaming candidate table
1709 NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY));
1710 pRoamTab->BssNr += 1;
1713 if (pRoamTab->BssNr > 0)
1715 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1716 if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE)
1718 pAd->RalinkCounters.PoorCQIRoamingCount ++;
1719 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount));
1720 MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL);
1721 RT28XX_MLME_HANDLER(pAd);
1724 // Maybe site survey required
1725 else
1727 if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now)
1729 // check CntlMachine.CurrState to avoid collision with NDIS SetOID request
1730 DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n"));
1731 pAd->StaCfg.ScanCnt = 2;
1732 pAd->StaCfg.LastScanTime = Now;
1733 MlmeAutoScan(pAd);
1737 DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));
1741 ==========================================================================
1742 Description:
1743 This routine calculates TxPER, RxPER of the past N-sec period. And
1744 according to the calculation result, ChannelQuality is calculated here
1745 to decide if current AP is still doing the job.
1747 If ChannelQuality is not good, a ROAMing attempt may be tried later.
1748 Output:
1749 StaCfg.ChannelQuality - 0..100
1751 IRQL = DISPATCH_LEVEL
1753 NOTE: This routine decide channle quality based on RX CRC error ratio.
1754 Caller should make sure a function call to NICUpdateRawCounters(pAd)
1755 is performed right before this routine, so that this routine can decide
1756 channel quality based on the most up-to-date information
1757 ==========================================================================
1759 VOID MlmeCalculateChannelQuality(
1760 IN PRTMP_ADAPTER pAd,
1761 IN ULONG Now32)
1763 ULONG TxOkCnt, TxCnt, TxPER, TxPRR;
1764 ULONG RxCnt, RxPER;
1765 UCHAR NorRssi;
1766 CHAR MaxRssi;
1767 ULONG BeaconLostTime = BEACON_LOST_TIME;
1769 MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2);
1772 // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics
1774 TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount;
1775 TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount;
1776 if (TxCnt < 5)
1778 TxPER = 0;
1779 TxPRR = 0;
1781 else
1783 TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt;
1784 TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt;
1788 // calculate RX PER - don't take RxPER into consideration if too few sample
1790 RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt;
1791 if (RxCnt < 5)
1792 RxPER = 0;
1793 else
1794 RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt;
1797 // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER
1799 if (INFRA_ON(pAd) &&
1800 (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic
1801 (pAd->StaCfg.LastBeaconRxTime + BeaconLostTime < Now32))
1803 DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %ld msec with TxOkCnt=%ld -> CQI=0\n", BeaconLostTime, TxOkCnt));
1804 pAd->Mlme.ChannelQuality = 0;
1806 else
1808 // Normalize Rssi
1809 if (MaxRssi > -40)
1810 NorRssi = 100;
1811 else if (MaxRssi < -90)
1812 NorRssi = 0;
1813 else
1814 NorRssi = (MaxRssi + 90) * 2;
1816 // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0)
1817 pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi +
1818 TX_WEIGHTING * (100 - TxPRR) +
1819 RX_WEIGHTING* (100 - RxPER)) / 100;
1820 if (pAd->Mlme.ChannelQuality >= 100)
1821 pAd->Mlme.ChannelQuality = 100;
1826 VOID MlmeSetTxRate(
1827 IN PRTMP_ADAPTER pAd,
1828 IN PMAC_TABLE_ENTRY pEntry,
1829 IN PRTMP_TX_RATE_SWITCH pTxRate)
1831 UCHAR MaxMode = MODE_OFDM;
1833 #ifdef DOT11_N_SUPPORT
1834 MaxMode = MODE_HTGREENFIELD;
1836 if (pTxRate->STBC && (pAd->StaCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2))
1837 pAd->StaCfg.HTPhyMode.field.STBC = STBC_USE;
1838 else
1839 #endif // DOT11_N_SUPPORT //
1840 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1842 if (pTxRate->CurrMCS < MCS_AUTO)
1843 pAd->StaCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS;
1845 if (pAd->StaCfg.HTPhyMode.field.MCS > 7)
1846 pAd->StaCfg.HTPhyMode.field.STBC = STBC_NONE;
1848 if (ADHOC_ON(pAd))
1850 // If peer adhoc is b-only mode, we can't send 11g rate.
1851 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1852 pEntry->HTPhyMode.field.STBC = STBC_NONE;
1855 // For Adhoc MODE_CCK, driver will use AdhocBOnlyJoined flag to roll back to B only if necessary
1857 pEntry->HTPhyMode.field.MODE = pTxRate->Mode;
1858 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1859 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1861 // Patch speed error in status page
1862 pAd->StaCfg.HTPhyMode.field.MODE = pEntry->HTPhyMode.field.MODE;
1864 else
1866 if (pTxRate->Mode <= MaxMode)
1867 pAd->StaCfg.HTPhyMode.field.MODE = pTxRate->Mode;
1869 #ifdef DOT11_N_SUPPORT
1870 if (pTxRate->ShortGI && (pAd->StaCfg.MaxHTPhyMode.field.ShortGI))
1871 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_400;
1872 else
1873 #endif // DOT11_N_SUPPORT //
1874 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1876 #ifdef DOT11_N_SUPPORT
1877 // Reexam each bandwidth's SGI support.
1878 if (pAd->StaCfg.HTPhyMode.field.ShortGI == GI_400)
1880 if ((pEntry->HTPhyMode.field.BW == BW_20) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI20_CAPABLE)))
1881 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1882 if ((pEntry->HTPhyMode.field.BW == BW_40) && (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SGI40_CAPABLE)))
1883 pAd->StaCfg.HTPhyMode.field.ShortGI = GI_800;
1886 // Turn RTS/CTS rate to 6Mbps.
1887 if ((pEntry->HTPhyMode.field.MCS == 0) && (pAd->StaCfg.HTPhyMode.field.MCS != 0))
1889 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1890 if (pAd->MacTab.fAnyBASession)
1892 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1894 else
1896 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1899 else if ((pEntry->HTPhyMode.field.MCS == 8) && (pAd->StaCfg.HTPhyMode.field.MCS != 8))
1901 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1902 if (pAd->MacTab.fAnyBASession)
1904 AsicUpdateProtect(pAd, HT_FORCERTSCTS, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1906 else
1908 AsicUpdateProtect(pAd, pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1911 else if ((pEntry->HTPhyMode.field.MCS != 0) && (pAd->StaCfg.HTPhyMode.field.MCS == 0))
1913 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1916 else if ((pEntry->HTPhyMode.field.MCS != 8) && (pAd->StaCfg.HTPhyMode.field.MCS == 8))
1918 AsicUpdateProtect(pAd, HT_RTSCTS_6M, ALLN_SETPROTECT, TRUE, (BOOLEAN)pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent);
1920 #endif // DOT11_N_SUPPORT //
1922 pEntry->HTPhyMode.field.STBC = pAd->StaCfg.HTPhyMode.field.STBC;
1923 pEntry->HTPhyMode.field.ShortGI = pAd->StaCfg.HTPhyMode.field.ShortGI;
1924 pEntry->HTPhyMode.field.MCS = pAd->StaCfg.HTPhyMode.field.MCS;
1925 pEntry->HTPhyMode.field.MODE = pAd->StaCfg.HTPhyMode.field.MODE;
1926 #ifdef DOT11_N_SUPPORT
1927 if ((pAd->StaCfg.MaxHTPhyMode.field.MODE == MODE_HTGREENFIELD) &&
1928 pAd->WIFItestbed.bGreenField)
1929 pEntry->HTPhyMode.field.MODE = MODE_HTGREENFIELD;
1930 #endif // DOT11_N_SUPPORT //
1933 pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word);
1937 ==========================================================================
1938 Description:
1939 This routine calculates the acumulated TxPER of eaxh TxRate. And
1940 according to the calculation result, change CommonCfg.TxRate which
1941 is the stable TX Rate we expect the Radio situation could sustained.
1943 CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate}
1944 Output:
1945 CommonCfg.TxRate -
1947 IRQL = DISPATCH_LEVEL
1949 NOTE:
1950 call this routine every second
1951 ==========================================================================
1953 VOID MlmeDynamicTxRateSwitching(
1954 IN PRTMP_ADAPTER pAd)
1956 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx;
1957 ULONG i, AccuTxTotalCnt = 0, TxTotalCnt;
1958 ULONG TxErrorRatio = 0;
1959 BOOLEAN bTxRateChanged, bUpgradeQuality = FALSE;
1960 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
1961 PUCHAR pTable;
1962 UCHAR TableSize = 0;
1963 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
1964 CHAR Rssi, RssiOffset = 0;
1965 TX_STA_CNT1_STRUC StaTx1;
1966 TX_STA_CNT0_STRUC TxStaCnt0;
1967 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
1968 MAC_TABLE_ENTRY *pEntry;
1970 /*if (pAd->Antenna.field.RxPath > 1)
1971 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
1972 else
1973 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;*/
1976 // walk through MAC table, see if need to change AP's TX rate toward each entry
1978 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
1980 pEntry = &pAd->MacTab.Content[i];
1982 // check if this entry need to switch rate automatically
1983 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
1984 continue;
1986 if ((pAd->MacTab.Size == 1) || (pEntry->ValidAsDls))
1988 Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.RssiSample.AvgRssi0, (CHAR)pAd->StaCfg.RssiSample.AvgRssi1, (CHAR)pAd->StaCfg.RssiSample.AvgRssi2);
1990 // Update statistic counter
1991 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
1992 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
1993 pAd->bUpdateBcnCntDone = TRUE;
1994 TxRetransmit = StaTx1.field.TxRetransmit;
1995 TxSuccess = StaTx1.field.TxSuccess;
1996 TxFailCount = TxStaCnt0.field.TxFailCount;
1997 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
1999 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2000 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2001 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2002 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2003 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2004 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2006 // if no traffic in the past 1-sec period, don't change TX rate,
2007 // but clear all bad history. because the bad history may affect the next
2008 // Chariot throughput test
2009 AccuTxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
2010 pAd->RalinkCounters.OneSecTxRetryOkCount +
2011 pAd->RalinkCounters.OneSecTxFailCount;
2013 if (TxTotalCnt)
2014 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2016 else
2018 Rssi = RTMPMaxRssi(pAd, (CHAR)pEntry->RssiSample.AvgRssi0, (CHAR)pEntry->RssiSample.AvgRssi1, (CHAR)pEntry->RssiSample.AvgRssi2);
2020 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2021 pEntry->OneSecTxRetryOkCount +
2022 pEntry->OneSecTxFailCount;
2024 if (TxTotalCnt)
2025 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2028 CurrRateIdx = pEntry->CurrTxRateIndex;
2030 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2032 if (CurrRateIdx >= TableSize)
2034 CurrRateIdx = TableSize - 1;
2037 // When switch from Fixed rate -> auto rate, the REAL TX rate might be different from pAd->CommonCfg.TxRateIndex.
2038 // So need to sync here.
2039 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2040 if ((pEntry->HTPhyMode.field.MCS != pCurrTxRate->CurrMCS)
2041 //&& (pAd->StaCfg.bAutoTxRateSwitch == TRUE)
2045 // Need to sync Real Tx rate and our record.
2046 // Then return for next DRS.
2047 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(InitTxRateIdx+1)*5];
2048 pEntry->CurrTxRateIndex = InitTxRateIdx;
2049 MlmeSetTxRate(pAd, pEntry, pCurrTxRate);
2051 // reset all OneSecTx counters
2052 RESET_ONE_SEC_TX_CNT(pEntry);
2053 continue;
2056 // decide the next upgrade rate and downgrade rate, if any
2057 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2059 UpRateIdx = CurrRateIdx + 1;
2060 DownRateIdx = CurrRateIdx -1;
2062 else if (CurrRateIdx == 0)
2064 UpRateIdx = CurrRateIdx + 1;
2065 DownRateIdx = CurrRateIdx;
2067 else if (CurrRateIdx == (TableSize - 1))
2069 UpRateIdx = CurrRateIdx;
2070 DownRateIdx = CurrRateIdx - 1;
2073 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2075 #ifdef DOT11_N_SUPPORT
2076 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2078 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2079 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2081 else
2082 #endif // DOT11_N_SUPPORT //
2084 TrainUp = pCurrTxRate->TrainUp;
2085 TrainDown = pCurrTxRate->TrainDown;
2088 //pAd->DrsCounters.LastTimeTxRateChangeAction = pAd->DrsCounters.LastSecTxRateChangeAction;
2091 // Keep the last time TxRateChangeAction status.
2093 pEntry->LastTimeTxRateChangeAction = pEntry->LastSecTxRateChangeAction;
2098 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2099 // (criteria copied from RT2500 for Netopia case)
2101 if (TxTotalCnt <= 15)
2103 CHAR idx = 0;
2104 UCHAR TxRateIdx;
2105 //UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS7 = 0, MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2106 UCHAR MCS0 = 0, MCS1 = 0, MCS2 = 0, MCS3 = 0, MCS4 = 0, MCS5 =0, MCS6 = 0, MCS7 = 0;
2107 UCHAR MCS12 = 0, MCS13 = 0, MCS14 = 0, MCS15 = 0;
2108 UCHAR MCS20 = 0, MCS21 = 0, MCS22 = 0, MCS23 = 0; // 3*3
2110 // check the existence and index of each needed MCS
2111 while (idx < pTable[0])
2113 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(idx+1)*5];
2115 if (pCurrTxRate->CurrMCS == MCS_0)
2117 MCS0 = idx;
2119 else if (pCurrTxRate->CurrMCS == MCS_1)
2121 MCS1 = idx;
2123 else if (pCurrTxRate->CurrMCS == MCS_2)
2125 MCS2 = idx;
2127 else if (pCurrTxRate->CurrMCS == MCS_3)
2129 MCS3 = idx;
2131 else if (pCurrTxRate->CurrMCS == MCS_4)
2133 MCS4 = idx;
2135 else if (pCurrTxRate->CurrMCS == MCS_5)
2137 MCS5 = idx;
2139 else if (pCurrTxRate->CurrMCS == MCS_6)
2141 MCS6 = idx;
2143 //else if (pCurrTxRate->CurrMCS == MCS_7)
2144 else if ((pCurrTxRate->CurrMCS == MCS_7) && (pCurrTxRate->ShortGI == GI_800)) // prevent the highest MCS using short GI when 1T and low throughput
2146 MCS7 = idx;
2148 else if (pCurrTxRate->CurrMCS == MCS_12)
2150 MCS12 = idx;
2152 else if (pCurrTxRate->CurrMCS == MCS_13)
2154 MCS13 = idx;
2156 else if (pCurrTxRate->CurrMCS == MCS_14)
2158 MCS14 = idx;
2160 //else if ((pCurrTxRate->CurrMCS == MCS_15)/* && (pCurrTxRate->ShortGI == GI_800)*/) //we hope to use ShortGI as initial rate
2161 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
2163 MCS15 = idx;
2165 else if (pCurrTxRate->CurrMCS == MCS_20) // 3*3
2167 MCS20 = idx;
2169 else if (pCurrTxRate->CurrMCS == MCS_21)
2171 MCS21 = idx;
2173 else if (pCurrTxRate->CurrMCS == MCS_22)
2175 MCS22 = idx;
2177 else if (pCurrTxRate->CurrMCS == MCS_23)
2179 MCS23 = idx;
2181 idx ++;
2184 if (pAd->LatchRfRegs.Channel <= 14)
2186 if (pAd->NicConfig2.field.ExternalLNAForG)
2188 RssiOffset = 2;
2190 else
2192 RssiOffset = 5;
2195 else
2197 if (pAd->NicConfig2.field.ExternalLNAForA)
2199 RssiOffset = 5;
2201 else
2203 RssiOffset = 8;
2206 #ifdef DOT11_N_SUPPORT
2207 /*if (MCS15)*/
2208 if ((pTable == RateSwitchTable11BGN3S) ||
2209 (pTable == RateSwitchTable11N3S) ||
2210 (pTable == RateSwitchTable))
2211 {// N mode with 3 stream // 3*3
2212 if (MCS23 && (Rssi >= -70))
2213 TxRateIdx = MCS15;
2214 else if (MCS22 && (Rssi >= -72))
2215 TxRateIdx = MCS14;
2216 else if (MCS21 && (Rssi >= -76))
2217 TxRateIdx = MCS13;
2218 else if (MCS20 && (Rssi >= -78))
2219 TxRateIdx = MCS12;
2220 else if (MCS4 && (Rssi >= -82))
2221 TxRateIdx = MCS4;
2222 else if (MCS3 && (Rssi >= -84))
2223 TxRateIdx = MCS3;
2224 else if (MCS2 && (Rssi >= -86))
2225 TxRateIdx = MCS2;
2226 else if (MCS1 && (Rssi >= -88))
2227 TxRateIdx = MCS1;
2228 else
2229 TxRateIdx = MCS0;
2231 else if ((pTable == RateSwitchTable11BGN2S) || (pTable == RateSwitchTable11BGN2SForABand) ||(pTable == RateSwitchTable11N2S) ||(pTable == RateSwitchTable11N2SForABand)) // 3*3
2232 {// N mode with 2 stream
2233 if (MCS15 && (Rssi >= (-70+RssiOffset)))
2234 TxRateIdx = MCS15;
2235 else if (MCS14 && (Rssi >= (-72+RssiOffset)))
2236 TxRateIdx = MCS14;
2237 else if (MCS13 && (Rssi >= (-76+RssiOffset)))
2238 TxRateIdx = MCS13;
2239 else if (MCS12 && (Rssi >= (-78+RssiOffset)))
2240 TxRateIdx = MCS12;
2241 else if (MCS4 && (Rssi >= (-82+RssiOffset)))
2242 TxRateIdx = MCS4;
2243 else if (MCS3 && (Rssi >= (-84+RssiOffset)))
2244 TxRateIdx = MCS3;
2245 else if (MCS2 && (Rssi >= (-86+RssiOffset)))
2246 TxRateIdx = MCS2;
2247 else if (MCS1 && (Rssi >= (-88+RssiOffset)))
2248 TxRateIdx = MCS1;
2249 else
2250 TxRateIdx = MCS0;
2252 else if ((pTable == RateSwitchTable11BGN1S) || (pTable == RateSwitchTable11N1S))
2253 {// N mode with 1 stream
2254 if (MCS7 && (Rssi > (-72+RssiOffset)))
2255 TxRateIdx = MCS7;
2256 else if (MCS6 && (Rssi > (-74+RssiOffset)))
2257 TxRateIdx = MCS6;
2258 else if (MCS5 && (Rssi > (-77+RssiOffset)))
2259 TxRateIdx = MCS5;
2260 else if (MCS4 && (Rssi > (-79+RssiOffset)))
2261 TxRateIdx = MCS4;
2262 else if (MCS3 && (Rssi > (-81+RssiOffset)))
2263 TxRateIdx = MCS3;
2264 else if (MCS2 && (Rssi > (-83+RssiOffset)))
2265 TxRateIdx = MCS2;
2266 else if (MCS1 && (Rssi > (-86+RssiOffset)))
2267 TxRateIdx = MCS1;
2268 else
2269 TxRateIdx = MCS0;
2271 else
2272 #endif // DOT11_N_SUPPORT //
2273 {// Legacy mode
2274 if (MCS7 && (Rssi > -70))
2275 TxRateIdx = MCS7;
2276 else if (MCS6 && (Rssi > -74))
2277 TxRateIdx = MCS6;
2278 else if (MCS5 && (Rssi > -78))
2279 TxRateIdx = MCS5;
2280 else if (MCS4 && (Rssi > -82))
2281 TxRateIdx = MCS4;
2282 else if (MCS4 == 0) // for B-only mode
2283 TxRateIdx = MCS3;
2284 else if (MCS3 && (Rssi > -85))
2285 TxRateIdx = MCS3;
2286 else if (MCS2 && (Rssi > -87))
2287 TxRateIdx = MCS2;
2288 else if (MCS1 && (Rssi > -90))
2289 TxRateIdx = MCS1;
2290 else
2291 TxRateIdx = MCS0;
2295 pEntry->CurrTxRateIndex = TxRateIdx;
2296 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2297 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2300 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2301 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2302 pEntry->fLastSecAccordingRSSI = TRUE;
2303 // reset all OneSecTx counters
2304 RESET_ONE_SEC_TX_CNT(pEntry);
2306 continue;
2309 if (pEntry->fLastSecAccordingRSSI == TRUE)
2311 pEntry->fLastSecAccordingRSSI = FALSE;
2312 pEntry->LastSecTxRateChangeAction = 0;
2313 // reset all OneSecTx counters
2314 RESET_ONE_SEC_TX_CNT(pEntry);
2316 continue;
2321 BOOLEAN bTrainUpDown = FALSE;
2323 pEntry->CurrTxRateStableTime ++;
2325 // downgrade TX quality if PER >= Rate-Down threshold
2326 if (TxErrorRatio >= TrainDown)
2328 bTrainUpDown = TRUE;
2329 pEntry->TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2331 // upgrade TX quality if PER <= Rate-Up threshold
2332 else if (TxErrorRatio <= TrainUp)
2334 bTrainUpDown = TRUE;
2335 bUpgradeQuality = TRUE;
2336 if (pEntry->TxQuality[CurrRateIdx])
2337 pEntry->TxQuality[CurrRateIdx] --; // quality very good in CurrRate
2339 if (pEntry->TxRateUpPenalty)
2340 pEntry->TxRateUpPenalty --;
2341 else if (pEntry->TxQuality[UpRateIdx])
2342 pEntry->TxQuality[UpRateIdx] --; // may improve next UP rate's quality
2345 pEntry->PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2347 if (bTrainUpDown)
2349 // perform DRS - consider TxRate Down first, then rate up.
2350 if ((CurrRateIdx != DownRateIdx) && (pEntry->TxQuality[CurrRateIdx] >= DRS_TX_QUALITY_WORST_BOUND))
2352 pEntry->CurrTxRateIndex = DownRateIdx;
2354 else if ((CurrRateIdx != UpRateIdx) && (pEntry->TxQuality[UpRateIdx] <= 0))
2356 pEntry->CurrTxRateIndex = UpRateIdx;
2359 } while (FALSE);
2361 // if rate-up happen, clear all bad history of all TX rates
2362 if (pEntry->CurrTxRateIndex > CurrRateIdx)
2364 pEntry->CurrTxRateStableTime = 0;
2365 pEntry->TxRateUpPenalty = 0;
2366 pEntry->LastSecTxRateChangeAction = 1; // rate UP
2367 NdisZeroMemory(pEntry->TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2368 NdisZeroMemory(pEntry->PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2371 // For TxRate fast train up
2373 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2375 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2377 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2379 bTxRateChanged = TRUE;
2381 // if rate-down happen, only clear DownRate's bad history
2382 else if (pEntry->CurrTxRateIndex < CurrRateIdx)
2384 pEntry->CurrTxRateStableTime = 0;
2385 pEntry->TxRateUpPenalty = 0; // no penalty
2386 pEntry->LastSecTxRateChangeAction = 2; // rate DOWN
2387 pEntry->TxQuality[pEntry->CurrTxRateIndex] = 0;
2388 pEntry->PER[pEntry->CurrTxRateIndex] = 0;
2391 // For TxRate fast train down
2393 if (!pAd->StaCfg.StaQuickResponeForRateUpTimerRunning)
2395 RTMPSetTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, 100);
2397 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = TRUE;
2399 bTxRateChanged = TRUE;
2401 else
2403 pEntry->LastSecTxRateChangeAction = 0; // rate no change
2404 bTxRateChanged = FALSE;
2407 pEntry->LastTxOkCount = TxSuccess;
2409 // reset all OneSecTx counters
2410 RESET_ONE_SEC_TX_CNT(pEntry);
2412 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pEntry->CurrTxRateIndex+1)*5];
2413 if (bTxRateChanged && pNextTxRate)
2415 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2421 ========================================================================
2422 Routine Description:
2423 Station side, Auto TxRate faster train up timer call back function.
2425 Arguments:
2426 SystemSpecific1 - Not used.
2427 FunctionContext - Pointer to our Adapter context.
2428 SystemSpecific2 - Not used.
2429 SystemSpecific3 - Not used.
2431 Return Value:
2432 None
2434 ========================================================================
2436 VOID StaQuickResponeForRateUpExec(
2437 IN PVOID SystemSpecific1,
2438 IN PVOID FunctionContext,
2439 IN PVOID SystemSpecific2,
2440 IN PVOID SystemSpecific3)
2442 PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
2443 UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx = 0;
2444 ULONG TxTotalCnt;
2445 ULONG TxErrorRatio = 0;
2446 BOOLEAN bTxRateChanged = TRUE; //, bUpgradeQuality = FALSE;
2447 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL;
2448 PUCHAR pTable;
2449 UCHAR TableSize = 0;
2450 UCHAR InitTxRateIdx = 0, TrainUp, TrainDown;
2451 TX_STA_CNT1_STRUC StaTx1;
2452 TX_STA_CNT0_STRUC TxStaCnt0;
2453 CHAR Rssi, ratio;
2454 ULONG TxRetransmit = 0, TxSuccess = 0, TxFailCount = 0;
2455 MAC_TABLE_ENTRY *pEntry;
2456 ULONG i;
2458 pAd->StaCfg.StaQuickResponeForRateUpTimerRunning = FALSE;
2461 // walk through MAC table, see if need to change AP's TX rate toward each entry
2463 for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++)
2465 pEntry = &pAd->MacTab.Content[i];
2467 // check if this entry need to switch rate automatically
2468 if (RTMPCheckEntryEnableAutoRateSwitch(pAd, pEntry) == FALSE)
2469 continue;
2471 //Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2);
2472 if (pAd->Antenna.field.TxPath > 1)
2473 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
2474 else
2475 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
2477 CurrRateIdx = pAd->CommonCfg.TxRateIndex;
2479 MlmeSelectTxRateTable(pAd, pEntry, &pTable, &TableSize, &InitTxRateIdx);
2481 // decide the next upgrade rate and downgrade rate, if any
2482 if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1)))
2484 UpRateIdx = CurrRateIdx + 1;
2485 DownRateIdx = CurrRateIdx -1;
2487 else if (CurrRateIdx == 0)
2489 UpRateIdx = CurrRateIdx + 1;
2490 DownRateIdx = CurrRateIdx;
2492 else if (CurrRateIdx == (TableSize - 1))
2494 UpRateIdx = CurrRateIdx;
2495 DownRateIdx = CurrRateIdx - 1;
2498 pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5];
2500 #ifdef DOT11_N_SUPPORT
2501 if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX))
2503 TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1));
2504 TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1));
2506 else
2507 #endif // DOT11_N_SUPPORT //
2509 TrainUp = pCurrTxRate->TrainUp;
2510 TrainDown = pCurrTxRate->TrainDown;
2513 if (pAd->MacTab.Size == 1)
2515 // Update statistic counter
2516 RTMP_IO_READ32(pAd, TX_STA_CNT0, &TxStaCnt0.word);
2517 RTMP_IO_READ32(pAd, TX_STA_CNT1, &StaTx1.word);
2519 TxRetransmit = StaTx1.field.TxRetransmit;
2520 TxSuccess = StaTx1.field.TxSuccess;
2521 TxFailCount = TxStaCnt0.field.TxFailCount;
2522 TxTotalCnt = TxRetransmit + TxSuccess + TxFailCount;
2524 pAd->RalinkCounters.OneSecTxRetryOkCount += StaTx1.field.TxRetransmit;
2525 pAd->RalinkCounters.OneSecTxNoRetryOkCount += StaTx1.field.TxSuccess;
2526 pAd->RalinkCounters.OneSecTxFailCount += TxStaCnt0.field.TxFailCount;
2527 pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += StaTx1.field.TxSuccess;
2528 pAd->WlanCounters.RetryCount.u.LowPart += StaTx1.field.TxRetransmit;
2529 pAd->WlanCounters.FailedCount.u.LowPart += TxStaCnt0.field.TxFailCount;
2531 if (TxTotalCnt)
2532 TxErrorRatio = ((TxRetransmit + TxFailCount) * 100) / TxTotalCnt;
2534 else
2536 TxTotalCnt = pEntry->OneSecTxNoRetryOkCount +
2537 pEntry->OneSecTxRetryOkCount +
2538 pEntry->OneSecTxFailCount;
2540 if (TxTotalCnt)
2541 TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) * 100) / TxTotalCnt;
2546 // CASE 1. when TX samples are fewer than 15, then decide TX rate solely on RSSI
2547 // (criteria copied from RT2500 for Netopia case)
2549 if (TxTotalCnt <= 12)
2551 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2552 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2554 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2556 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2557 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2559 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2561 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2564 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: TxTotalCnt <= 15, train back to original rate \n"));
2565 return;
2570 ULONG OneSecTxNoRetryOKRationCount;
2572 if (pAd->DrsCounters.LastTimeTxRateChangeAction == 0)
2573 ratio = 5;
2574 else
2575 ratio = 4;
2577 // downgrade TX quality if PER >= Rate-Down threshold
2578 if (TxErrorRatio >= TrainDown)
2580 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2583 pAd->DrsCounters.PER[CurrRateIdx] = (UCHAR)TxErrorRatio;
2585 OneSecTxNoRetryOKRationCount = (TxSuccess * ratio);
2587 // perform DRS - consider TxRate Down first, then rate up.
2588 if ((pAd->DrsCounters.LastSecTxRateChangeAction == 1) && (CurrRateIdx != DownRateIdx))
2590 if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2592 pAd->CommonCfg.TxRateIndex = DownRateIdx;
2593 pAd->DrsCounters.TxQuality[CurrRateIdx] = DRS_TX_QUALITY_WORST_BOUND;
2598 else if ((pAd->DrsCounters.LastSecTxRateChangeAction == 2) && (CurrRateIdx != UpRateIdx))
2600 if ((TxErrorRatio >= 50) || (TxErrorRatio >= TrainDown))
2604 else if ((pAd->DrsCounters.LastTxOkCount + 2) >= OneSecTxNoRetryOKRationCount)
2606 pAd->CommonCfg.TxRateIndex = UpRateIdx;
2609 }while (FALSE);
2611 // if rate-up happen, clear all bad history of all TX rates
2612 if (pAd->CommonCfg.TxRateIndex > CurrRateIdx)
2614 pAd->DrsCounters.TxRateUpPenalty = 0;
2615 NdisZeroMemory(pAd->DrsCounters.TxQuality, sizeof(USHORT) * MAX_STEP_OF_TX_RATE_SWITCH);
2616 NdisZeroMemory(pAd->DrsCounters.PER, sizeof(UCHAR) * MAX_STEP_OF_TX_RATE_SWITCH);
2618 // if rate-down happen, only clear DownRate's bad history
2619 else if (pAd->CommonCfg.TxRateIndex < CurrRateIdx)
2621 DBGPRINT_RAW(RT_DEBUG_TRACE,("QuickDRS: --TX rate from %d to %d \n", CurrRateIdx, pAd->CommonCfg.TxRateIndex));
2623 pAd->DrsCounters.TxRateUpPenalty = 0; // no penalty
2624 pAd->DrsCounters.TxQuality[pAd->CommonCfg.TxRateIndex] = 0;
2625 pAd->DrsCounters.PER[pAd->CommonCfg.TxRateIndex] = 0;
2627 else
2629 bTxRateChanged = FALSE;
2632 pNextTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(pAd->CommonCfg.TxRateIndex+1)*5];
2633 if (bTxRateChanged && pNextTxRate)
2635 MlmeSetTxRate(pAd, pEntry, pNextTxRate);
2641 ==========================================================================
2642 Description:
2643 This routine is executed periodically inside MlmePeriodicExec() after
2644 association with an AP.
2645 It checks if StaCfg.Psm is consistent with user policy (recorded in
2646 StaCfg.WindowsPowerMode). If not, enforce user policy. However,
2647 there're some conditions to consider:
2648 1. we don't support power-saving in ADHOC mode, so Psm=PWR_ACTIVE all
2649 the time when Mibss==TRUE
2650 2. When link up in INFRA mode, Psm should not be switch to PWR_SAVE
2651 if outgoing traffic available in TxRing or MgmtRing.
2652 Output:
2653 1. change pAd->StaCfg.Psm to PWR_SAVE or leave it untouched
2655 IRQL = DISPATCH_LEVEL
2657 ==========================================================================
2659 VOID MlmeCheckPsmChange(
2660 IN PRTMP_ADAPTER pAd,
2661 IN ULONG Now32)
2663 ULONG PowerMode;
2665 // condition -
2666 // 1. Psm maybe ON only happen in INFRASTRUCTURE mode
2667 // 2. user wants either MAX_PSP or FAST_PSP
2668 // 3. but current psm is not in PWR_SAVE
2669 // 4. CNTL state machine is not doing SCANning
2670 // 5. no TX SUCCESS event for the past 1-sec period
2671 #ifdef NDIS51_MINIPORT
2672 if (pAd->StaCfg.WindowsPowerProfile == NdisPowerProfileBattery)
2673 PowerMode = pAd->StaCfg.WindowsBatteryPowerMode;
2674 else
2675 #endif
2676 PowerMode = pAd->StaCfg.WindowsPowerMode;
2678 if (INFRA_ON(pAd) &&
2679 (PowerMode != Ndis802_11PowerModeCAM) &&
2680 (pAd->StaCfg.Psm == PWR_ACTIVE) &&
2681 RTMP_TEST_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP))
2683 NdisGetSystemUpTime(&pAd->Mlme.LastSendNULLpsmTime);
2684 pAd->RalinkCounters.RxCountSinceLastNULL = 0;
2685 MlmeSetPsmBit(pAd, PWR_SAVE);
2686 if (!(pAd->CommonCfg.bAPSDCapable && pAd->CommonCfg.APEdcaParm.bAPSDCapable))
2688 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, FALSE);
2690 else
2692 RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE);
2697 // IRQL = PASSIVE_LEVEL
2698 // IRQL = DISPATCH_LEVEL
2699 VOID MlmeSetPsmBit(
2700 IN PRTMP_ADAPTER pAd,
2701 IN USHORT psm)
2703 AUTO_RSP_CFG_STRUC csr4;
2705 pAd->StaCfg.Psm = psm;
2706 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2707 csr4.field.AckCtsPsmBit = (psm == PWR_SAVE)? 1:0;
2708 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2709 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetPsmBit = %d\n", psm));
2712 // IRQL = DISPATCH_LEVEL
2713 VOID MlmeSetTxPreamble(
2714 IN PRTMP_ADAPTER pAd,
2715 IN USHORT TxPreamble)
2717 AUTO_RSP_CFG_STRUC csr4;
2720 // Always use Long preamble before verifiation short preamble functionality works well.
2721 // Todo: remove the following line if short preamble functionality works
2723 //TxPreamble = Rt802_11PreambleLong;
2725 RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word);
2726 if (TxPreamble == Rt802_11PreambleLong)
2728 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= LONG PREAMBLE)\n"));
2729 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2730 csr4.field.AutoResponderPreamble = 0;
2732 else
2734 // NOTE: 1Mbps should always use long preamble
2735 DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble (= SHORT PREAMBLE)\n"));
2736 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED);
2737 csr4.field.AutoResponderPreamble = 1;
2740 RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word);
2744 ==========================================================================
2745 Description:
2746 Update basic rate bitmap
2747 ==========================================================================
2750 VOID UpdateBasicRateBitmap(
2751 IN PRTMP_ADAPTER pAdapter)
2753 INT i, j;
2754 /* 1 2 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */
2755 UCHAR rate[] = { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
2756 UCHAR *sup_p = pAdapter->CommonCfg.SupRate;
2757 UCHAR *ext_p = pAdapter->CommonCfg.ExtRate;
2758 ULONG bitmap = pAdapter->CommonCfg.BasicRateBitmap;
2761 /* if A mode, always use fix BasicRateBitMap */
2762 //if (pAdapter->CommonCfg.Channel == PHY_11A)
2763 if (pAdapter->CommonCfg.Channel > 14)
2764 pAdapter->CommonCfg.BasicRateBitmap = 0x150; /* 6, 12, 24M */
2765 /* End of if */
2767 if (pAdapter->CommonCfg.BasicRateBitmap > 4095)
2769 /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */
2770 return;
2771 } /* End of if */
2773 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2775 sup_p[i] &= 0x7f;
2776 ext_p[i] &= 0x7f;
2777 } /* End of for */
2779 for(i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2781 if (bitmap & (1 << i))
2783 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2785 if (sup_p[j] == rate[i])
2786 sup_p[j] |= 0x80;
2787 /* End of if */
2788 } /* End of for */
2790 for(j=0; j<MAX_LEN_OF_SUPPORTED_RATES; j++)
2792 if (ext_p[j] == rate[i])
2793 ext_p[j] |= 0x80;
2794 /* End of if */
2795 } /* End of for */
2796 } /* End of if */
2797 } /* End of for */
2798 } /* End of UpdateBasicRateBitmap */
2800 // IRQL = PASSIVE_LEVEL
2801 // IRQL = DISPATCH_LEVEL
2802 // bLinkUp is to identify the inital link speed.
2803 // TRUE indicates the rate update at linkup, we should not try to set the rate at 54Mbps.
2804 VOID MlmeUpdateTxRates(
2805 IN PRTMP_ADAPTER pAd,
2806 IN BOOLEAN bLinkUp,
2807 IN UCHAR apidx)
2809 int i, num;
2810 UCHAR Rate = RATE_6, MaxDesire = RATE_1, MaxSupport = RATE_1;
2811 UCHAR MinSupport = RATE_54;
2812 ULONG BasicRateBitmap = 0;
2813 UCHAR CurrBasicRate = RATE_1;
2814 UCHAR *pSupRate, SupRateLen, *pExtRate, ExtRateLen;
2815 PHTTRANSMIT_SETTING pHtPhy = NULL;
2816 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
2817 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
2818 BOOLEAN *auto_rate_cur_p;
2819 UCHAR HtMcs = MCS_AUTO;
2821 // find max desired rate
2822 UpdateBasicRateBitmap(pAd);
2824 num = 0;
2825 auto_rate_cur_p = NULL;
2826 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2828 switch (pAd->CommonCfg.DesireRate[i] & 0x7f)
2830 case 2: Rate = RATE_1; num++; break;
2831 case 4: Rate = RATE_2; num++; break;
2832 case 11: Rate = RATE_5_5; num++; break;
2833 case 22: Rate = RATE_11; num++; break;
2834 case 12: Rate = RATE_6; num++; break;
2835 case 18: Rate = RATE_9; num++; break;
2836 case 24: Rate = RATE_12; num++; break;
2837 case 36: Rate = RATE_18; num++; break;
2838 case 48: Rate = RATE_24; num++; break;
2839 case 72: Rate = RATE_36; num++; break;
2840 case 96: Rate = RATE_48; num++; break;
2841 case 108: Rate = RATE_54; num++; break;
2842 //default: Rate = RATE_1; break;
2844 if (MaxDesire < Rate) MaxDesire = Rate;
2847 //===========================================================================
2848 //===========================================================================
2849 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2851 pHtPhy = &pAd->StaCfg.HTPhyMode;
2852 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
2853 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
2855 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
2856 HtMcs = pAd->StaCfg.DesiredTransmitSetting.field.MCS;
2858 if ((pAd->StaCfg.BssType == BSS_ADHOC) &&
2859 (pAd->CommonCfg.PhyMode == PHY_11B) &&
2860 (MaxDesire > RATE_11))
2862 MaxDesire = RATE_11;
2866 pAd->CommonCfg.MaxDesiredRate = MaxDesire;
2867 pMinHtPhy->word = 0;
2868 pMaxHtPhy->word = 0;
2869 pHtPhy->word = 0;
2871 // Auto rate switching is enabled only if more than one DESIRED RATES are
2872 // specified; otherwise disabled
2873 if (num <= 1)
2875 *auto_rate_cur_p = FALSE;
2877 else
2879 *auto_rate_cur_p = TRUE;
2882 #if 1
2883 if (HtMcs != MCS_AUTO)
2885 *auto_rate_cur_p = FALSE;
2887 else
2889 *auto_rate_cur_p = TRUE;
2891 #endif
2893 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
2895 pSupRate = &pAd->StaActive.SupRate[0];
2896 pExtRate = &pAd->StaActive.ExtRate[0];
2897 SupRateLen = pAd->StaActive.SupRateLen;
2898 ExtRateLen = pAd->StaActive.ExtRateLen;
2900 else
2902 pSupRate = &pAd->CommonCfg.SupRate[0];
2903 pExtRate = &pAd->CommonCfg.ExtRate[0];
2904 SupRateLen = pAd->CommonCfg.SupRateLen;
2905 ExtRateLen = pAd->CommonCfg.ExtRateLen;
2908 // find max supported rate
2909 for (i=0; i<SupRateLen; i++)
2911 switch (pSupRate[i] & 0x7f)
2913 case 2: Rate = RATE_1; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2914 case 4: Rate = RATE_2; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2915 case 11: Rate = RATE_5_5; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2916 case 22: Rate = RATE_11; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2917 case 12: Rate = RATE_6; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2918 case 18: Rate = RATE_9; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2919 case 24: Rate = RATE_12; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2920 case 36: Rate = RATE_18; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2921 case 48: Rate = RATE_24; /*if (pSupRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2922 case 72: Rate = RATE_36; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2923 case 96: Rate = RATE_48; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2924 case 108: Rate = RATE_54; if (pSupRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2925 default: Rate = RATE_1; break;
2927 if (MaxSupport < Rate) MaxSupport = Rate;
2929 if (MinSupport > Rate) MinSupport = Rate;
2932 for (i=0; i<ExtRateLen; i++)
2934 switch (pExtRate[i] & 0x7f)
2936 case 2: Rate = RATE_1; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0001; break;
2937 case 4: Rate = RATE_2; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0002; break;
2938 case 11: Rate = RATE_5_5; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0004; break;
2939 case 22: Rate = RATE_11; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0008; break;
2940 case 12: Rate = RATE_6; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0010; break;
2941 case 18: Rate = RATE_9; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0020; break;
2942 case 24: Rate = RATE_12; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0040; break;
2943 case 36: Rate = RATE_18; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0080; break;
2944 case 48: Rate = RATE_24; /*if (pExtRate[i] & 0x80)*/ BasicRateBitmap |= 0x0100; break;
2945 case 72: Rate = RATE_36; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0200; break;
2946 case 96: Rate = RATE_48; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0400; break;
2947 case 108: Rate = RATE_54; if (pExtRate[i] & 0x80) BasicRateBitmap |= 0x0800; break;
2948 default: Rate = RATE_1; break;
2950 if (MaxSupport < Rate) MaxSupport = Rate;
2952 if (MinSupport > Rate) MinSupport = Rate;
2955 RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap);
2957 // calculate the exptected ACK rate for each TX rate. This info is used to caculate
2958 // the DURATION field of outgoing uniicast DATA/MGMT frame
2959 for (i=0; i<MAX_LEN_OF_SUPPORTED_RATES; i++)
2961 if (BasicRateBitmap & (0x01 << i))
2962 CurrBasicRate = (UCHAR)i;
2963 pAd->CommonCfg.ExpectedACKRate[i] = CurrBasicRate;
2966 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateTxRates[MaxSupport = %d] = MaxDesire %d Mbps\n", RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire]));
2967 // max tx rate = min {max desire rate, max supported rate}
2968 if (MaxSupport < MaxDesire)
2969 pAd->CommonCfg.MaxTxRate = MaxSupport;
2970 else
2971 pAd->CommonCfg.MaxTxRate = MaxDesire;
2973 pAd->CommonCfg.MinTxRate = MinSupport;
2974 if (*auto_rate_cur_p)
2976 short dbm = 0;
2978 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
2979 dbm = pAd->StaCfg.RssiSample.AvgRssi0 - pAd->BbpRssiToDbmDelta;
2981 if (bLinkUp == TRUE)
2982 pAd->CommonCfg.TxRate = RATE_24;
2983 else
2984 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2986 if (dbm < -75)
2987 pAd->CommonCfg.TxRate = RATE_11;
2988 else if (dbm < -70)
2989 pAd->CommonCfg.TxRate = RATE_24;
2991 // should never exceed MaxTxRate (consider 11B-only mode)
2992 if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate)
2993 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
2995 pAd->CommonCfg.TxRateIndex = 0;
2997 else
2999 pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate;
3000 pHtPhy->field.MCS = (pAd->CommonCfg.MaxTxRate > 3) ? (pAd->CommonCfg.MaxTxRate - 4) : pAd->CommonCfg.MaxTxRate;
3001 pHtPhy->field.MODE = (pAd->CommonCfg.MaxTxRate > 3) ? MODE_OFDM : MODE_CCK;
3003 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC;
3004 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI;
3005 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS;
3006 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE;
3009 if (pAd->CommonCfg.TxRate <= RATE_11)
3011 pMaxHtPhy->field.MODE = MODE_CCK;
3012 pMaxHtPhy->field.MCS = pAd->CommonCfg.TxRate;
3013 pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;
3015 else
3017 pMaxHtPhy->field.MODE = MODE_OFDM;
3018 pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.TxRate];
3019 if (pAd->CommonCfg.MinTxRate >= RATE_6 && (pAd->CommonCfg.MinTxRate <= RATE_54))
3020 {pMinHtPhy->field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MinTxRate];}
3021 else
3022 {pMinHtPhy->field.MCS = pAd->CommonCfg.MinTxRate;}
3025 pHtPhy->word = (pMaxHtPhy->word);
3026 if (bLinkUp && (pAd->OpMode == OPMODE_STA))
3028 pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word;
3029 pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word;
3030 pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word;
3032 else
3034 switch (pAd->CommonCfg.PhyMode)
3036 case PHY_11BG_MIXED:
3037 case PHY_11B:
3038 #ifdef DOT11_N_SUPPORT
3039 case PHY_11BGN_MIXED:
3040 #endif // DOT11_N_SUPPORT //
3041 pAd->CommonCfg.MlmeRate = RATE_1;
3042 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3043 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3044 pAd->CommonCfg.RtsRate = RATE_11;
3045 break;
3046 case PHY_11G:
3047 case PHY_11A:
3048 #ifdef DOT11_N_SUPPORT
3049 case PHY_11AGN_MIXED:
3050 case PHY_11GN_MIXED:
3051 case PHY_11N_2_4G:
3052 case PHY_11AN_MIXED:
3053 case PHY_11N_5G:
3054 #endif // DOT11_N_SUPPORT //
3055 pAd->CommonCfg.MlmeRate = RATE_6;
3056 pAd->CommonCfg.RtsRate = RATE_6;
3057 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3058 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3059 break;
3060 case PHY_11ABG_MIXED:
3061 #ifdef DOT11_N_SUPPORT
3062 case PHY_11ABGN_MIXED:
3063 #endif // DOT11_N_SUPPORT //
3064 if (pAd->CommonCfg.Channel <= 14)
3066 pAd->CommonCfg.MlmeRate = RATE_1;
3067 pAd->CommonCfg.RtsRate = RATE_1;
3068 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
3069 pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1;
3071 else
3073 pAd->CommonCfg.MlmeRate = RATE_6;
3074 pAd->CommonCfg.RtsRate = RATE_6;
3075 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3076 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3078 break;
3079 default: // error
3080 pAd->CommonCfg.MlmeRate = RATE_6;
3081 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
3082 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
3083 pAd->CommonCfg.RtsRate = RATE_1;
3084 break;
3087 // Keep Basic Mlme Rate.
3089 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word;
3090 if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM)
3091 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_24];
3092 else
3093 pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1;
3094 pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate;
3097 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n",
3098 RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], RateIdToMbps[pAd->CommonCfg.MaxTxRate], RateIdToMbps[pAd->CommonCfg.MinTxRate],
3099 /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p));
3100 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateTxRates (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n",
3101 RateIdToMbps[pAd->CommonCfg.TxRate], RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap));
3102 DBGPRINT(RT_DEBUG_TRACE, ("MlmeUpdateTxRates (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n",
3103 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 ));
3106 #ifdef DOT11_N_SUPPORT
3108 ==========================================================================
3109 Description:
3110 This function update HT Rate setting.
3111 Input Wcid value is valid for 2 case :
3112 1. it's used for Station in infra mode that copy AP rate to Mactable.
3113 2. OR Station in adhoc mode to copy peer's HT rate to Mactable.
3115 IRQL = DISPATCH_LEVEL
3117 ==========================================================================
3119 VOID MlmeUpdateHtTxRates(
3120 IN PRTMP_ADAPTER pAd,
3121 IN UCHAR apidx)
3123 UCHAR StbcMcs; //j, StbcMcs, bitmask;
3124 CHAR i; // 3*3
3125 RT_HT_CAPABILITY *pRtHtCap = NULL;
3126 RT_HT_PHY_INFO *pActiveHtPhy = NULL;
3127 ULONG BasicMCS;
3128 UCHAR j, bitmask;
3129 PRT_HT_PHY_INFO pDesireHtPhy = NULL;
3130 PHTTRANSMIT_SETTING pHtPhy = NULL;
3131 PHTTRANSMIT_SETTING pMaxHtPhy = NULL;
3132 PHTTRANSMIT_SETTING pMinHtPhy = NULL;
3133 BOOLEAN *auto_rate_cur_p;
3135 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates===> \n"));
3137 auto_rate_cur_p = NULL;
3139 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3141 pDesireHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3142 pActiveHtPhy = &pAd->StaCfg.DesiredHtPhyInfo;
3143 pHtPhy = &pAd->StaCfg.HTPhyMode;
3144 pMaxHtPhy = &pAd->StaCfg.MaxHTPhyMode;
3145 pMinHtPhy = &pAd->StaCfg.MinHTPhyMode;
3147 auto_rate_cur_p = &pAd->StaCfg.bAutoTxRateSwitch;
3150 if ((ADHOC_ON(pAd) || INFRA_ON(pAd)) && (pAd->OpMode == OPMODE_STA))
3152 if (pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE)
3153 return;
3155 pRtHtCap = &pAd->StaActive.SupportedHtPhy;
3156 pActiveHtPhy = &pAd->StaActive.SupportedPhyInfo;
3157 StbcMcs = (UCHAR)pAd->MlmeAux.AddHtInfo.AddHtInfo3.StbcMcs;
3158 BasicMCS =pAd->MlmeAux.AddHtInfo.MCSSet[0]+(pAd->MlmeAux.AddHtInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3159 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3160 pMaxHtPhy->field.STBC = STBC_USE;
3161 else
3162 pMaxHtPhy->field.STBC = STBC_NONE;
3164 else
3166 if (pDesireHtPhy->bHtEnable == FALSE)
3167 return;
3169 pRtHtCap = &pAd->CommonCfg.DesiredHtPhy;
3170 StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs;
3171 BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16);
3172 if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pRtHtCap->RxSTBC) && (pAd->Antenna.field.TxPath == 2))
3173 pMaxHtPhy->field.STBC = STBC_USE;
3174 else
3175 pMaxHtPhy->field.STBC = STBC_NONE;
3178 // Decide MAX ht rate.
3179 if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF))
3180 pMaxHtPhy->field.MODE = MODE_HTGREENFIELD;
3181 else
3182 pMaxHtPhy->field.MODE = MODE_HTMIX;
3184 if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth))
3185 pMaxHtPhy->field.BW = BW_40;
3186 else
3187 pMaxHtPhy->field.BW = BW_20;
3189 if (pMaxHtPhy->field.BW == BW_20)
3190 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20);
3191 else
3192 pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40);
3194 for (i=23; i>=0; i--) // 3*3
3196 j = i/8;
3197 bitmask = (1<<(i-(j*8)));
3199 if ((pActiveHtPhy->MCSSet[j] & bitmask) && (pDesireHtPhy->MCSSet[j] & bitmask))
3201 pMaxHtPhy->field.MCS = i;
3202 break;
3205 if (i==0)
3206 break;
3209 // Copy MIN ht rate. rt2860???
3210 pMinHtPhy->field.BW = BW_20;
3211 pMinHtPhy->field.MCS = 0;
3212 pMinHtPhy->field.STBC = 0;
3213 pMinHtPhy->field.ShortGI = 0;
3214 //If STA assigns fixed rate. update to fixed here.
3215 if ( (pAd->OpMode == OPMODE_STA) && (pDesireHtPhy->MCSSet[0] != 0xff))
3217 if (pDesireHtPhy->MCSSet[4] != 0)
3219 pMaxHtPhy->field.MCS = 32;
3220 pMinHtPhy->field.MCS = 32;
3221 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== Use Fixed MCS = %d\n",pMinHtPhy->field.MCS));
3224 for (i=23; (CHAR)i >= 0; i--) // 3*3
3226 j = i/8;
3227 bitmask = (1<<(i-(j*8)));
3228 if ( (pDesireHtPhy->MCSSet[j] & bitmask) && (pActiveHtPhy->MCSSet[j] & bitmask))
3230 pMaxHtPhy->field.MCS = i;
3231 pMinHtPhy->field.MCS = i;
3232 break;
3234 if (i==0)
3235 break;
3239 // Decide ht rate
3240 pHtPhy->field.STBC = pMaxHtPhy->field.STBC;
3241 pHtPhy->field.BW = pMaxHtPhy->field.BW;
3242 pHtPhy->field.MODE = pMaxHtPhy->field.MODE;
3243 pHtPhy->field.MCS = pMaxHtPhy->field.MCS;
3244 pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI;
3246 // use default now. rt2860
3247 if (pDesireHtPhy->MCSSet[0] != 0xff)
3248 *auto_rate_cur_p = FALSE;
3249 else
3250 *auto_rate_cur_p = TRUE;
3252 DBGPRINT(RT_DEBUG_TRACE, (" MlmeUpdateHtTxRates<---.AMsduSize = %d \n", pAd->CommonCfg.DesiredHtPhy.AmsduSize ));
3253 DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS,
3254 pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE));
3255 DBGPRINT(RT_DEBUG_TRACE,("MlmeUpdateHtTxRates<=== \n"));
3257 #endif // DOT11_N_SUPPORT //
3259 // IRQL = DISPATCH_LEVEL
3260 VOID MlmeRadioOff(
3261 IN PRTMP_ADAPTER pAd)
3263 RT28XX_MLME_RADIO_OFF(pAd);
3266 // IRQL = DISPATCH_LEVEL
3267 VOID MlmeRadioOn(
3268 IN PRTMP_ADAPTER pAd)
3270 RT28XX_MLME_RADIO_ON(pAd);
3273 // ===========================================================================================
3274 // bss_table.c
3275 // ===========================================================================================
3278 /*! \brief initialize BSS table
3279 * \param p_tab pointer to the table
3280 * \return none
3281 * \pre
3282 * \post
3284 IRQL = PASSIVE_LEVEL
3285 IRQL = DISPATCH_LEVEL
3288 VOID BssTableInit(
3289 IN BSS_TABLE *Tab)
3291 int i;
3293 Tab->BssNr = 0;
3294 Tab->BssOverlapNr = 0;
3295 for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++)
3297 NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY));
3298 Tab->BssEntry[i].Rssi = -127; // initial the rssi as a minimum value
3302 #ifdef DOT11_N_SUPPORT
3303 VOID BATableInit(
3304 IN PRTMP_ADAPTER pAd,
3305 IN BA_TABLE *Tab)
3307 int i;
3309 Tab->numAsOriginator = 0;
3310 Tab->numAsRecipient = 0;
3311 NdisAllocateSpinLock(&pAd->BATabLock);
3312 for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++)
3314 Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE;
3315 NdisAllocateSpinLock(&(Tab->BARecEntry[i].RxReRingLock));
3317 for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++)
3319 Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE;
3322 #endif // DOT11_N_SUPPORT //
3324 /*! \brief search the BSS table by SSID
3325 * \param p_tab pointer to the bss table
3326 * \param ssid SSID string
3327 * \return index of the table, BSS_NOT_FOUND if not in the table
3328 * \pre
3329 * \post
3330 * \note search by sequential search
3332 IRQL = DISPATCH_LEVEL
3335 ULONG BssTableSearch(
3336 IN BSS_TABLE *Tab,
3337 IN PUCHAR pBssid,
3338 IN UCHAR Channel)
3340 UCHAR i;
3342 for (i = 0; i < Tab->BssNr; i++)
3345 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3346 // We should distinguish this case.
3348 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3349 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3350 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid))
3352 return i;
3355 return (ULONG)BSS_NOT_FOUND;
3358 ULONG BssSsidTableSearch(
3359 IN BSS_TABLE *Tab,
3360 IN PUCHAR pBssid,
3361 IN PUCHAR pSsid,
3362 IN UCHAR SsidLen,
3363 IN UCHAR Channel)
3365 UCHAR i;
3367 for (i = 0; i < Tab->BssNr; i++)
3370 // Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.
3371 // We should distinguish this case.
3373 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3374 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3375 MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) &&
3376 SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen))
3378 return i;
3381 return (ULONG)BSS_NOT_FOUND;
3384 ULONG BssTableSearchWithSSID(
3385 IN BSS_TABLE *Tab,
3386 IN PUCHAR Bssid,
3387 IN PUCHAR pSsid,
3388 IN UCHAR SsidLen,
3389 IN UCHAR Channel)
3391 UCHAR i;
3393 for (i = 0; i < Tab->BssNr; i++)
3395 if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) ||
3396 ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) &&
3397 MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) &&
3398 (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) ||
3399 (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) ||
3400 (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen))))
3402 return i;
3405 return (ULONG)BSS_NOT_FOUND;
3408 // IRQL = DISPATCH_LEVEL
3409 VOID BssTableDeleteEntry(
3410 IN OUT BSS_TABLE *Tab,
3411 IN PUCHAR pBssid,
3412 IN UCHAR Channel)
3414 UCHAR i, j;
3416 for (i = 0; i < Tab->BssNr; i++)
3418 if ((Tab->BssEntry[i].Channel == Channel) &&
3419 (MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)))
3421 for (j = i; j < Tab->BssNr - 1; j++)
3423 NdisMoveMemory(&(Tab->BssEntry[j]), &(Tab->BssEntry[j + 1]), sizeof(BSS_ENTRY));
3425 NdisZeroMemory(&(Tab->BssEntry[Tab->BssNr - 1]), sizeof(BSS_ENTRY));
3426 Tab->BssNr -= 1;
3427 return;
3432 #ifdef DOT11_N_SUPPORT
3434 ========================================================================
3435 Routine Description:
3436 Delete the Originator Entry in BAtable. Or decrease numAs Originator by 1 if needed.
3438 Arguments:
3439 // IRQL = DISPATCH_LEVEL
3440 ========================================================================
3442 VOID BATableDeleteORIEntry(
3443 IN OUT PRTMP_ADAPTER pAd,
3444 IN BA_ORI_ENTRY *pBAORIEntry)
3447 if (pBAORIEntry->ORI_BA_Status != Originator_NONE)
3449 NdisAcquireSpinLock(&pAd->BATabLock);
3450 if (pBAORIEntry->ORI_BA_Status == Originator_Done)
3452 pAd->BATable.numAsOriginator -= 1;
3453 DBGPRINT(RT_DEBUG_TRACE, ("BATableDeleteORIEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient));
3454 // Erase Bitmap flag.
3456 pAd->MacTab.Content[pBAORIEntry->Wcid].TXBAbitmap &= (~(1<<(pBAORIEntry->TID) )); // If STA mode, erase flag here
3457 pAd->MacTab.Content[pBAORIEntry->Wcid].BAOriWcidArray[pBAORIEntry->TID] = 0; // If STA mode, erase flag here
3458 pBAORIEntry->ORI_BA_Status = Originator_NONE;
3459 pBAORIEntry->Token = 1;
3460 // Not clear Sequence here.
3461 NdisReleaseSpinLock(&pAd->BATabLock);
3464 #endif // DOT11_N_SUPPORT //
3466 /*! \brief
3467 * \param
3468 * \return
3469 * \pre
3470 * \post
3472 IRQL = DISPATCH_LEVEL
3475 VOID BssEntrySet(
3476 IN PRTMP_ADAPTER pAd,
3477 OUT BSS_ENTRY *pBss,
3478 IN PUCHAR pBssid,
3479 IN CHAR Ssid[],
3480 IN UCHAR SsidLen,
3481 IN UCHAR BssType,
3482 IN USHORT BeaconPeriod,
3483 IN PCF_PARM pCfParm,
3484 IN USHORT AtimWin,
3485 IN USHORT CapabilityInfo,
3486 IN UCHAR SupRate[],
3487 IN UCHAR SupRateLen,
3488 IN UCHAR ExtRate[],
3489 IN UCHAR ExtRateLen,
3490 IN HT_CAPABILITY_IE *pHtCapability,
3491 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3492 IN UCHAR HtCapabilityLen,
3493 IN UCHAR AddHtInfoLen,
3494 IN UCHAR NewExtChanOffset,
3495 IN UCHAR Channel,
3496 IN CHAR Rssi,
3497 IN LARGE_INTEGER TimeStamp,
3498 IN UCHAR CkipFlag,
3499 IN PEDCA_PARM pEdcaParm,
3500 IN PQOS_CAPABILITY_PARM pQosCapability,
3501 IN PQBSS_LOAD_PARM pQbssLoad,
3502 IN USHORT LengthVIE,
3503 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3505 COPY_MAC_ADDR(pBss->Bssid, pBssid);
3506 // Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID
3507 pBss->Hidden = 1;
3508 if (SsidLen > 0)
3510 // For hidden SSID AP, it might send beacon with SSID len equal to 0
3511 // Or send beacon /probe response with SSID len matching real SSID length,
3512 // but SSID is all zero. such as "00-00-00-00" with length 4.
3513 // We have to prevent this case overwrite correct table
3514 if (NdisEqualMemory(Ssid, ZeroSsid, SsidLen) == 0)
3516 NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID);
3517 NdisMoveMemory(pBss->Ssid, Ssid, SsidLen);
3518 pBss->SsidLen = SsidLen;
3519 pBss->Hidden = 0;
3522 else
3523 pBss->SsidLen = 0;
3524 pBss->BssType = BssType;
3525 pBss->BeaconPeriod = BeaconPeriod;
3526 if (BssType == BSS_INFRA)
3528 if (pCfParm->bValid)
3530 pBss->CfpCount = pCfParm->CfpCount;
3531 pBss->CfpPeriod = pCfParm->CfpPeriod;
3532 pBss->CfpMaxDuration = pCfParm->CfpMaxDuration;
3533 pBss->CfpDurRemaining = pCfParm->CfpDurRemaining;
3536 else
3538 pBss->AtimWin = AtimWin;
3541 pBss->CapabilityInfo = CapabilityInfo;
3542 // The privacy bit indicate security is ON, it maight be WEP, TKIP or AES
3543 // Combine with AuthMode, they will decide the connection methods.
3544 pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo);
3545 ASSERT(SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3546 if (SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES)
3547 NdisMoveMemory(pBss->SupRate, SupRate, SupRateLen);
3548 else
3549 NdisMoveMemory(pBss->SupRate, SupRate, MAX_LEN_OF_SUPPORTED_RATES);
3550 pBss->SupRateLen = SupRateLen;
3551 ASSERT(ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES);
3552 NdisMoveMemory(pBss->ExtRate, ExtRate, ExtRateLen);
3553 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3554 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3555 pBss->NewExtChanOffset = NewExtChanOffset;
3556 pBss->ExtRateLen = ExtRateLen;
3557 pBss->Channel = Channel;
3558 pBss->CentralChannel = Channel;
3559 pBss->Rssi = Rssi;
3560 // Update CkipFlag. if not exists, the value is 0x0
3561 pBss->CkipFlag = CkipFlag;
3563 // New for microsoft Fixed IEs
3564 NdisMoveMemory(pBss->FixIEs.Timestamp, &TimeStamp, 8);
3565 pBss->FixIEs.BeaconInterval = BeaconPeriod;
3566 pBss->FixIEs.Capabilities = CapabilityInfo;
3568 // New for microsoft Variable IEs
3569 if (LengthVIE != 0)
3571 pBss->VarIELen = LengthVIE;
3572 NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen);
3574 else
3576 pBss->VarIELen = 0;
3579 pBss->AddHtInfoLen = 0;
3580 pBss->HtCapabilityLen = 0;
3581 #ifdef DOT11_N_SUPPORT
3582 if (HtCapabilityLen> 0)
3584 pBss->HtCapabilityLen = HtCapabilityLen;
3585 NdisMoveMemory(&pBss->HtCapability, pHtCapability, HtCapabilityLen);
3586 if (AddHtInfoLen > 0)
3588 pBss->AddHtInfoLen = AddHtInfoLen;
3589 NdisMoveMemory(&pBss->AddHtInfo, pAddHtInfo, AddHtInfoLen);
3591 if ((pAddHtInfo->ControlChan > 2)&& (pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_BELOW) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3593 pBss->CentralChannel = pAddHtInfo->ControlChan - 2;
3595 else if ((pAddHtInfo->AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) && (pHtCapability->HtCapInfo.ChannelWidth == BW_40))
3597 pBss->CentralChannel = pAddHtInfo->ControlChan + 2;
3601 #endif // DOT11_N_SUPPORT //
3603 BssCipherParse(pBss);
3605 // new for QOS
3606 if (pEdcaParm)
3607 NdisMoveMemory(&pBss->EdcaParm, pEdcaParm, sizeof(EDCA_PARM));
3608 else
3609 pBss->EdcaParm.bValid = FALSE;
3610 if (pQosCapability)
3611 NdisMoveMemory(&pBss->QosCapability, pQosCapability, sizeof(QOS_CAPABILITY_PARM));
3612 else
3613 pBss->QosCapability.bValid = FALSE;
3614 if (pQbssLoad)
3615 NdisMoveMemory(&pBss->QbssLoad, pQbssLoad, sizeof(QBSS_LOAD_PARM));
3616 else
3617 pBss->QbssLoad.bValid = FALSE;
3619 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
3621 PEID_STRUCT pEid;
3622 USHORT Length = 0;
3625 NdisZeroMemory(&pBss->WpaIE.IE[0], MAX_CUSTOM_LEN);
3626 NdisZeroMemory(&pBss->RsnIE.IE[0], MAX_CUSTOM_LEN);
3628 pEid = (PEID_STRUCT) pVIE;
3630 while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE)
3632 switch(pEid->Eid)
3634 case IE_WPA:
3635 if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4))
3637 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3639 pBss->WpaIE.IELen = 0;
3640 break;
3642 pBss->WpaIE.IELen = pEid->Len + 2;
3643 NdisMoveMemory(pBss->WpaIE.IE, pEid, pBss->WpaIE.IELen);
3645 break;
3646 case IE_RSN:
3647 if (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3))
3649 if ((pEid->Len + 2) > MAX_CUSTOM_LEN)
3651 pBss->RsnIE.IELen = 0;
3652 break;
3654 pBss->RsnIE.IELen = pEid->Len + 2;
3655 NdisMoveMemory(pBss->RsnIE.IE, pEid, pBss->RsnIE.IELen);
3657 break;
3659 Length = Length + 2 + (USHORT)pEid->Len; // Eid[1] + Len[1]+ content[Len]
3660 pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len);
3666 * \brief insert an entry into the bss table
3667 * \param p_tab The BSS table
3668 * \param Bssid BSSID
3669 * \param ssid SSID
3670 * \param ssid_len Length of SSID
3671 * \param bss_type
3672 * \param beacon_period
3673 * \param timestamp
3674 * \param p_cf
3675 * \param atim_win
3676 * \param cap
3677 * \param rates
3678 * \param rates_len
3679 * \param channel_idx
3680 * \return none
3681 * \pre
3682 * \post
3683 * \note If SSID is identical, the old entry will be replaced by the new one
3685 IRQL = DISPATCH_LEVEL
3688 ULONG BssTableSetEntry(
3689 IN PRTMP_ADAPTER pAd,
3690 OUT BSS_TABLE *Tab,
3691 IN PUCHAR pBssid,
3692 IN CHAR Ssid[],
3693 IN UCHAR SsidLen,
3694 IN UCHAR BssType,
3695 IN USHORT BeaconPeriod,
3696 IN CF_PARM *CfParm,
3697 IN USHORT AtimWin,
3698 IN USHORT CapabilityInfo,
3699 IN UCHAR SupRate[],
3700 IN UCHAR SupRateLen,
3701 IN UCHAR ExtRate[],
3702 IN UCHAR ExtRateLen,
3703 IN HT_CAPABILITY_IE *pHtCapability,
3704 IN ADD_HT_INFO_IE *pAddHtInfo, // AP might use this additional ht info IE
3705 IN UCHAR HtCapabilityLen,
3706 IN UCHAR AddHtInfoLen,
3707 IN UCHAR NewExtChanOffset,
3708 IN UCHAR ChannelNo,
3709 IN CHAR Rssi,
3710 IN LARGE_INTEGER TimeStamp,
3711 IN UCHAR CkipFlag,
3712 IN PEDCA_PARM pEdcaParm,
3713 IN PQOS_CAPABILITY_PARM pQosCapability,
3714 IN PQBSS_LOAD_PARM pQbssLoad,
3715 IN USHORT LengthVIE,
3716 IN PNDIS_802_11_VARIABLE_IEs pVIE)
3718 ULONG Idx;
3720 Idx = BssTableSearchWithSSID(Tab, pBssid, Ssid, SsidLen, ChannelNo);
3721 if (Idx == BSS_NOT_FOUND)
3723 if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3726 // It may happen when BSS Table was full.
3727 // The desired AP will not be added into BSS Table
3728 // In this case, if we found the desired AP then overwrite BSS Table.
3730 if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
3732 if (MAC_ADDR_EQUAL(pAd->MlmeAux.Bssid, pBssid) ||
3733 SSID_EQUAL(pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen, Ssid, SsidLen))
3735 Idx = Tab->BssOverlapNr;
3736 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3737 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3738 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3739 Tab->BssOverlapNr = (Tab->BssOverlapNr++) % MAX_LEN_OF_BSS_TABLE;
3741 return Idx;
3743 else
3745 return BSS_NOT_FOUND;
3748 Idx = Tab->BssNr;
3749 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod, CfParm, AtimWin,
3750 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3751 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3752 Tab->BssNr++;
3754 else
3756 BssEntrySet(pAd, &Tab->BssEntry[Idx], pBssid, Ssid, SsidLen, BssType, BeaconPeriod,CfParm, AtimWin,
3757 CapabilityInfo, SupRate, SupRateLen, ExtRate, ExtRateLen,pHtCapability, pAddHtInfo,HtCapabilityLen, AddHtInfoLen,
3758 NewExtChanOffset, ChannelNo, Rssi, TimeStamp, CkipFlag, pEdcaParm, pQosCapability, pQbssLoad, LengthVIE, pVIE);
3761 return Idx;
3764 // IRQL = DISPATCH_LEVEL
3765 VOID BssTableSsidSort(
3766 IN PRTMP_ADAPTER pAd,
3767 OUT BSS_TABLE *OutTab,
3768 IN CHAR Ssid[],
3769 IN UCHAR SsidLen)
3771 INT i;
3772 BssTableInit(OutTab);
3774 for (i = 0; i < pAd->ScanTab.BssNr; i++)
3776 BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i];
3777 BOOLEAN bIsHiddenApIncluded = FALSE;
3779 if (((pAd->CommonCfg.bIEEE80211H == 1) &&
3780 (pAd->MlmeAux.Channel > 14) &&
3781 RadarChannelCheck(pAd, pInBss->Channel))
3784 if (pInBss->Hidden)
3785 bIsHiddenApIncluded = TRUE;
3788 if ((pInBss->BssType == pAd->StaCfg.BssType) &&
3789 (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded))
3791 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3792 #ifdef DOT11_N_SUPPORT
3793 // 2.4G/5G N only mode
3794 if ((pInBss->HtCapabilityLen == 0) &&
3795 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3797 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3798 continue;
3800 #endif // DOT11_N_SUPPORT //
3802 // New for WPA2
3803 // Check the Authmode first
3804 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3806 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3807 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3808 // None matched
3809 continue;
3811 // Check cipher suite, AP must have more secured cipher than station setting
3812 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3814 // If it's not mixed mode, we should only let BSS pass with the same encryption
3815 if (pInBss->WPA.bMixMode == FALSE)
3816 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3817 continue;
3819 // check group cipher
3820 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3821 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3822 (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled))
3823 continue;
3825 // check pairwise cipher, skip if none matched
3826 // If profile set to AES, let it pass without question.
3827 // If profile set to TKIP, we must find one mateched
3828 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3829 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3830 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3831 continue;
3833 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3835 // If it's not mixed mode, we should only let BSS pass with the same encryption
3836 if (pInBss->WPA2.bMixMode == FALSE)
3837 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3838 continue;
3840 // check group cipher
3841 if ((pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher) &&
3842 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) &&
3843 (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled))
3844 continue;
3846 // check pairwise cipher, skip if none matched
3847 // If profile set to AES, let it pass without question.
3848 // If profile set to TKIP, we must find one mateched
3849 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3850 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3851 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3852 continue;
3855 // Bss Type matched, SSID matched.
3856 // We will check wepstatus for qualification Bss
3857 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3859 DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", pAd->StaCfg.WepStatus, pInBss->WepStatus));
3861 // For the SESv2 case, we will not qualify WepStatus.
3863 if (!pInBss->bSES)
3864 continue;
3867 // Since the AP is using hidden SSID, and we are trying to connect to ANY
3868 // It definitely will fail. So, skip it.
3869 // CCX also require not even try to connect it!!
3870 if (SsidLen == 0)
3871 continue;
3873 #ifdef DOT11_N_SUPPORT
3874 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3875 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3876 if ((pInBss->CentralChannel != pInBss->Channel) &&
3877 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3879 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3881 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3882 SetCommonHT(pAd);
3883 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3885 else
3887 if (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == BAND_WIDTH_20)
3889 SetCommonHT(pAd);
3893 #endif // DOT11_N_SUPPORT //
3895 // copy matching BSS from InTab to OutTab
3896 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3898 OutTab->BssNr++;
3900 else if ((pInBss->BssType == pAd->StaCfg.BssType) && (SsidLen == 0))
3902 BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr];
3905 #ifdef DOT11_N_SUPPORT
3906 // 2.4G/5G N only mode
3907 if ((pInBss->HtCapabilityLen == 0) &&
3908 ((pAd->CommonCfg.PhyMode == PHY_11N_2_4G) || (pAd->CommonCfg.PhyMode == PHY_11N_5G)))
3910 DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n"));
3911 continue;
3913 #endif // DOT11_N_SUPPORT //
3915 // New for WPA2
3916 // Check the Authmode first
3917 if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPA)
3919 // Check AuthMode and AuthModeAux for matching, in case AP support dual-mode
3920 if ((pAd->StaCfg.AuthMode != pInBss->AuthMode) && (pAd->StaCfg.AuthMode != pInBss->AuthModeAux))
3921 // None matched
3922 continue;
3924 // Check cipher suite, AP must have more secured cipher than station setting
3925 if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK))
3927 // If it's not mixed mode, we should only let BSS pass with the same encryption
3928 if (pInBss->WPA.bMixMode == FALSE)
3929 if (pAd->StaCfg.WepStatus != pInBss->WPA.GroupCipher)
3930 continue;
3932 // check group cipher
3933 if (pAd->StaCfg.WepStatus < pInBss->WPA.GroupCipher)
3934 continue;
3936 // check pairwise cipher, skip if none matched
3937 // If profile set to AES, let it pass without question.
3938 // If profile set to TKIP, we must find one mateched
3939 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3940 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipher) &&
3941 (pAd->StaCfg.WepStatus != pInBss->WPA.PairCipherAux))
3942 continue;
3944 else if ((pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2) || (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK))
3946 // If it's not mixed mode, we should only let BSS pass with the same encryption
3947 if (pInBss->WPA2.bMixMode == FALSE)
3948 if (pAd->StaCfg.WepStatus != pInBss->WPA2.GroupCipher)
3949 continue;
3951 // check group cipher
3952 if (pAd->StaCfg.WepStatus < pInBss->WPA2.GroupCipher)
3953 continue;
3955 // check pairwise cipher, skip if none matched
3956 // If profile set to AES, let it pass without question.
3957 // If profile set to TKIP, we must find one mateched
3958 if ((pAd->StaCfg.WepStatus == Ndis802_11Encryption2Enabled) &&
3959 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipher) &&
3960 (pAd->StaCfg.WepStatus != pInBss->WPA2.PairCipherAux))
3961 continue;
3964 // Bss Type matched, SSID matched.
3965 // We will check wepstatus for qualification Bss
3966 else if (pAd->StaCfg.WepStatus != pInBss->WepStatus)
3967 continue;
3969 #ifdef DOT11_N_SUPPORT
3970 // If both station and AP use 40MHz, still need to check if the 40MHZ band's legality in my country region
3971 // If this 40MHz wideband is not allowed in my country list, use bandwidth 20MHZ instead,
3972 if ((pInBss->CentralChannel != pInBss->Channel) &&
3973 (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40))
3975 if (RTMPCheckChannel(pAd, pInBss->CentralChannel, pInBss->Channel) == FALSE)
3977 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
3978 SetCommonHT(pAd);
3979 pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40;
3982 #endif // DOT11_N_SUPPORT //
3984 // copy matching BSS from InTab to OutTab
3985 NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY));
3987 OutTab->BssNr++;
3990 if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE)
3991 break;
3994 BssTableSortByRssi(OutTab);
3998 // IRQL = DISPATCH_LEVEL
3999 VOID BssTableSortByRssi(
4000 IN OUT BSS_TABLE *OutTab)
4002 INT i, j;
4003 BSS_ENTRY TmpBss;
4005 for (i = 0; i < OutTab->BssNr - 1; i++)
4007 for (j = i+1; j < OutTab->BssNr; j++)
4009 if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi)
4011 NdisMoveMemory(&TmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY));
4012 NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY));
4013 NdisMoveMemory(&OutTab->BssEntry[i], &TmpBss, sizeof(BSS_ENTRY));
4019 VOID BssCipherParse(
4020 IN OUT PBSS_ENTRY pBss)
4022 PEID_STRUCT pEid;
4023 PUCHAR pTmp;
4024 PRSN_IE_HEADER_STRUCT pRsnHeader;
4025 PCIPHER_SUITE_STRUCT pCipher;
4026 PAKM_SUITE_STRUCT pAKM;
4027 USHORT Count;
4028 INT Length;
4029 NDIS_802_11_ENCRYPTION_STATUS TmpCipher;
4032 // WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.
4034 if (pBss->Privacy)
4036 pBss->WepStatus = Ndis802_11WEPEnabled;
4038 else
4040 pBss->WepStatus = Ndis802_11WEPDisabled;
4042 // Set default to disable & open authentication before parsing variable IE
4043 pBss->AuthMode = Ndis802_11AuthModeOpen;
4044 pBss->AuthModeAux = Ndis802_11AuthModeOpen;
4046 // Init WPA setting
4047 pBss->WPA.PairCipher = Ndis802_11WEPDisabled;
4048 pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled;
4049 pBss->WPA.GroupCipher = Ndis802_11WEPDisabled;
4050 pBss->WPA.RsnCapability = 0;
4051 pBss->WPA.bMixMode = FALSE;
4053 // Init WPA2 setting
4054 pBss->WPA2.PairCipher = Ndis802_11WEPDisabled;
4055 pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled;
4056 pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled;
4057 pBss->WPA2.RsnCapability = 0;
4058 pBss->WPA2.bMixMode = FALSE;
4061 Length = (INT) pBss->VarIELen;
4063 while (Length > 0)
4065 // Parse cipher suite base on WPA1 & WPA2, they should be parsed differently
4066 pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length;
4067 pEid = (PEID_STRUCT) pTmp;
4068 switch (pEid->Eid)
4070 case IE_WPA:
4071 //Parse Cisco IE_WPA (LEAP, CCKM, etc.)
4072 if ( NdisEqualMemory((pTmp+8), CISCO_OUI, 3))
4074 pTmp += 11;
4075 switch (*pTmp)
4077 case 1:
4078 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4079 pBss->WepStatus = Ndis802_11Encryption1Enabled;
4080 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4081 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4082 break;
4083 case 2:
4084 pBss->WepStatus = Ndis802_11Encryption2Enabled;
4085 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4086 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4087 break;
4088 case 4:
4089 pBss->WepStatus = Ndis802_11Encryption3Enabled;
4090 pBss->WPA.PairCipher = Ndis802_11Encryption1Enabled;
4091 pBss->WPA.GroupCipher = Ndis802_11Encryption1Enabled;
4092 break;
4093 default:
4094 break;
4097 // if Cisco IE_WPA, break
4098 break;
4100 else if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7))
4102 pBss->bSES = TRUE;
4103 break;
4105 else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1)
4107 // if unsupported vendor specific IE
4108 break;
4110 // Skip OUI, version, and multicast suite
4111 // This part should be improved in the future when AP supported multiple cipher suite.
4112 // For now, it's OK since almost all APs have fixed cipher suite supported.
4113 // pTmp = (PUCHAR) pEid->Octet;
4114 pTmp += 11;
4116 // Cipher Suite Selectors from Spec P802.11i/D3.2 P26.
4117 // Value Meaning
4118 // 0 None
4119 // 1 WEP-40
4120 // 2 Tkip
4121 // 3 WRAP
4122 // 4 AES
4123 // 5 WEP-104
4124 // Parse group cipher
4125 switch (*pTmp)
4127 case 1:
4128 pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled;
4129 break;
4130 case 5:
4131 pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled;
4132 break;
4133 case 2:
4134 pBss->WPA.GroupCipher = Ndis802_11Encryption2Enabled;
4135 break;
4136 case 4:
4137 pBss->WPA.GroupCipher = Ndis802_11Encryption3Enabled;
4138 break;
4139 default:
4140 break;
4142 // number of unicast suite
4143 pTmp += 1;
4145 // skip all unicast cipher suites
4146 //Count = *(PUSHORT) pTmp;
4147 Count = (pTmp[1]<<8) + pTmp[0];
4148 pTmp += sizeof(USHORT);
4150 // Parsing all unicast cipher suite
4151 while (Count > 0)
4153 // Skip OUI
4154 pTmp += 3;
4155 TmpCipher = Ndis802_11WEPDisabled;
4156 switch (*pTmp)
4158 case 1:
4159 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4160 TmpCipher = Ndis802_11Encryption1Enabled;
4161 break;
4162 case 2:
4163 TmpCipher = Ndis802_11Encryption2Enabled;
4164 break;
4165 case 4:
4166 TmpCipher = Ndis802_11Encryption3Enabled;
4167 break;
4168 default:
4169 break;
4171 if (TmpCipher > pBss->WPA.PairCipher)
4173 // Move the lower cipher suite to PairCipherAux
4174 pBss->WPA.PairCipherAux = pBss->WPA.PairCipher;
4175 pBss->WPA.PairCipher = TmpCipher;
4177 else
4179 pBss->WPA.PairCipherAux = TmpCipher;
4181 pTmp++;
4182 Count--;
4185 // 4. get AKM suite counts
4186 //Count = *(PUSHORT) pTmp;
4187 Count = (pTmp[1]<<8) + pTmp[0];
4188 pTmp += sizeof(USHORT);
4189 pTmp += 3;
4191 switch (*pTmp)
4193 case 1:
4194 // Set AP support WPA mode
4195 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4196 pBss->AuthMode = Ndis802_11AuthModeWPA;
4197 else
4198 pBss->AuthModeAux = Ndis802_11AuthModeWPA;
4199 break;
4200 case 2:
4201 // Set AP support WPA mode
4202 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4203 pBss->AuthMode = Ndis802_11AuthModeWPAPSK;
4204 else
4205 pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK;
4206 break;
4207 default:
4208 break;
4210 pTmp += 1;
4212 // Fixed for WPA-None
4213 if (pBss->BssType == BSS_ADHOC)
4215 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4216 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4217 pBss->WepStatus = pBss->WPA.GroupCipher;
4218 // Patched bugs for old driver
4219 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4220 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4222 else
4223 pBss->WepStatus = pBss->WPA.PairCipher;
4225 // Check the Pair & Group, if different, turn on mixed mode flag
4226 if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher)
4227 pBss->WPA.bMixMode = TRUE;
4229 break;
4231 case IE_RSN:
4232 pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp;
4234 // 0. Version must be 1
4235 if (le2cpu16(pRsnHeader->Version) != 1)
4236 break;
4237 pTmp += sizeof(RSN_IE_HEADER_STRUCT);
4239 // 1. Check group cipher
4240 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4241 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4242 break;
4244 // Parse group cipher
4245 switch (pCipher->Type)
4247 case 1:
4248 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled;
4249 break;
4250 case 5:
4251 pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled;
4252 break;
4253 case 2:
4254 pBss->WPA2.GroupCipher = Ndis802_11Encryption2Enabled;
4255 break;
4256 case 4:
4257 pBss->WPA2.GroupCipher = Ndis802_11Encryption3Enabled;
4258 break;
4259 default:
4260 break;
4262 // set to correct offset for next parsing
4263 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4265 // 2. Get pairwise cipher counts
4266 //Count = *(PUSHORT) pTmp;
4267 Count = (pTmp[1]<<8) + pTmp[0];
4268 pTmp += sizeof(USHORT);
4270 // 3. Get pairwise cipher
4271 // Parsing all unicast cipher suite
4272 while (Count > 0)
4274 // Skip OUI
4275 pCipher = (PCIPHER_SUITE_STRUCT) pTmp;
4276 TmpCipher = Ndis802_11WEPDisabled;
4277 switch (pCipher->Type)
4279 case 1:
4280 case 5: // Although WEP is not allowed in WPA related auth mode, we parse it anyway
4281 TmpCipher = Ndis802_11Encryption1Enabled;
4282 break;
4283 case 2:
4284 TmpCipher = Ndis802_11Encryption2Enabled;
4285 break;
4286 case 4:
4287 TmpCipher = Ndis802_11Encryption3Enabled;
4288 break;
4289 default:
4290 break;
4292 if (TmpCipher > pBss->WPA2.PairCipher)
4294 // Move the lower cipher suite to PairCipherAux
4295 pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher;
4296 pBss->WPA2.PairCipher = TmpCipher;
4298 else
4300 pBss->WPA2.PairCipherAux = TmpCipher;
4302 pTmp += sizeof(CIPHER_SUITE_STRUCT);
4303 Count--;
4306 // 4. get AKM suite counts
4307 //Count = *(PUSHORT) pTmp;
4308 Count = (pTmp[1]<<8) + pTmp[0];
4309 pTmp += sizeof(USHORT);
4311 // 5. Get AKM ciphers
4312 pAKM = (PAKM_SUITE_STRUCT) pTmp;
4313 if (!RTMPEqualMemory(pTmp, RSN_OUI, 3))
4314 break;
4316 switch (pAKM->Type)
4318 case 1:
4319 // Set AP support WPA mode
4320 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4321 pBss->AuthMode = Ndis802_11AuthModeWPA2;
4322 else
4323 pBss->AuthModeAux = Ndis802_11AuthModeWPA2;
4324 break;
4325 case 2:
4326 // Set AP support WPA mode
4327 if (pBss->AuthMode == Ndis802_11AuthModeOpen)
4328 pBss->AuthMode = Ndis802_11AuthModeWPA2PSK;
4329 else
4330 pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK;
4331 break;
4332 default:
4333 break;
4335 pTmp += (Count * sizeof(AKM_SUITE_STRUCT));
4337 // Fixed for WPA-None
4338 if (pBss->BssType == BSS_ADHOC)
4340 pBss->AuthMode = Ndis802_11AuthModeWPANone;
4341 pBss->AuthModeAux = Ndis802_11AuthModeWPANone;
4342 pBss->WPA.PairCipherAux = pBss->WPA2.PairCipherAux;
4343 pBss->WPA.GroupCipher = pBss->WPA2.GroupCipher;
4344 pBss->WepStatus = pBss->WPA.GroupCipher;
4345 // Patched bugs for old driver
4346 if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)
4347 pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher;
4349 pBss->WepStatus = pBss->WPA2.PairCipher;
4351 // 6. Get RSN capability
4352 //pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;
4353 pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0];
4354 pTmp += sizeof(USHORT);
4356 // Check the Pair & Group, if different, turn on mixed mode flag
4357 if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher)
4358 pBss->WPA2.bMixMode = TRUE;
4360 break;
4361 default:
4362 break;
4364 Length -= (pEid->Len + 2);
4368 // ===========================================================================================
4369 // mac_table.c
4370 // ===========================================================================================
4372 /*! \brief generates a random mac address value for IBSS BSSID
4373 * \param Addr the bssid location
4374 * \return none
4375 * \pre
4376 * \post
4378 VOID MacAddrRandomBssid(
4379 IN PRTMP_ADAPTER pAd,
4380 OUT PUCHAR pAddr)
4382 INT i;
4384 for (i = 0; i < MAC_ADDR_LEN; i++)
4386 pAddr[i] = RandomByte(pAd);
4389 pAddr[0] = (pAddr[0] & 0xfe) | 0x02; // the first 2 bits must be 01xxxxxxxx
4392 /*! \brief init the management mac frame header
4393 * \param p_hdr mac header
4394 * \param subtype subtype of the frame
4395 * \param p_ds destination address, don't care if it is a broadcast address
4396 * \return none
4397 * \pre the station has the following information in the pAd->StaCfg
4398 * - bssid
4399 * - station address
4400 * \post
4401 * \note this function initializes the following field
4403 IRQL = PASSIVE_LEVEL
4404 IRQL = DISPATCH_LEVEL
4407 VOID MgtMacHeaderInit(
4408 IN PRTMP_ADAPTER pAd,
4409 IN OUT PHEADER_802_11 pHdr80211,
4410 IN UCHAR SubType,
4411 IN UCHAR ToDs,
4412 IN PUCHAR pDA,
4413 IN PUCHAR pBssid)
4415 NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11));
4417 pHdr80211->FC.Type = BTYPE_MGMT;
4418 pHdr80211->FC.SubType = SubType;
4419 pHdr80211->FC.ToDs = ToDs;
4420 COPY_MAC_ADDR(pHdr80211->Addr1, pDA);
4422 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4423 COPY_MAC_ADDR(pHdr80211->Addr2, pAd->CurrentAddress);
4425 COPY_MAC_ADDR(pHdr80211->Addr3, pBssid);
4428 // ===========================================================================================
4429 // mem_mgmt.c
4430 // ===========================================================================================
4432 /*!***************************************************************************
4433 * This routine build an outgoing frame, and fill all information specified
4434 * in argument list to the frame body. The actual frame size is the summation
4435 * of all arguments.
4436 * input params:
4437 * Buffer - pointer to a pre-allocated memory segment
4438 * args - a list of <int arg_size, arg> pairs.
4439 * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this
4440 * function will FAIL!!!
4441 * return:
4442 * Size of the buffer
4443 * usage:
4444 * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS);
4446 IRQL = PASSIVE_LEVEL
4447 IRQL = DISPATCH_LEVEL
4449 ****************************************************************************/
4450 ULONG MakeOutgoingFrame(
4451 OUT CHAR *Buffer,
4452 OUT ULONG *FrameLen, ...)
4454 CHAR *p;
4455 int leng;
4456 ULONG TotLeng;
4457 va_list Args;
4459 // calculates the total length
4460 TotLeng = 0;
4461 va_start(Args, FrameLen);
4464 leng = va_arg(Args, int);
4465 if (leng == END_OF_ARGS)
4467 break;
4469 p = va_arg(Args, PVOID);
4470 NdisMoveMemory(&Buffer[TotLeng], p, leng);
4471 TotLeng = TotLeng + leng;
4472 } while(TRUE);
4474 va_end(Args); /* clean up */
4475 *FrameLen = TotLeng;
4476 return TotLeng;
4479 // ===========================================================================================
4480 // mlme_queue.c
4481 // ===========================================================================================
4483 /*! \brief Initialize The MLME Queue, used by MLME Functions
4484 * \param *Queue The MLME Queue
4485 * \return Always Return NDIS_STATE_SUCCESS in this implementation
4486 * \pre
4487 * \post
4488 * \note Because this is done only once (at the init stage), no need to be locked
4490 IRQL = PASSIVE_LEVEL
4493 NDIS_STATUS MlmeQueueInit(
4494 IN MLME_QUEUE *Queue)
4496 INT i;
4498 NdisAllocateSpinLock(&Queue->Lock);
4500 Queue->Num = 0;
4501 Queue->Head = 0;
4502 Queue->Tail = 0;
4504 for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++)
4506 Queue->Entry[i].Occupied = FALSE;
4507 Queue->Entry[i].MsgLen = 0;
4508 NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE);
4511 return NDIS_STATUS_SUCCESS;
4514 /*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread
4515 * \param *Queue The MLME Queue
4516 * \param Machine The State Machine Id
4517 * \param MsgType The Message Type
4518 * \param MsgLen The Message length
4519 * \param *Msg The message pointer
4520 * \return TRUE if enqueue is successful, FALSE if the queue is full
4521 * \pre
4522 * \post
4523 * \note The message has to be initialized
4525 IRQL = PASSIVE_LEVEL
4526 IRQL = DISPATCH_LEVEL
4529 BOOLEAN MlmeEnqueue(
4530 IN PRTMP_ADAPTER pAd,
4531 IN ULONG Machine,
4532 IN ULONG MsgType,
4533 IN ULONG MsgLen,
4534 IN VOID *Msg)
4536 INT Tail;
4537 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4539 // Do nothing if the driver is starting halt state.
4540 // This might happen when timer already been fired before cancel timer with mlmehalt
4541 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4542 return FALSE;
4544 // First check the size, it MUST not exceed the mlme queue size
4545 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4547 DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen));
4548 return FALSE;
4551 if (MlmeQueueFull(Queue))
4553 return FALSE;
4556 NdisAcquireSpinLock(&(Queue->Lock));
4557 Tail = Queue->Tail;
4558 Queue->Tail++;
4559 Queue->Num++;
4560 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4562 Queue->Tail = 0;
4565 Queue->Entry[Tail].Wcid = RESERVED_WCID;
4566 Queue->Entry[Tail].Occupied = TRUE;
4567 Queue->Entry[Tail].Machine = Machine;
4568 Queue->Entry[Tail].MsgType = MsgType;
4569 Queue->Entry[Tail].MsgLen = MsgLen;
4571 if (Msg != NULL)
4573 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4576 NdisReleaseSpinLock(&(Queue->Lock));
4577 return TRUE;
4580 /*! \brief This function is used when Recv gets a MLME message
4581 * \param *Queue The MLME Queue
4582 * \param TimeStampHigh The upper 32 bit of timestamp
4583 * \param TimeStampLow The lower 32 bit of timestamp
4584 * \param Rssi The receiving RSSI strength
4585 * \param MsgLen The length of the message
4586 * \param *Msg The message pointer
4587 * \return TRUE if everything ok, FALSE otherwise (like Queue Full)
4588 * \pre
4589 * \post
4591 IRQL = DISPATCH_LEVEL
4594 BOOLEAN MlmeEnqueueForRecv(
4595 IN PRTMP_ADAPTER pAd,
4596 IN ULONG Wcid,
4597 IN ULONG TimeStampHigh,
4598 IN ULONG TimeStampLow,
4599 IN UCHAR Rssi0,
4600 IN UCHAR Rssi1,
4601 IN UCHAR Rssi2,
4602 IN ULONG MsgLen,
4603 IN VOID *Msg,
4604 IN UCHAR Signal)
4606 INT Tail, Machine;
4607 PFRAME_802_11 pFrame = (PFRAME_802_11)Msg;
4608 INT MsgType;
4609 MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue;
4611 // Do nothing if the driver is starting halt state.
4612 // This might happen when timer already been fired before cancel timer with mlmehalt
4613 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))
4615 DBGPRINT_ERR(("MlmeEnqueueForRecv: fRTMP_ADAPTER_HALT_IN_PROGRESS\n"));
4616 return FALSE;
4619 // First check the size, it MUST not exceed the mlme queue size
4620 if (MsgLen > MGMT_DMA_BUFFER_SIZE)
4622 DBGPRINT_ERR(("MlmeEnqueueForRecv: frame too large, size = %ld \n", MsgLen));
4623 return FALSE;
4626 if (MlmeQueueFull(Queue))
4628 return FALSE;
4631 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4633 if (!MsgTypeSubst(pAd, pFrame, &Machine, &MsgType))
4635 DBGPRINT_ERR(("MlmeEnqueueForRecv: un-recongnized mgmt->subtype=%d\n",pFrame->Hdr.FC.SubType));
4636 return FALSE;
4640 // OK, we got all the informations, it is time to put things into queue
4641 NdisAcquireSpinLock(&(Queue->Lock));
4642 Tail = Queue->Tail;
4643 Queue->Tail++;
4644 Queue->Num++;
4645 if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE)
4647 Queue->Tail = 0;
4649 Queue->Entry[Tail].Occupied = TRUE;
4650 Queue->Entry[Tail].Machine = Machine;
4651 Queue->Entry[Tail].MsgType = MsgType;
4652 Queue->Entry[Tail].MsgLen = MsgLen;
4653 Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow;
4654 Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh;
4655 Queue->Entry[Tail].Rssi0 = Rssi0;
4656 Queue->Entry[Tail].Rssi1 = Rssi1;
4657 Queue->Entry[Tail].Rssi2 = Rssi2;
4658 Queue->Entry[Tail].Signal = Signal;
4659 Queue->Entry[Tail].Wcid = (UCHAR)Wcid;
4661 Queue->Entry[Tail].Channel = pAd->LatchRfRegs.Channel;
4663 if (Msg != NULL)
4665 NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen);
4668 NdisReleaseSpinLock(&(Queue->Lock));
4670 RT28XX_MLME_HANDLER(pAd);
4672 return TRUE;
4676 /*! \brief Dequeue a message from the MLME Queue
4677 * \param *Queue The MLME Queue
4678 * \param *Elem The message dequeued from MLME Queue
4679 * \return TRUE if the Elem contains something, FALSE otherwise
4680 * \pre
4681 * \post
4683 IRQL = DISPATCH_LEVEL
4686 BOOLEAN MlmeDequeue(
4687 IN MLME_QUEUE *Queue,
4688 OUT MLME_QUEUE_ELEM **Elem)
4690 NdisAcquireSpinLock(&(Queue->Lock));
4691 *Elem = &(Queue->Entry[Queue->Head]);
4692 Queue->Num--;
4693 Queue->Head++;
4694 if (Queue->Head == MAX_LEN_OF_MLME_QUEUE)
4696 Queue->Head = 0;
4698 NdisReleaseSpinLock(&(Queue->Lock));
4699 return TRUE;
4702 // IRQL = DISPATCH_LEVEL
4703 VOID MlmeRestartStateMachine(
4704 IN PRTMP_ADAPTER pAd)
4706 MLME_QUEUE_ELEM *Elem = NULL;
4707 BOOLEAN Cancelled;
4709 DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n"));
4711 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4712 if(pAd->Mlme.bRunning)
4714 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4715 return;
4717 else
4719 pAd->Mlme.bRunning = TRUE;
4721 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4723 // Remove all Mlme queues elements
4724 while (!MlmeQueueEmpty(&pAd->Mlme.Queue))
4726 //From message type, determine which state machine I should drive
4727 if (MlmeDequeue(&pAd->Mlme.Queue, &Elem))
4729 // free MLME element
4730 Elem->Occupied = FALSE;
4731 Elem->MsgLen = 0;
4734 else {
4735 DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n"));
4739 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4741 // Cancel all timer events
4742 // Be careful to cancel new added timer
4743 RTMPCancelTimer(&pAd->MlmeAux.AssocTimer, &Cancelled);
4744 RTMPCancelTimer(&pAd->MlmeAux.ReassocTimer, &Cancelled);
4745 RTMPCancelTimer(&pAd->MlmeAux.DisassocTimer, &Cancelled);
4746 RTMPCancelTimer(&pAd->MlmeAux.AuthTimer, &Cancelled);
4747 RTMPCancelTimer(&pAd->MlmeAux.BeaconTimer, &Cancelled);
4748 RTMPCancelTimer(&pAd->MlmeAux.ScanTimer, &Cancelled);
4751 // Change back to original channel in case of doing scan
4752 AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE);
4753 AsicLockChannel(pAd, pAd->CommonCfg.Channel);
4755 // Resume MSDU which is turned off durning scan
4756 RTMPResumeMsduTransmission(pAd);
4758 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
4760 // Set all state machines back IDLE
4761 pAd->Mlme.CntlMachine.CurrState = CNTL_IDLE;
4762 pAd->Mlme.AssocMachine.CurrState = ASSOC_IDLE;
4763 pAd->Mlme.AuthMachine.CurrState = AUTH_REQ_IDLE;
4764 pAd->Mlme.AuthRspMachine.CurrState = AUTH_RSP_IDLE;
4765 pAd->Mlme.SyncMachine.CurrState = SYNC_IDLE;
4766 pAd->Mlme.ActMachine.CurrState = ACT_IDLE;
4769 // Remove running state
4770 NdisAcquireSpinLock(&pAd->Mlme.TaskLock);
4771 pAd->Mlme.bRunning = FALSE;
4772 NdisReleaseSpinLock(&pAd->Mlme.TaskLock);
4775 /*! \brief test if the MLME Queue is empty
4776 * \param *Queue The MLME Queue
4777 * \return TRUE if the Queue is empty, FALSE otherwise
4778 * \pre
4779 * \post
4781 IRQL = DISPATCH_LEVEL
4784 BOOLEAN MlmeQueueEmpty(
4785 IN MLME_QUEUE *Queue)
4787 BOOLEAN Ans;
4789 NdisAcquireSpinLock(&(Queue->Lock));
4790 Ans = (Queue->Num == 0);
4791 NdisReleaseSpinLock(&(Queue->Lock));
4793 return Ans;
4796 /*! \brief test if the MLME Queue is full
4797 * \param *Queue The MLME Queue
4798 * \return TRUE if the Queue is empty, FALSE otherwise
4799 * \pre
4800 * \post
4802 IRQL = PASSIVE_LEVEL
4803 IRQL = DISPATCH_LEVEL
4806 BOOLEAN MlmeQueueFull(
4807 IN MLME_QUEUE *Queue)
4809 BOOLEAN Ans;
4811 NdisAcquireSpinLock(&(Queue->Lock));
4812 Ans = (Queue->Num == MAX_LEN_OF_MLME_QUEUE || Queue->Entry[Queue->Tail].Occupied);
4813 NdisReleaseSpinLock(&(Queue->Lock));
4815 return Ans;
4818 /*! \brief The destructor of MLME Queue
4819 * \param
4820 * \return
4821 * \pre
4822 * \post
4823 * \note Clear Mlme Queue, Set Queue->Num to Zero.
4825 IRQL = PASSIVE_LEVEL
4828 VOID MlmeQueueDestroy(
4829 IN MLME_QUEUE *pQueue)
4831 NdisAcquireSpinLock(&(pQueue->Lock));
4832 pQueue->Num = 0;
4833 pQueue->Head = 0;
4834 pQueue->Tail = 0;
4835 NdisReleaseSpinLock(&(pQueue->Lock));
4836 NdisFreeSpinLock(&(pQueue->Lock));
4839 /*! \brief To substitute the message type if the message is coming from external
4840 * \param pFrame The frame received
4841 * \param *Machine The state machine
4842 * \param *MsgType the message type for the state machine
4843 * \return TRUE if the substitution is successful, FALSE otherwise
4844 * \pre
4845 * \post
4847 IRQL = DISPATCH_LEVEL
4850 BOOLEAN MsgTypeSubst(
4851 IN PRTMP_ADAPTER pAd,
4852 IN PFRAME_802_11 pFrame,
4853 OUT INT *Machine,
4854 OUT INT *MsgType)
4856 USHORT Seq;
4857 UCHAR EAPType;
4858 PUCHAR pData;
4860 // Pointer to start of data frames including SNAP header
4861 pData = (PUCHAR) pFrame + LENGTH_802_11;
4863 // The only data type will pass to this function is EAPOL frame
4864 if (pFrame->Hdr.FC.Type == BTYPE_DATA)
4866 if (NdisEqualMemory(SNAP_AIRONET, pData, LENGTH_802_1_H))
4868 // Cisco Aironet SNAP header
4869 *Machine = AIRONET_STATE_MACHINE;
4870 *MsgType = MT2_AIRONET_MSG;
4871 return (TRUE);
4874 *Machine = WPA_PSK_STATE_MACHINE;
4875 EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
4876 return(WpaMsgTypeSubst(EAPType, MsgType));
4880 switch (pFrame->Hdr.FC.SubType)
4882 case SUBTYPE_ASSOC_REQ:
4883 *Machine = ASSOC_STATE_MACHINE;
4884 *MsgType = MT2_PEER_ASSOC_REQ;
4885 break;
4886 case SUBTYPE_ASSOC_RSP:
4887 *Machine = ASSOC_STATE_MACHINE;
4888 *MsgType = MT2_PEER_ASSOC_RSP;
4889 break;
4890 case SUBTYPE_REASSOC_REQ:
4891 *Machine = ASSOC_STATE_MACHINE;
4892 *MsgType = MT2_PEER_REASSOC_REQ;
4893 break;
4894 case SUBTYPE_REASSOC_RSP:
4895 *Machine = ASSOC_STATE_MACHINE;
4896 *MsgType = MT2_PEER_REASSOC_RSP;
4897 break;
4898 case SUBTYPE_PROBE_REQ:
4899 *Machine = SYNC_STATE_MACHINE;
4900 *MsgType = MT2_PEER_PROBE_REQ;
4901 break;
4902 case SUBTYPE_PROBE_RSP:
4903 *Machine = SYNC_STATE_MACHINE;
4904 *MsgType = MT2_PEER_PROBE_RSP;
4905 break;
4906 case SUBTYPE_BEACON:
4907 *Machine = SYNC_STATE_MACHINE;
4908 *MsgType = MT2_PEER_BEACON;
4909 break;
4910 case SUBTYPE_ATIM:
4911 *Machine = SYNC_STATE_MACHINE;
4912 *MsgType = MT2_PEER_ATIM;
4913 break;
4914 case SUBTYPE_DISASSOC:
4915 *Machine = ASSOC_STATE_MACHINE;
4916 *MsgType = MT2_PEER_DISASSOC_REQ;
4917 break;
4918 case SUBTYPE_AUTH:
4919 // get the sequence number from payload 24 Mac Header + 2 bytes algorithm
4920 NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
4921 if (Seq == 1 || Seq == 3)
4923 *Machine = AUTH_RSP_STATE_MACHINE;
4924 *MsgType = MT2_PEER_AUTH_ODD;
4926 else if (Seq == 2 || Seq == 4)
4928 *Machine = AUTH_STATE_MACHINE;
4929 *MsgType = MT2_PEER_AUTH_EVEN;
4931 else
4933 return FALSE;
4935 break;
4936 case SUBTYPE_DEAUTH:
4937 *Machine = AUTH_RSP_STATE_MACHINE;
4938 *MsgType = MT2_PEER_DEAUTH;
4939 break;
4940 case SUBTYPE_ACTION:
4941 *Machine = ACTION_STATE_MACHINE;
4942 // Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support
4943 if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
4945 *MsgType = MT2_ACT_INVALID;
4947 else
4949 *MsgType = (pFrame->Octet[0]&0x7F);
4951 break;
4952 default:
4953 return FALSE;
4954 break;
4957 return TRUE;
4960 // ===========================================================================================
4961 // state_machine.c
4962 // ===========================================================================================
4964 /*! \brief Initialize the state machine.
4965 * \param *S pointer to the state machine
4966 * \param Trans State machine transition function
4967 * \param StNr number of states
4968 * \param MsgNr number of messages
4969 * \param DefFunc default function, when there is invalid state/message combination
4970 * \param InitState initial state of the state machine
4971 * \param Base StateMachine base, internal use only
4972 * \pre p_sm should be a legal pointer
4973 * \post
4975 IRQL = PASSIVE_LEVEL
4978 VOID StateMachineInit(
4979 IN STATE_MACHINE *S,
4980 IN STATE_MACHINE_FUNC Trans[],
4981 IN ULONG StNr,
4982 IN ULONG MsgNr,
4983 IN STATE_MACHINE_FUNC DefFunc,
4984 IN ULONG InitState,
4985 IN ULONG Base)
4987 ULONG i, j;
4989 // set number of states and messages
4990 S->NrState = StNr;
4991 S->NrMsg = MsgNr;
4992 S->Base = Base;
4994 S->TransFunc = Trans;
4996 // init all state transition to default function
4997 for (i = 0; i < StNr; i++)
4999 for (j = 0; j < MsgNr; j++)
5001 S->TransFunc[i * MsgNr + j] = DefFunc;
5005 // set the starting state
5006 S->CurrState = InitState;
5009 /*! \brief This function fills in the function pointer into the cell in the state machine
5010 * \param *S pointer to the state machine
5011 * \param St state
5012 * \param Msg incoming message
5013 * \param f the function to be executed when (state, message) combination occurs at the state machine
5014 * \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
5015 * \post
5017 IRQL = PASSIVE_LEVEL
5020 VOID StateMachineSetAction(
5021 IN STATE_MACHINE *S,
5022 IN ULONG St,
5023 IN ULONG Msg,
5024 IN STATE_MACHINE_FUNC Func)
5026 ULONG MsgIdx;
5028 MsgIdx = Msg - S->Base;
5030 if (St < S->NrState && MsgIdx < S->NrMsg)
5032 // boundary checking before setting the action
5033 S->TransFunc[St * S->NrMsg + MsgIdx] = Func;
5037 /*! \brief This function does the state transition
5038 * \param *Adapter the NIC adapter pointer
5039 * \param *S the state machine
5040 * \param *Elem the message to be executed
5041 * \return None
5043 IRQL = DISPATCH_LEVEL
5046 VOID StateMachinePerformAction(
5047 IN PRTMP_ADAPTER pAd,
5048 IN STATE_MACHINE *S,
5049 IN MLME_QUEUE_ELEM *Elem)
5051 (*(S->TransFunc[S->CurrState * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem);
5055 ==========================================================================
5056 Description:
5057 The drop function, when machine executes this, the message is simply
5058 ignored. This function does nothing, the message is freed in
5059 StateMachinePerformAction()
5060 ==========================================================================
5062 VOID Drop(
5063 IN PRTMP_ADAPTER pAd,
5064 IN MLME_QUEUE_ELEM *Elem)
5068 // ===========================================================================================
5069 // lfsr.c
5070 // ===========================================================================================
5073 ==========================================================================
5074 Description:
5076 IRQL = PASSIVE_LEVEL
5078 ==========================================================================
5080 VOID LfsrInit(
5081 IN PRTMP_ADAPTER pAd,
5082 IN ULONG Seed)
5084 if (Seed == 0)
5085 pAd->Mlme.ShiftReg = 1;
5086 else
5087 pAd->Mlme.ShiftReg = Seed;
5091 ==========================================================================
5092 Description:
5093 ==========================================================================
5095 UCHAR RandomByte(
5096 IN PRTMP_ADAPTER pAd)
5098 ULONG i;
5099 UCHAR R, Result;
5101 R = 0;
5103 if (pAd->Mlme.ShiftReg == 0)
5104 NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg);
5106 for (i = 0; i < 8; i++)
5108 if (pAd->Mlme.ShiftReg & 0x00000001)
5110 pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000;
5111 Result = 1;
5113 else
5115 pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1;
5116 Result = 0;
5118 R = (R << 1) | Result;
5121 return R;
5124 VOID AsicUpdateAutoFallBackTable(
5125 IN PRTMP_ADAPTER pAd,
5126 IN PUCHAR pRateTable)
5128 UCHAR i;
5129 HT_FBK_CFG0_STRUC HtCfg0;
5130 HT_FBK_CFG1_STRUC HtCfg1;
5131 LG_FBK_CFG0_STRUC LgCfg0;
5132 LG_FBK_CFG1_STRUC LgCfg1;
5133 PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate;
5135 // set to initial value
5136 HtCfg0.word = 0x65432100;
5137 HtCfg1.word = 0xedcba988;
5138 LgCfg0.word = 0xedcba988;
5139 LgCfg1.word = 0x00002100;
5141 pNextTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1;
5142 for (i = 1; i < *((PUCHAR) pRateTable); i++)
5144 pCurrTxRate = (PRTMP_TX_RATE_SWITCH)pRateTable+1+i;
5145 switch (pCurrTxRate->Mode)
5147 case 0: //CCK
5148 break;
5149 case 1: //OFDM
5151 switch(pCurrTxRate->CurrMCS)
5153 case 0:
5154 LgCfg0.field.OFDMMCS0FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5155 break;
5156 case 1:
5157 LgCfg0.field.OFDMMCS1FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5158 break;
5159 case 2:
5160 LgCfg0.field.OFDMMCS2FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5161 break;
5162 case 3:
5163 LgCfg0.field.OFDMMCS3FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5164 break;
5165 case 4:
5166 LgCfg0.field.OFDMMCS4FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5167 break;
5168 case 5:
5169 LgCfg0.field.OFDMMCS5FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5170 break;
5171 case 6:
5172 LgCfg0.field.OFDMMCS6FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5173 break;
5174 case 7:
5175 LgCfg0.field.OFDMMCS7FBK = (pNextTxRate->Mode == MODE_OFDM) ? (pNextTxRate->CurrMCS+8): pNextTxRate->CurrMCS;
5176 break;
5179 break;
5180 #ifdef DOT11_N_SUPPORT
5181 case 2: //HT-MIX
5182 case 3: //HT-GF
5184 if ((pNextTxRate->Mode >= MODE_HTMIX) && (pCurrTxRate->CurrMCS != pNextTxRate->CurrMCS))
5186 switch(pCurrTxRate->CurrMCS)
5188 case 0:
5189 HtCfg0.field.HTMCS0FBK = pNextTxRate->CurrMCS;
5190 break;
5191 case 1:
5192 HtCfg0.field.HTMCS1FBK = pNextTxRate->CurrMCS;
5193 break;
5194 case 2:
5195 HtCfg0.field.HTMCS2FBK = pNextTxRate->CurrMCS;
5196 break;
5197 case 3:
5198 HtCfg0.field.HTMCS3FBK = pNextTxRate->CurrMCS;
5199 break;
5200 case 4:
5201 HtCfg0.field.HTMCS4FBK = pNextTxRate->CurrMCS;
5202 break;
5203 case 5:
5204 HtCfg0.field.HTMCS5FBK = pNextTxRate->CurrMCS;
5205 break;
5206 case 6:
5207 HtCfg0.field.HTMCS6FBK = pNextTxRate->CurrMCS;
5208 break;
5209 case 7:
5210 HtCfg0.field.HTMCS7FBK = pNextTxRate->CurrMCS;
5211 break;
5212 case 8:
5213 HtCfg1.field.HTMCS8FBK = pNextTxRate->CurrMCS;
5214 break;
5215 case 9:
5216 HtCfg1.field.HTMCS9FBK = pNextTxRate->CurrMCS;
5217 break;
5218 case 10:
5219 HtCfg1.field.HTMCS10FBK = pNextTxRate->CurrMCS;
5220 break;
5221 case 11:
5222 HtCfg1.field.HTMCS11FBK = pNextTxRate->CurrMCS;
5223 break;
5224 case 12:
5225 HtCfg1.field.HTMCS12FBK = pNextTxRate->CurrMCS;
5226 break;
5227 case 13:
5228 HtCfg1.field.HTMCS13FBK = pNextTxRate->CurrMCS;
5229 break;
5230 case 14:
5231 HtCfg1.field.HTMCS14FBK = pNextTxRate->CurrMCS;
5232 break;
5233 case 15:
5234 HtCfg1.field.HTMCS15FBK = pNextTxRate->CurrMCS;
5235 break;
5236 default:
5237 DBGPRINT(RT_DEBUG_ERROR, ("AsicUpdateAutoFallBackTable: not support CurrMCS=%d\n", pCurrTxRate->CurrMCS));
5241 break;
5242 #endif // DOT11_N_SUPPORT //
5245 pNextTxRate = pCurrTxRate;
5248 RTMP_IO_WRITE32(pAd, HT_FBK_CFG0, HtCfg0.word);
5249 RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, HtCfg1.word);
5250 RTMP_IO_WRITE32(pAd, LG_FBK_CFG0, LgCfg0.word);
5251 RTMP_IO_WRITE32(pAd, LG_FBK_CFG1, LgCfg1.word);
5255 ========================================================================
5257 Routine Description:
5258 Set MAC register value according operation mode.
5259 OperationMode AND bNonGFExist are for MM and GF Proteciton.
5260 If MM or GF mask is not set, those passing argument doesn't not take effect.
5262 Operation mode meaning:
5263 = 0 : Pure HT, no preotection.
5264 = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS.
5265 = 0x10: No Transmission in 40M is protected.
5266 = 0x11: Transmission in both 40M and 20M shall be protected
5267 if (bNonGFExist)
5268 we should choose not to use GF. But still set correct ASIC registers.
5269 ========================================================================
5271 VOID AsicUpdateProtect(
5272 IN PRTMP_ADAPTER pAd,
5273 IN USHORT OperationMode,
5274 IN UCHAR SetMask,
5275 IN BOOLEAN bDisableBGProtect,
5276 IN BOOLEAN bNonGFExist)
5278 PROT_CFG_STRUC ProtCfg, ProtCfg4;
5279 UINT32 Protect[6];
5280 USHORT offset;
5281 UCHAR i;
5282 UINT32 MacReg = 0;
5284 #ifdef DOT11_N_SUPPORT
5285 if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8))
5287 return;
5290 if (pAd->BATable.numAsOriginator)
5293 // enable the RTS/CTS to avoid channel collision
5295 SetMask = ALLN_SETPROTECT;
5296 OperationMode = 8;
5298 #endif // DOT11_N_SUPPORT //
5300 // Config ASIC RTS threshold register
5301 RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg);
5302 MacReg &= 0xFF0000FF;
5303 #if 0
5304 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5305 #else
5306 // If the user want disable RtsThreshold and enable Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096
5307 if ((
5308 #ifdef DOT11_N_SUPPORT
5309 (pAd->CommonCfg.BACapability.field.AmsduEnable) ||
5310 #endif // DOT11_N_SUPPORT //
5311 (pAd->CommonCfg.bAggregationCapable == TRUE))
5312 && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)
5314 MacReg |= (0x1000 << 8);
5316 else
5318 MacReg |= (pAd->CommonCfg.RtsThreshold << 8);
5320 #endif
5322 RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg);
5324 // Initial common protection settings
5325 RTMPZeroMemory(Protect, sizeof(Protect));
5326 ProtCfg4.word = 0;
5327 ProtCfg.word = 0;
5328 ProtCfg.field.TxopAllowGF40 = 1;
5329 ProtCfg.field.TxopAllowGF20 = 1;
5330 ProtCfg.field.TxopAllowMM40 = 1;
5331 ProtCfg.field.TxopAllowMM20 = 1;
5332 ProtCfg.field.TxopAllowOfdm = 1;
5333 ProtCfg.field.TxopAllowCck = 1;
5334 ProtCfg.field.RTSThEn = 1;
5335 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5337 // update PHY mode and rate
5338 if (pAd->CommonCfg.Channel > 14)
5339 ProtCfg.field.ProtectRate = 0x4000;
5340 ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate;
5342 // Handle legacy(B/G) protection
5343 if (bDisableBGProtect)
5345 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5346 ProtCfg.field.ProtectCtrl = 0;
5347 Protect[0] = ProtCfg.word;
5348 Protect[1] = ProtCfg.word;
5350 else
5352 //ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;
5353 ProtCfg.field.ProtectCtrl = 0; // CCK do not need to be protected
5354 Protect[0] = ProtCfg.word;
5355 ProtCfg.field.ProtectCtrl = ASIC_CTS; // OFDM needs using CCK to protect
5356 Protect[1] = ProtCfg.word;
5359 #ifdef DOT11_N_SUPPORT
5360 // Decide HT frame protection.
5361 if ((SetMask & ALLN_SETPROTECT) != 0)
5363 switch(OperationMode)
5365 case 0x0:
5366 // NO PROTECT
5367 // 1.All STAs in the BSS are 20/40 MHz HT
5368 // 2. in ai 20/40MHz BSS
5369 // 3. all STAs are 20MHz in a 20MHz BSS
5370 // Pure HT. no protection.
5372 // MM20_PROT_CFG
5373 // Reserved (31:27)
5374 // PROT_TXOP(25:20) -- 010111
5375 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5376 // PROT_CTRL(17:16) -- 00 (None)
5377 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5378 Protect[2] = 0x01744004;
5380 // MM40_PROT_CFG
5381 // Reserved (31:27)
5382 // PROT_TXOP(25:20) -- 111111
5383 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5384 // PROT_CTRL(17:16) -- 00 (None)
5385 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5386 Protect[3] = 0x03f44084;
5388 // CF20_PROT_CFG
5389 // Reserved (31:27)
5390 // PROT_TXOP(25:20) -- 010111
5391 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5392 // PROT_CTRL(17:16) -- 00 (None)
5393 // PROT_RATE(15:0) -- 0x4004 (OFDM 24M)
5394 Protect[4] = 0x01744004;
5396 // CF40_PROT_CFG
5397 // Reserved (31:27)
5398 // PROT_TXOP(25:20) -- 111111
5399 // PROT_NAV(19:18) -- 01 (Short NAV protection)
5400 // PROT_CTRL(17:16) -- 00 (None)
5401 // PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)
5402 Protect[5] = 0x03f44084;
5404 if (bNonGFExist)
5406 // PROT_NAV(19:18) -- 01 (Short NAV protectiion)
5407 // PROT_CTRL(17:16) -- 01 (RTS/CTS)
5408 Protect[4] = 0x01754004;
5409 Protect[5] = 0x03f54084;
5411 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5412 break;
5414 case 1:
5415 // This is "HT non-member protection mode."
5416 // If there may be non-HT STAs my BSS
5417 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5418 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5419 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5421 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5422 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083;
5424 //Assign Protection method for 20&40 MHz packets
5425 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5426 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5427 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5428 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5429 Protect[2] = ProtCfg.word;
5430 Protect[3] = ProtCfg4.word;
5431 Protect[4] = ProtCfg.word;
5432 Protect[5] = ProtCfg4.word;
5433 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5434 break;
5436 case 2:
5437 // If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets
5438 ProtCfg.word = 0x01744004; // PROT_CTRL(17:16) : 0 (None)
5439 ProtCfg4.word = 0x03f44084; // duplicaet legacy 24M. BW set 1.
5441 //Assign Protection method for 40MHz packets
5442 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5443 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5444 Protect[2] = ProtCfg.word;
5445 Protect[3] = ProtCfg4.word;
5446 if (bNonGFExist)
5448 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5449 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5451 Protect[4] = ProtCfg.word;
5452 Protect[5] = ProtCfg4.word;
5454 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE;
5455 break;
5457 case 3:
5458 // HT mixed mode. PROTECT ALL!
5459 // Assign Rate
5460 ProtCfg.word = 0x01744004; //duplicaet legacy 24M. BW set 1.
5461 ProtCfg4.word = 0x03f44084;
5462 // both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the
5463 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED))
5465 ProtCfg.word = 0x01740003; //ERP use Protection bit is set, use protection rate at Clause 18..
5466 ProtCfg4.word = 0x03f40003; // Don't duplicate RTS/CTS in CCK mode. 0x03f40083
5468 //Assign Protection method for 20&40 MHz packets
5469 ProtCfg.field.ProtectCtrl = ASIC_RTS;
5470 ProtCfg.field.ProtectNav = ASIC_SHORTNAV;
5471 ProtCfg4.field.ProtectCtrl = ASIC_RTS;
5472 ProtCfg4.field.ProtectNav = ASIC_SHORTNAV;
5473 Protect[2] = ProtCfg.word;
5474 Protect[3] = ProtCfg4.word;
5475 Protect[4] = ProtCfg.word;
5476 Protect[5] = ProtCfg4.word;
5477 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5478 break;
5480 case 8:
5481 // Special on for Atheros problem n chip.
5482 Protect[2] = 0x01754004;
5483 Protect[3] = 0x03f54084;
5484 Protect[4] = 0x01754004;
5485 Protect[5] = 0x03f54084;
5486 pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE;
5487 break;
5490 #endif // DOT11_N_SUPPORT //
5492 offset = CCK_PROT_CFG;
5493 for (i = 0;i < 6;i++)
5495 if ((SetMask & (1<< i)))
5497 RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]);
5503 ==========================================================================
5504 Description:
5506 IRQL = PASSIVE_LEVEL
5507 IRQL = DISPATCH_LEVEL
5509 ==========================================================================
5511 VOID AsicSwitchChannel(
5512 IN PRTMP_ADAPTER pAd,
5513 IN UCHAR Channel,
5514 IN BOOLEAN bScan)
5516 ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0;
5517 CHAR TxPwer = 0, TxPwer2 = DEFAULT_RF_TX_POWER; //Bbp94 = BBPR94_DEFAULT, TxPwer2 = DEFAULT_RF_TX_POWER;
5518 UCHAR index;
5519 UINT32 Value = 0; //BbpReg, Value;
5520 RTMP_RF_REGS *RFRegTable;
5522 // Search Tx power value
5523 for (index = 0; index < pAd->ChannelListNum; index++)
5525 if (Channel == pAd->ChannelList[index].Channel)
5527 TxPwer = pAd->ChannelList[index].Power;
5528 TxPwer2 = pAd->ChannelList[index].Power2;
5529 break;
5533 if (index == MAX_NUM_OF_CHANNELS)
5535 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: Cant find the Channel#%d \n", Channel));
5539 RFRegTable = RF2850RegTable;
5541 switch (pAd->RfIcType)
5543 case RFIC_2820:
5544 case RFIC_2850:
5545 case RFIC_2720:
5546 case RFIC_2750:
5548 for (index = 0; index < NUM_OF_2850_CHNL; index++)
5550 if (Channel == RFRegTable[index].Channel)
5552 R2 = RFRegTable[index].R2;
5553 if (pAd->Antenna.field.TxPath == 1)
5555 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
5558 if (pAd->Antenna.field.RxPath == 2)
5560 R2 |= 0x40; // write 1 to off Rxpath.
5562 else if (pAd->Antenna.field.RxPath == 1)
5564 R2 |= 0x20040; // write 1 to off RxPath
5567 if (Channel > 14)
5569 // initialize R3, R4
5570 R3 = (RFRegTable[index].R3 & 0xffffc1ff);
5571 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15);
5573 // 5G band power range: 0xF9~0X0F, TX0 Reg3 bit9/TX1 Reg4 bit6="0" means the TX power reduce 7dB
5574 // R3
5575 if ((TxPwer >= -7) && (TxPwer < 0))
5577 TxPwer = (7+TxPwer);
5578 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5579 R3 |= (TxPwer << 10);
5580 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer=%d \n", TxPwer));
5582 else
5584 TxPwer = (TxPwer > 0xF) ? (0xF) : (TxPwer);
5585 R3 |= (TxPwer << 10) | (1 << 9);
5588 // R4
5589 if ((TxPwer2 >= -7) && (TxPwer2 < 0))
5591 TxPwer2 = (7+TxPwer2);
5592 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5593 R4 |= (TxPwer2 << 7);
5594 DBGPRINT(RT_DEBUG_ERROR, ("AsicSwitchChannel: TxPwer2=%d \n", TxPwer2));
5596 else
5598 TxPwer2 = (TxPwer2 > 0xF) ? (0xF) : (TxPwer2);
5599 R4 |= (TxPwer2 << 7) | (1 << 6);
5602 else
5604 R3 = (RFRegTable[index].R3 & 0xffffc1ff) | (TxPwer << 9); // set TX power0
5605 R4 = (RFRegTable[index].R4 & (~0x001f87c0)) | (pAd->RfFreqOffset << 15) | (TxPwer2 <<6);// Set freq Offset & TxPwr1
5608 // Based on BBP current mode before changing RF channel.
5609 if (!bScan && (pAd->CommonCfg.BBPCurrentBW == BW_40))
5611 R4 |=0x200000;
5614 // Update variables
5615 pAd->LatchRfRegs.Channel = Channel;
5616 pAd->LatchRfRegs.R1 = RFRegTable[index].R1;
5617 pAd->LatchRfRegs.R2 = R2;
5618 pAd->LatchRfRegs.R3 = R3;
5619 pAd->LatchRfRegs.R4 = R4;
5621 // Set RF value 1's set R3[bit2] = [0]
5622 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5623 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5624 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5625 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5627 RTMPusecDelay(200);
5629 // Set RF value 2's set R3[bit2] = [1]
5630 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5631 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5632 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 | 0x04));
5633 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5635 RTMPusecDelay(200);
5637 // Set RF value 3's set R3[bit2] = [0]
5638 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R1);
5639 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R2);
5640 RTMP_RF_IO_WRITE32(pAd, (pAd->LatchRfRegs.R3 & (~0x04)));
5641 RTMP_RF_IO_WRITE32(pAd, pAd->LatchRfRegs.R4);
5643 break;
5646 break;
5648 default:
5649 break;
5653 // Change BBP setting during siwtch from a->g, g->a
5654 if (Channel <= 14)
5656 ULONG TxPinCfg = 0x00050F0A;//Gary 2007/08/09 0x050A0A
5658 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5659 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5660 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5661 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.
5662 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5664 // Rx High power VGA offset for LNA select
5665 if (pAd->NicConfig2.field.ExternalLNAForG)
5667 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x62);
5668 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5670 else
5672 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0x84);
5673 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5676 // 5G band selection PIN, bit1 and bit2 are complement
5677 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5678 Value &= (~0x6);
5679 Value |= (0x04);
5680 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5682 // Turn off unused PA or LNA when only 1T or 1R
5683 if (pAd->Antenna.field.TxPath == 1)
5685 TxPinCfg &= 0xFFFFFFF3;
5687 if (pAd->Antenna.field.RxPath == 1)
5689 TxPinCfg &= 0xFFFFF3FF;
5692 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5694 else
5696 ULONG TxPinCfg = 0x00050F05;//Gary 2007/8/9 0x050505
5698 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - GET_LNA_GAIN(pAd)));
5699 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - GET_LNA_GAIN(pAd)));
5700 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - GET_LNA_GAIN(pAd)));
5701 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.
5702 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2);
5704 // Rx High power VGA offset for LNA select
5705 if (pAd->NicConfig2.field.ExternalLNAForA)
5707 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x46);
5709 else
5711 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R75, 0x50);
5714 // 5G band selection PIN, bit1 and bit2 are complement
5715 RTMP_IO_READ32(pAd, TX_BAND_CFG, &Value);
5716 Value &= (~0x6);
5717 Value |= (0x02);
5718 RTMP_IO_WRITE32(pAd, TX_BAND_CFG, Value);
5720 // Turn off unused PA or LNA when only 1T or 1R
5721 if (pAd->Antenna.field.TxPath == 1)
5723 TxPinCfg &= 0xFFFFFFF3;
5725 if (pAd->Antenna.field.RxPath == 1)
5727 TxPinCfg &= 0xFFFFF3FF;
5730 RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg);
5733 // R66 should be set according to Channel and use 20MHz when scanning
5734 //RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, (0x2E + GET_LNA_GAIN(pAd)));
5735 if (bScan)
5736 RTMPSetAGCInitValue(pAd, BW_20);
5737 else
5738 RTMPSetAGCInitValue(pAd, pAd->CommonCfg.BBPCurrentBW);
5741 // On 11A, We should delay and wait RF/BBP to be stable
5742 // and the appropriate time should be 1000 micro seconds
5743 // 2005/06/05 - On 11G, We also need this delay time. Otherwise it's difficult to pass the WHQL.
5745 RTMPusecDelay(1000);
5747 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",
5748 Channel,
5749 pAd->RfIcType,
5750 (R3 & 0x00003e00) >> 9,
5751 (R4 & 0x000007c0) >> 6,
5752 pAd->Antenna.field.TxPath,
5753 pAd->LatchRfRegs.R1,
5754 pAd->LatchRfRegs.R2,
5755 pAd->LatchRfRegs.R3,
5756 pAd->LatchRfRegs.R4));
5760 ==========================================================================
5761 Description:
5762 This function is required for 2421 only, and should not be used during
5763 site survey. It's only required after NIC decided to stay at a channel
5764 for a longer period.
5765 When this function is called, it's always after AsicSwitchChannel().
5767 IRQL = PASSIVE_LEVEL
5768 IRQL = DISPATCH_LEVEL
5770 ==========================================================================
5772 VOID AsicLockChannel(
5773 IN PRTMP_ADAPTER pAd,
5774 IN UCHAR Channel)
5779 ==========================================================================
5780 Description:
5782 IRQL = PASSIVE_LEVEL
5783 IRQL = DISPATCH_LEVEL
5785 ==========================================================================
5787 VOID AsicAntennaSelect(
5788 IN PRTMP_ADAPTER pAd,
5789 IN UCHAR Channel)
5794 ========================================================================
5796 Routine Description:
5797 Antenna miscellaneous setting.
5799 Arguments:
5800 pAd Pointer to our adapter
5801 BandState Indicate current Band State.
5803 Return Value:
5804 None
5806 IRQL <= DISPATCH_LEVEL
5808 Note:
5809 1.) Frame End type control
5810 only valid for G only (RF_2527 & RF_2529)
5811 0: means DPDT, set BBP R4 bit 5 to 1
5812 1: means SPDT, set BBP R4 bit 5 to 0
5815 ========================================================================
5817 VOID AsicAntennaSetting(
5818 IN PRTMP_ADAPTER pAd,
5819 IN ABGBAND_STATE BandState)
5823 VOID AsicRfTuningExec(
5824 IN PVOID SystemSpecific1,
5825 IN PVOID FunctionContext,
5826 IN PVOID SystemSpecific2,
5827 IN PVOID SystemSpecific3)
5832 ==========================================================================
5833 Description:
5834 Gives CCK TX rate 2 more dB TX power.
5835 This routine works only in LINK UP in INFRASTRUCTURE mode.
5837 calculate desired Tx power in RF R3.Tx0~5, should consider -
5838 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment)
5839 1. TxPowerPercentage
5840 2. auto calibration based on TSSI feedback
5841 3. extra 2 db for CCK
5842 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP
5844 NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment),
5845 it should be called AFTER MlmeDynamicTxRatSwitching()
5846 ==========================================================================
5848 VOID AsicAdjustTxPower(
5849 IN PRTMP_ADAPTER pAd)
5851 INT i, j;
5852 CHAR DeltaPwr = 0;
5853 BOOLEAN bAutoTxAgc = FALSE;
5854 UCHAR TssiRef, *pTssiMinusBoundary, *pTssiPlusBoundary, TxAgcStep;
5855 UCHAR BbpR1 = 0, BbpR49 = 0, idx;
5856 PCHAR pTxAgcCompensate;
5857 ULONG TxPwr[5];
5858 CHAR Value;
5860 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)
5861 || (pAd->bPCIclkOff == TRUE)
5862 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF)
5863 || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
5864 return;
5866 if (pAd->CommonCfg.BBPCurrentBW == BW_40)
5868 if (pAd->CommonCfg.CentralChannel > 14)
5870 TxPwr[0] = pAd->Tx40MPwrCfgABand[0];
5871 TxPwr[1] = pAd->Tx40MPwrCfgABand[1];
5872 TxPwr[2] = pAd->Tx40MPwrCfgABand[2];
5873 TxPwr[3] = pAd->Tx40MPwrCfgABand[3];
5874 TxPwr[4] = pAd->Tx40MPwrCfgABand[4];
5876 else
5878 TxPwr[0] = pAd->Tx40MPwrCfgGBand[0];
5879 TxPwr[1] = pAd->Tx40MPwrCfgGBand[1];
5880 TxPwr[2] = pAd->Tx40MPwrCfgGBand[2];
5881 TxPwr[3] = pAd->Tx40MPwrCfgGBand[3];
5882 TxPwr[4] = pAd->Tx40MPwrCfgGBand[4];
5885 else
5887 if (pAd->CommonCfg.Channel > 14)
5889 TxPwr[0] = pAd->Tx20MPwrCfgABand[0];
5890 TxPwr[1] = pAd->Tx20MPwrCfgABand[1];
5891 TxPwr[2] = pAd->Tx20MPwrCfgABand[2];
5892 TxPwr[3] = pAd->Tx20MPwrCfgABand[3];
5893 TxPwr[4] = pAd->Tx20MPwrCfgABand[4];
5895 else
5897 TxPwr[0] = pAd->Tx20MPwrCfgGBand[0];
5898 TxPwr[1] = pAd->Tx20MPwrCfgGBand[1];
5899 TxPwr[2] = pAd->Tx20MPwrCfgGBand[2];
5900 TxPwr[3] = pAd->Tx20MPwrCfgGBand[3];
5901 TxPwr[4] = pAd->Tx20MPwrCfgGBand[4];
5905 // TX power compensation for temperature variation based on TSSI. try every 4 second
5906 if (pAd->Mlme.OneSecPeriodicRound % 4 == 0)
5908 if (pAd->CommonCfg.Channel <= 14)
5910 /* bg channel */
5911 bAutoTxAgc = pAd->bAutoTxAgcG;
5912 TssiRef = pAd->TssiRefG;
5913 pTssiMinusBoundary = &pAd->TssiMinusBoundaryG[0];
5914 pTssiPlusBoundary = &pAd->TssiPlusBoundaryG[0];
5915 TxAgcStep = pAd->TxAgcStepG;
5916 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5918 else
5920 /* a channel */
5921 bAutoTxAgc = pAd->bAutoTxAgcA;
5922 TssiRef = pAd->TssiRefA;
5923 pTssiMinusBoundary = &pAd->TssiMinusBoundaryA[0];
5924 pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0];
5925 TxAgcStep = pAd->TxAgcStepA;
5926 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5929 if (bAutoTxAgc)
5931 /* BbpR1 is unsigned char */
5932 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &BbpR49);
5934 /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */
5935 /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */
5936 /* step value is defined in pAd->TxAgcStepG for tx power value */
5938 /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */
5939 /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0
5940 above value are examined in mass factory production */
5941 /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */
5943 /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */
5944 /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */
5945 /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */
5947 if (BbpR49 > pTssiMinusBoundary[1])
5949 // Reading is larger than the reference value
5950 // check for how large we need to decrease the Tx power
5951 for (idx = 1; idx < 5; idx++)
5953 if (BbpR49 <= pTssiMinusBoundary[idx]) // Found the range
5954 break;
5956 // The index is the step we should decrease, idx = 0 means there is nothing to compensate
5957 *pTxAgcCompensate = -(TxAgcStep * (idx-1));
5959 DeltaPwr += (*pTxAgcCompensate);
5960 DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n",
5961 BbpR49, TssiRef, TxAgcStep, idx-1));
5963 else if (BbpR49 < pTssiPlusBoundary[1])
5965 // Reading is smaller than the reference value
5966 // check for how large we need to increase the Tx power
5967 for (idx = 1; idx < 5; idx++)
5969 if (BbpR49 >= pTssiPlusBoundary[idx]) // Found the range
5970 break;
5972 // The index is the step we should increase, idx = 0 means there is nothing to compensate
5973 *pTxAgcCompensate = TxAgcStep * (idx-1);
5974 DeltaPwr += (*pTxAgcCompensate);
5975 DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R1=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5976 BbpR49, TssiRef, TxAgcStep, idx-1));
5978 else
5980 *pTxAgcCompensate = 0;
5981 DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n",
5982 BbpR49, TssiRef, TxAgcStep, 0));
5986 else
5988 if (pAd->CommonCfg.Channel <= 14)
5990 bAutoTxAgc = pAd->bAutoTxAgcG;
5991 pTxAgcCompensate = &pAd->TxAgcCompensateG;
5993 else
5995 bAutoTxAgc = pAd->bAutoTxAgcA;
5996 pTxAgcCompensate = &pAd->TxAgcCompensateA;
5999 if (bAutoTxAgc)
6000 DeltaPwr += (*pTxAgcCompensate);
6003 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1);
6004 BbpR1 &= 0xFC;
6006 /* calculate delta power based on the percentage specified from UI */
6007 // E2PROM setting is calibrated for maximum TX power (i.e. 100%)
6008 // We lower TX power here according to the percentage specified from UI
6009 if (pAd->CommonCfg.TxPowerPercentage == 0xffffffff) // AUTO TX POWER control
6011 else if (pAd->CommonCfg.TxPowerPercentage > 90) // 91 ~ 100% & AUTO, treat as 100% in terms of mW
6013 else if (pAd->CommonCfg.TxPowerPercentage > 60) // 61 ~ 90%, treat as 75% in terms of mW // DeltaPwr -= 1;
6015 DeltaPwr -= 1;
6017 else if (pAd->CommonCfg.TxPowerPercentage > 30) // 31 ~ 60%, treat as 50% in terms of mW // DeltaPwr -= 3;
6019 DeltaPwr -= 3;
6021 else if (pAd->CommonCfg.TxPowerPercentage > 15) // 16 ~ 30%, treat as 25% in terms of mW // DeltaPwr -= 6;
6023 BbpR1 |= 0x01;
6025 else if (pAd->CommonCfg.TxPowerPercentage > 9) // 10 ~ 15%, treat as 12.5% in terms of mW // DeltaPwr -= 9;
6027 BbpR1 |= 0x01;
6028 DeltaPwr -= 3;
6030 else // 0 ~ 9 %, treat as MIN(~3%) in terms of mW // DeltaPwr -= 12;
6032 BbpR1 |= 0x02;
6035 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1);
6037 /* reset different new tx power for different TX rate */
6038 for(i=0; i<5; i++)
6040 if (TxPwr[i] != 0xffffffff)
6042 for (j=0; j<8; j++)
6044 Value = (CHAR)((TxPwr[i] >> j*4) & 0x0F); /* 0 ~ 15 */
6046 if ((Value + DeltaPwr) < 0)
6048 Value = 0; /* min */
6050 else if ((Value + DeltaPwr) > 0xF)
6052 Value = 0xF; /* max */
6054 else
6056 Value += DeltaPwr; /* temperature compensation */
6059 /* fill new value to CSR offset */
6060 TxPwr[i] = (TxPwr[i] & ~(0x0000000F << j*4)) | (Value << j*4);
6063 /* write tx power value to CSR */
6064 /* TX_PWR_CFG_0 (8 tx rate) for TX power for OFDM 12M/18M
6065 TX power for OFDM 6M/9M
6066 TX power for CCK5.5M/11M
6067 TX power for CCK1M/2M */
6068 /* TX_PWR_CFG_1 ~ TX_PWR_CFG_4 */
6069 RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, TxPwr[i]);
6076 ==========================================================================
6077 Description:
6078 put PHY to sleep here, and set next wakeup timer. PHY doesn't not wakeup
6079 automatically. Instead, MCU will issue a TwakeUpInterrupt to host after
6080 the wakeup timer timeout. Driver has to issue a separate command to wake
6081 PHY up.
6083 IRQL = DISPATCH_LEVEL
6085 ==========================================================================
6087 VOID AsicSleepThenAutoWakeup(
6088 IN PRTMP_ADAPTER pAd,
6089 IN USHORT TbttNumToNextWakeUp)
6091 RT28XX_STA_SLEEP_THEN_AUTO_WAKEUP(pAd, TbttNumToNextWakeUp);
6095 ==========================================================================
6096 Description:
6097 AsicForceWakeup() is used whenever manual wakeup is required
6098 AsicForceSleep() should only be used when not in INFRA BSS. When
6099 in INFRA BSS, we should use AsicSleepThenAutoWakeup() instead.
6100 ==========================================================================
6102 VOID AsicForceSleep(
6103 IN PRTMP_ADAPTER pAd)
6109 ==========================================================================
6110 Description:
6111 AsicForceWakeup() is used whenever Twakeup timer (set via AsicSleepThenAutoWakeup)
6112 expired.
6114 IRQL = PASSIVE_LEVEL
6115 IRQL = DISPATCH_LEVEL
6116 ==========================================================================
6118 VOID AsicForceWakeup(
6119 IN PRTMP_ADAPTER pAd,
6120 IN UCHAR Level)
6122 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicForceWakeup \n"));
6123 RT28XX_STA_FORCE_WAKEUP(pAd, Level);
6127 ==========================================================================
6128 Description:
6129 Set My BSSID
6131 IRQL = DISPATCH_LEVEL
6133 ==========================================================================
6135 VOID AsicSetBssid(
6136 IN PRTMP_ADAPTER pAd,
6137 IN PUCHAR pBssid)
6139 ULONG Addr4;
6140 DBGPRINT(RT_DEBUG_TRACE, ("==============> AsicSetBssid %x:%x:%x:%x:%x:%x\n",
6141 pBssid[0],pBssid[1],pBssid[2],pBssid[3], pBssid[4],pBssid[5]));
6143 Addr4 = (ULONG)(pBssid[0]) |
6144 (ULONG)(pBssid[1] << 8) |
6145 (ULONG)(pBssid[2] << 16) |
6146 (ULONG)(pBssid[3] << 24);
6147 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4);
6149 Addr4 = 0;
6150 // always one BSSID in STA mode
6151 Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8);
6153 RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4);
6156 VOID AsicSetMcastWC(
6157 IN PRTMP_ADAPTER pAd)
6159 MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[MCAST_WCID];
6160 USHORT offset;
6162 pEntry->Sst = SST_ASSOC;
6163 pEntry->Aid = MCAST_WCID; // Softap supports 1 BSSID and use WCID=0 as multicast Wcid index
6164 pEntry->PsMode = PWR_ACTIVE;
6165 pEntry->CurrTxRate = pAd->CommonCfg.MlmeRate;
6166 offset = MAC_WCID_BASE + BSS0Mcast_WCID * HW_WCID_ENTRY_SIZE;
6170 ==========================================================================
6171 Description:
6173 IRQL = DISPATCH_LEVEL
6175 ==========================================================================
6177 VOID AsicDelWcidTab(
6178 IN PRTMP_ADAPTER pAd,
6179 IN UCHAR Wcid)
6181 ULONG Addr0 = 0x0, Addr1 = 0x0;
6182 ULONG offset;
6184 DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>Wcid = 0x%x\n",Wcid));
6185 offset = MAC_WCID_BASE + Wcid * HW_WCID_ENTRY_SIZE;
6186 RTMP_IO_WRITE32(pAd, offset, Addr0);
6187 offset += 4;
6188 RTMP_IO_WRITE32(pAd, offset, Addr1);
6192 ==========================================================================
6193 Description:
6195 IRQL = DISPATCH_LEVEL
6197 ==========================================================================
6199 VOID AsicEnableRDG(
6200 IN PRTMP_ADAPTER pAd)
6202 TX_LINK_CFG_STRUC TxLinkCfg;
6203 UINT32 Data = 0;
6205 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6206 TxLinkCfg.field.TxRDGEn = 1;
6207 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6209 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6210 Data &= 0xFFFFFF00;
6211 Data |= 0x80;
6212 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6214 //OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_AGGREGATION_INUSED);
6218 ==========================================================================
6219 Description:
6221 IRQL = DISPATCH_LEVEL
6223 ==========================================================================
6225 VOID AsicDisableRDG(
6226 IN PRTMP_ADAPTER pAd)
6228 TX_LINK_CFG_STRUC TxLinkCfg;
6229 UINT32 Data = 0;
6232 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
6233 TxLinkCfg.field.TxRDGEn = 0;
6234 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
6236 RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data);
6238 Data &= 0xFFFFFF00;
6239 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)
6240 #ifdef DOT11_N_SUPPORT
6241 && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE)
6242 #endif // DOT11_N_SUPPORT //
6245 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6246 if (pAd->CommonCfg.bEnableTxBurst)
6247 Data |= 0x20;
6249 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data);
6253 ==========================================================================
6254 Description:
6256 IRQL = PASSIVE_LEVEL
6257 IRQL = DISPATCH_LEVEL
6259 ==========================================================================
6261 VOID AsicDisableSync(
6262 IN PRTMP_ADAPTER pAd)
6264 BCN_TIME_CFG_STRUC csr;
6266 DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n"));
6268 // 2003-12-20 disable TSF and TBTT while NIC in power-saving have side effect
6269 // that NIC will never wakes up because TSF stops and no more
6270 // TBTT interrupts
6271 pAd->TbttTickCount = 0;
6272 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6273 csr.field.bBeaconGen = 0;
6274 csr.field.bTBTTEnable = 0;
6275 csr.field.TsfSyncMode = 0;
6276 csr.field.bTsfTicking = 0;
6277 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6282 ==========================================================================
6283 Description:
6285 IRQL = DISPATCH_LEVEL
6287 ==========================================================================
6289 VOID AsicEnableBssSync(
6290 IN PRTMP_ADAPTER pAd)
6292 BCN_TIME_CFG_STRUC csr;
6294 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableBssSync(INFRA mode)\n"));
6296 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word);
6298 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6300 csr.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6301 csr.field.bTsfTicking = 1;
6302 csr.field.TsfSyncMode = 1; // sync TSF in INFRASTRUCTURE mode
6303 csr.field.bBeaconGen = 0; // do NOT generate BEACON
6304 csr.field.bTBTTEnable = 1;
6307 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word);
6311 ==========================================================================
6312 Description:
6313 Note:
6314 BEACON frame in shared memory should be built ok before this routine
6315 can be called. Otherwise, a garbage frame maybe transmitted out every
6316 Beacon period.
6318 IRQL = DISPATCH_LEVEL
6320 ==========================================================================
6322 VOID AsicEnableIbssSync(
6323 IN PRTMP_ADAPTER pAd)
6325 BCN_TIME_CFG_STRUC csr9;
6326 PUCHAR ptr;
6327 UINT i;
6329 DBGPRINT(RT_DEBUG_TRACE, ("--->AsicEnableIbssSync(ADHOC mode. MPDUtotalByteCount = %d)\n", pAd->BeaconTxWI.MPDUtotalByteCount));
6331 RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr9.word);
6332 csr9.field.bBeaconGen = 0;
6333 csr9.field.bTBTTEnable = 0;
6334 csr9.field.bTsfTicking = 0;
6335 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6337 // move BEACON TXD and frame content to on-chip memory
6338 ptr = (PUCHAR)&pAd->BeaconTxWI;
6339 for (i=0; i<TXWI_SIZE; i+=4) // 16-byte TXWI field
6341 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6342 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + i, longptr);
6343 ptr += 4;
6346 // start right after the 16-byte TXWI field
6347 ptr = pAd->BeaconBuf;
6348 for (i=0; i< pAd->BeaconTxWI.MPDUtotalByteCount; i+=4)
6350 UINT32 longptr = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24);
6351 RTMP_IO_WRITE32(pAd, HW_BEACON_BASE0 + TXWI_SIZE + i, longptr);
6352 ptr +=4;
6355 // start sending BEACON
6356 csr9.field.BeaconInterval = pAd->CommonCfg.BeaconPeriod << 4; // ASIC register in units of 1/16 TU
6357 csr9.field.bTsfTicking = 1;
6358 csr9.field.TsfSyncMode = 2; // sync TSF in IBSS mode
6359 csr9.field.bTBTTEnable = 1;
6360 csr9.field.bBeaconGen = 1;
6361 RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr9.word);
6365 ==========================================================================
6366 Description:
6368 IRQL = PASSIVE_LEVEL
6369 IRQL = DISPATCH_LEVEL
6371 ==========================================================================
6373 VOID AsicSetEdcaParm(
6374 IN PRTMP_ADAPTER pAd,
6375 IN PEDCA_PARM pEdcaParm)
6377 EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg;
6378 AC_TXOP_CSR0_STRUC csr0;
6379 AC_TXOP_CSR1_STRUC csr1;
6380 AIFSN_CSR_STRUC AifsnCsr;
6381 CWMIN_CSR_STRUC CwminCsr;
6382 CWMAX_CSR_STRUC CwmaxCsr;
6383 int i;
6385 Ac0Cfg.word = 0;
6386 Ac1Cfg.word = 0;
6387 Ac2Cfg.word = 0;
6388 Ac3Cfg.word = 0;
6389 if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE))
6391 DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n"));
6392 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6393 for (i=0; i<MAX_LEN_OF_MAC_TABLE; i++)
6395 if (pAd->MacTab.Content[i].ValidAsCLI || pAd->MacTab.Content[i].ValidAsApCli)
6396 CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE);
6399 //========================================================
6400 // MAC Register has a copy .
6401 //========================================================
6402 if( pAd->CommonCfg.bEnableTxBurst )
6404 // For CWC test, change txop from 0x30 to 0x20 in TxBurst mode
6405 Ac0Cfg.field.AcTxop = 0x20; // Suggest by John for TxBurst in HT Mode
6407 else
6408 Ac0Cfg.field.AcTxop = 0; // QID_AC_BE
6409 Ac0Cfg.field.Cwmin = CW_MIN_IN_BITS;
6410 Ac0Cfg.field.Cwmax = CW_MAX_IN_BITS;
6411 Ac0Cfg.field.Aifsn = 2;
6412 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6414 Ac1Cfg.field.AcTxop = 0; // QID_AC_BK
6415 Ac1Cfg.field.Cwmin = CW_MIN_IN_BITS;
6416 Ac1Cfg.field.Cwmax = CW_MAX_IN_BITS;
6417 Ac1Cfg.field.Aifsn = 2;
6418 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6420 if (pAd->CommonCfg.PhyMode == PHY_11B)
6422 Ac2Cfg.field.AcTxop = 192; // AC_VI: 192*32us ~= 6ms
6423 Ac3Cfg.field.AcTxop = 96; // AC_VO: 96*32us ~= 3ms
6425 else
6427 Ac2Cfg.field.AcTxop = 96; // AC_VI: 96*32us ~= 3ms
6428 Ac3Cfg.field.AcTxop = 48; // AC_VO: 48*32us ~= 1.5ms
6430 Ac2Cfg.field.Cwmin = CW_MIN_IN_BITS;
6431 Ac2Cfg.field.Cwmax = CW_MAX_IN_BITS;
6432 Ac2Cfg.field.Aifsn = 2;
6433 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6434 Ac3Cfg.field.Cwmin = CW_MIN_IN_BITS;
6435 Ac3Cfg.field.Cwmax = CW_MAX_IN_BITS;
6436 Ac3Cfg.field.Aifsn = 2;
6437 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6439 //========================================================
6440 // DMA Register has a copy too.
6441 //========================================================
6442 csr0.field.Ac0Txop = 0; // QID_AC_BE
6443 csr0.field.Ac1Txop = 0; // QID_AC_BK
6444 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6445 if (pAd->CommonCfg.PhyMode == PHY_11B)
6447 csr1.field.Ac2Txop = 192; // AC_VI: 192*32us ~= 6ms
6448 csr1.field.Ac3Txop = 96; // AC_VO: 96*32us ~= 3ms
6450 else
6452 csr1.field.Ac2Txop = 96; // AC_VI: 96*32us ~= 3ms
6453 csr1.field.Ac3Txop = 48; // AC_VO: 48*32us ~= 1.5ms
6455 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6457 CwminCsr.word = 0;
6458 CwminCsr.field.Cwmin0 = CW_MIN_IN_BITS;
6459 CwminCsr.field.Cwmin1 = CW_MIN_IN_BITS;
6460 CwminCsr.field.Cwmin2 = CW_MIN_IN_BITS;
6461 CwminCsr.field.Cwmin3 = CW_MIN_IN_BITS;
6462 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6464 CwmaxCsr.word = 0;
6465 CwmaxCsr.field.Cwmax0 = CW_MAX_IN_BITS;
6466 CwmaxCsr.field.Cwmax1 = CW_MAX_IN_BITS;
6467 CwmaxCsr.field.Cwmax2 = CW_MAX_IN_BITS;
6468 CwmaxCsr.field.Cwmax3 = CW_MAX_IN_BITS;
6469 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6471 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222);
6473 NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM));
6475 else
6477 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED);
6478 //========================================================
6479 // MAC Register has a copy.
6480 //========================================================
6482 // Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27
6483 // To degrade our VIDO Queue's throughput for WiFi WMM S3T07 Issue.
6485 //pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; // rt2860c need this
6487 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE];
6488 Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE];
6489 Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE];
6490 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; //+1;
6492 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6493 Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; //+2;
6494 Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK];
6495 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; //+1;
6497 Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10;
6498 Ac2Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VI];
6499 Ac2Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VI];
6500 Ac2Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VI];
6502 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6504 // Tuning for Wi-Fi WMM S06
6505 if (pAd->CommonCfg.bWiFiTest &&
6506 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6507 Ac2Cfg.field.Aifsn -= 1;
6509 // Tuning for TGn Wi-Fi 5.2.32
6510 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6511 if (STA_TGN_WIFI_ON(pAd) &&
6512 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6514 Ac0Cfg.field.Aifsn = 3;
6515 Ac2Cfg.field.AcTxop = 5;
6519 Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO];
6520 Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO];
6521 Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO];
6522 Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO];
6524 //#ifdef WIFI_TEST
6525 if (pAd->CommonCfg.bWiFiTest)
6527 if (Ac3Cfg.field.AcTxop == 102)
6529 Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10;
6530 Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */
6531 Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK];
6532 Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK];
6533 Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI];
6534 } /* End of if */
6536 //#endif // WIFI_TEST //
6538 RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word);
6539 RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
6540 RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word);
6541 RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word);
6544 //========================================================
6545 // DMA Register has a copy too.
6546 //========================================================
6547 csr0.field.Ac0Txop = Ac0Cfg.field.AcTxop;
6548 csr0.field.Ac1Txop = Ac1Cfg.field.AcTxop;
6549 RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word);
6551 csr1.field.Ac2Txop = Ac2Cfg.field.AcTxop;
6552 csr1.field.Ac3Txop = Ac3Cfg.field.AcTxop;
6553 RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word);
6555 CwminCsr.word = 0;
6556 CwminCsr.field.Cwmin0 = pEdcaParm->Cwmin[QID_AC_BE];
6557 CwminCsr.field.Cwmin1 = pEdcaParm->Cwmin[QID_AC_BK];
6558 CwminCsr.field.Cwmin2 = pEdcaParm->Cwmin[QID_AC_VI];
6560 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6561 CwminCsr.field.Cwmin3 = pEdcaParm->Cwmin[QID_AC_VO] - 1; //for TGn wifi test
6563 RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word);
6565 CwmaxCsr.word = 0;
6566 CwmaxCsr.field.Cwmax0 = pEdcaParm->Cwmax[QID_AC_BE];
6567 CwmaxCsr.field.Cwmax1 = pEdcaParm->Cwmax[QID_AC_BK];
6568 CwmaxCsr.field.Cwmax2 = pEdcaParm->Cwmax[QID_AC_VI];
6569 CwmaxCsr.field.Cwmax3 = pEdcaParm->Cwmax[QID_AC_VO];
6570 RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word);
6572 AifsnCsr.word = 0;
6573 AifsnCsr.field.Aifsn0 = Ac0Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BE];
6574 AifsnCsr.field.Aifsn1 = Ac1Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_BK];
6575 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn; //pEdcaParm->Aifsn[QID_AC_VI];
6577 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6579 // Tuning for Wi-Fi WMM S06
6580 if (pAd->CommonCfg.bWiFiTest &&
6581 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6582 AifsnCsr.field.Aifsn2 = Ac2Cfg.field.Aifsn - 4;
6584 // Tuning for TGn Wi-Fi 5.2.32
6585 // STA TestBed changes in this item: conexant legacy sta ==> broadcom 11n sta
6586 if (STA_TGN_WIFI_ON(pAd) &&
6587 pEdcaParm->Aifsn[QID_AC_VI] == 10)
6589 AifsnCsr.field.Aifsn0 = 3;
6590 AifsnCsr.field.Aifsn2 = 7;
6594 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6595 AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn - 1; //pEdcaParm->Aifsn[QID_AC_VO]; //for TGn wifi test
6597 RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, AifsnCsr.word);
6599 NdisMoveMemory(&pAd->CommonCfg.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM));
6600 if (!ADHOC_ON(pAd))
6602 DBGPRINT(RT_DEBUG_TRACE,("EDCA [#%d]: AIFSN CWmin CWmax TXOP(us) ACM\n", pEdcaParm->EdcaUpdateCount));
6603 DBGPRINT(RT_DEBUG_TRACE,(" AC_BE %2d %2d %2d %4d %d\n",
6604 pEdcaParm->Aifsn[0],
6605 pEdcaParm->Cwmin[0],
6606 pEdcaParm->Cwmax[0],
6607 pEdcaParm->Txop[0]<<5,
6608 pEdcaParm->bACM[0]));
6609 DBGPRINT(RT_DEBUG_TRACE,(" AC_BK %2d %2d %2d %4d %d\n",
6610 pEdcaParm->Aifsn[1],
6611 pEdcaParm->Cwmin[1],
6612 pEdcaParm->Cwmax[1],
6613 pEdcaParm->Txop[1]<<5,
6614 pEdcaParm->bACM[1]));
6615 DBGPRINT(RT_DEBUG_TRACE,(" AC_VI %2d %2d %2d %4d %d\n",
6616 pEdcaParm->Aifsn[2],
6617 pEdcaParm->Cwmin[2],
6618 pEdcaParm->Cwmax[2],
6619 pEdcaParm->Txop[2]<<5,
6620 pEdcaParm->bACM[2]));
6621 DBGPRINT(RT_DEBUG_TRACE,(" AC_VO %2d %2d %2d %4d %d\n",
6622 pEdcaParm->Aifsn[3],
6623 pEdcaParm->Cwmin[3],
6624 pEdcaParm->Cwmax[3],
6625 pEdcaParm->Txop[3]<<5,
6626 pEdcaParm->bACM[3]));
6632 ==========================================================================
6633 Description:
6635 IRQL = PASSIVE_LEVEL
6636 IRQL = DISPATCH_LEVEL
6638 ==========================================================================
6640 VOID AsicSetSlotTime(
6641 IN PRTMP_ADAPTER pAd,
6642 IN BOOLEAN bUseShortSlotTime)
6644 ULONG SlotTime;
6645 UINT32 RegValue = 0;
6647 if (pAd->CommonCfg.Channel > 14)
6648 bUseShortSlotTime = TRUE;
6650 if (bUseShortSlotTime)
6651 OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6652 else
6653 OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED);
6655 SlotTime = (bUseShortSlotTime)? 9 : 20;
6657 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6659 // force using short SLOT time for FAE to demo performance when TxBurst is ON
6660 if (((pAd->StaActive.SupportedPhyInfo.bHtEnable == FALSE) && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED)))
6661 #ifdef DOT11_N_SUPPORT
6662 || ((pAd->StaActive.SupportedPhyInfo.bHtEnable == TRUE) && (pAd->CommonCfg.BACapability.field.Policy == BA_NOTUSE))
6663 #endif // DOT11_N_SUPPORT //
6666 // In this case, we will think it is doing Wi-Fi test
6667 // And we will not set to short slot when bEnableTxBurst is TRUE.
6669 else if (pAd->CommonCfg.bEnableTxBurst)
6670 SlotTime = 9;
6674 // For some reasons, always set it to short slot time.
6676 // ToDo: Should consider capability with 11B
6678 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
6680 if (pAd->StaCfg.BssType == BSS_ADHOC)
6681 SlotTime = 20;
6684 RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue);
6685 RegValue = RegValue & 0xFFFFFF00;
6687 RegValue |= SlotTime;
6689 RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue);
6693 ========================================================================
6694 Description:
6695 Add Shared key information into ASIC.
6696 Update shared key, TxMic and RxMic to Asic Shared key table
6697 Update its cipherAlg to Asic Shared key Mode.
6699 Return:
6700 ========================================================================
6702 VOID AsicAddSharedKeyEntry(
6703 IN PRTMP_ADAPTER pAd,
6704 IN UCHAR BssIndex,
6705 IN UCHAR KeyIdx,
6706 IN UCHAR CipherAlg,
6707 IN PUCHAR pKey,
6708 IN PUCHAR pTxMic,
6709 IN PUCHAR pRxMic)
6711 ULONG offset; //, csr0;
6712 SHAREDKEY_MODE_STRUC csr1;
6713 INT i;
6715 DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx));
6716 //============================================================================================
6718 DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx));
6719 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6720 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]));
6721 if (pRxMic)
6723 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6724 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
6726 if (pTxMic)
6728 DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
6729 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
6731 //============================================================================================
6733 // fill key material - key + TX MIC + RX MIC
6735 offset = SHARED_KEY_TABLE_BASE + (4*BssIndex + KeyIdx)*HW_KEY_ENTRY_SIZE;
6736 for (i=0; i<MAX_LEN_OF_SHARE_KEY; i++)
6738 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6741 offset += MAX_LEN_OF_SHARE_KEY;
6742 if (pTxMic)
6744 for (i=0; i<8; i++)
6746 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6750 offset += 8;
6751 if (pRxMic)
6753 for (i=0; i<8; i++)
6755 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6761 // Update cipher algorithm. WSTA always use BSS0
6763 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6764 DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word));
6765 if ((BssIndex%2) == 0)
6767 if (KeyIdx == 0)
6768 csr1.field.Bss0Key0CipherAlg = CipherAlg;
6769 else if (KeyIdx == 1)
6770 csr1.field.Bss0Key1CipherAlg = CipherAlg;
6771 else if (KeyIdx == 2)
6772 csr1.field.Bss0Key2CipherAlg = CipherAlg;
6773 else
6774 csr1.field.Bss0Key3CipherAlg = CipherAlg;
6776 else
6778 if (KeyIdx == 0)
6779 csr1.field.Bss1Key0CipherAlg = CipherAlg;
6780 else if (KeyIdx == 1)
6781 csr1.field.Bss1Key1CipherAlg = CipherAlg;
6782 else if (KeyIdx == 2)
6783 csr1.field.Bss1Key2CipherAlg = CipherAlg;
6784 else
6785 csr1.field.Bss1Key3CipherAlg = CipherAlg;
6787 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6788 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6792 // IRQL = DISPATCH_LEVEL
6793 VOID AsicRemoveSharedKeyEntry(
6794 IN PRTMP_ADAPTER pAd,
6795 IN UCHAR BssIndex,
6796 IN UCHAR KeyIdx)
6798 //ULONG SecCsr0;
6799 SHAREDKEY_MODE_STRUC csr1;
6801 DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx));
6803 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), &csr1.word);
6804 if ((BssIndex%2) == 0)
6806 if (KeyIdx == 0)
6807 csr1.field.Bss0Key0CipherAlg = 0;
6808 else if (KeyIdx == 1)
6809 csr1.field.Bss0Key1CipherAlg = 0;
6810 else if (KeyIdx == 2)
6811 csr1.field.Bss0Key2CipherAlg = 0;
6812 else
6813 csr1.field.Bss0Key3CipherAlg = 0;
6815 else
6817 if (KeyIdx == 0)
6818 csr1.field.Bss1Key0CipherAlg = 0;
6819 else if (KeyIdx == 1)
6820 csr1.field.Bss1Key1CipherAlg = 0;
6821 else if (KeyIdx == 2)
6822 csr1.field.Bss1Key2CipherAlg = 0;
6823 else
6824 csr1.field.Bss1Key3CipherAlg = 0;
6826 DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word));
6827 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE+4*(BssIndex/2), csr1.word);
6828 ASSERT(BssIndex < 4);
6829 ASSERT(KeyIdx < 4);
6834 VOID AsicUpdateWCIDAttribute(
6835 IN PRTMP_ADAPTER pAd,
6836 IN USHORT WCID,
6837 IN UCHAR BssIndex,
6838 IN UCHAR CipherAlg,
6839 IN BOOLEAN bUsePairewiseKeyTable)
6841 ULONG WCIDAttri = 0, offset;
6844 // Update WCID attribute.
6845 // Only TxKey could update WCID attribute.
6847 offset = MAC_WCID_ATTRIBUTE_BASE + (WCID * HW_WCID_ATTRI_SIZE);
6848 WCIDAttri = (BssIndex << 4) | (CipherAlg << 1) | (bUsePairewiseKeyTable);
6849 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
6852 VOID AsicUpdateWCIDIVEIV(
6853 IN PRTMP_ADAPTER pAd,
6854 IN USHORT WCID,
6855 IN ULONG uIV,
6856 IN ULONG uEIV)
6858 ULONG offset;
6860 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6862 RTMP_IO_WRITE32(pAd, offset, uIV);
6863 RTMP_IO_WRITE32(pAd, offset + 4, uEIV);
6866 VOID AsicUpdateRxWCIDTable(
6867 IN PRTMP_ADAPTER pAd,
6868 IN USHORT WCID,
6869 IN PUCHAR pAddr)
6871 ULONG offset;
6872 ULONG Addr;
6874 offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE);
6875 Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24);
6876 RTMP_IO_WRITE32(pAd, offset, Addr);
6877 Addr = pAddr[4] + (pAddr[5] << 8);
6878 RTMP_IO_WRITE32(pAd, offset + 4, Addr);
6883 ========================================================================
6885 Routine Description:
6886 Set Cipher Key, Cipher algorithm, IV/EIV to Asic
6888 Arguments:
6889 pAd Pointer to our adapter
6890 WCID WCID Entry number.
6891 BssIndex BSSID index, station or none multiple BSSID support
6892 this value should be 0.
6893 KeyIdx This KeyIdx will set to IV's KeyID if bTxKey enabled
6894 pCipherKey Pointer to Cipher Key.
6895 bUsePairewiseKeyTable TRUE means saved the key in SharedKey table,
6896 otherwise PairewiseKey table
6897 bTxKey This is the transmit key if enabled.
6899 Return Value:
6900 None
6902 Note:
6903 This routine will set the relative key stuff to Asic including WCID attribute,
6904 Cipher Key, Cipher algorithm and IV/EIV.
6906 IV/EIV will be update if this CipherKey is the transmission key because
6907 ASIC will base on IV's KeyID value to select Cipher Key.
6909 If bTxKey sets to FALSE, this is not the TX key, but it could be
6910 RX key
6912 For AP mode bTxKey must be always set to TRUE.
6913 ========================================================================
6915 VOID AsicAddKeyEntry(
6916 IN PRTMP_ADAPTER pAd,
6917 IN USHORT WCID,
6918 IN UCHAR BssIndex,
6919 IN UCHAR KeyIdx,
6920 IN PCIPHER_KEY pCipherKey,
6921 IN BOOLEAN bUsePairewiseKeyTable,
6922 IN BOOLEAN bTxKey)
6924 ULONG offset;
6925 UCHAR IV4 = 0;
6926 PUCHAR pKey = pCipherKey->Key;
6927 PUCHAR pTxMic = pCipherKey->TxMic;
6928 PUCHAR pRxMic = pCipherKey->RxMic;
6929 PUCHAR pTxtsc = pCipherKey->TxTsc;
6930 UCHAR CipherAlg = pCipherKey->CipherAlg;
6931 SHAREDKEY_MODE_STRUC csr1;
6932 UCHAR i;
6934 DBGPRINT(RT_DEBUG_TRACE, ("==> AsicAddKeyEntry\n"));
6936 // 1.) decide key table offset
6938 if (bUsePairewiseKeyTable)
6939 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
6940 else
6941 offset = SHARED_KEY_TABLE_BASE + (4 * BssIndex + KeyIdx) * HW_KEY_ENTRY_SIZE;
6944 // 2.) Set Key to Asic
6946 //for (i = 0; i < KeyLen; i++)
6947 for (i = 0; i < MAX_LEN_OF_PEER_KEY; i++)
6949 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
6951 offset += MAX_LEN_OF_PEER_KEY;
6954 // 3.) Set MIC key if available
6956 if (pTxMic)
6958 for (i = 0; i < 8; i++)
6960 RTMP_IO_WRITE8(pAd, offset + i, pTxMic[i]);
6963 offset += LEN_TKIP_TXMICK;
6965 if (pRxMic)
6967 for (i = 0; i < 8; i++)
6969 RTMP_IO_WRITE8(pAd, offset + i, pRxMic[i]);
6975 // 4.) Modify IV/EIV if needs
6976 // This will force Asic to use this key ID by setting IV.
6978 if (bTxKey)
6980 offset = MAC_IVEIV_TABLE_BASE + (WCID * HW_IVEIV_ENTRY_SIZE);
6982 // Write IV
6984 RTMP_IO_WRITE8(pAd, offset, pTxtsc[1]);
6985 RTMP_IO_WRITE8(pAd, offset + 1, ((pTxtsc[1] | 0x20) & 0x7f));
6986 RTMP_IO_WRITE8(pAd, offset + 2, pTxtsc[0]);
6988 IV4 = (KeyIdx << 6);
6989 if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_TKIP_NO_MIC) ||(CipherAlg == CIPHER_AES))
6990 IV4 |= 0x20; // turn on extension bit means EIV existence
6992 RTMP_IO_WRITE8(pAd, offset + 3, IV4);
6995 // Write EIV
6997 offset += 4;
6998 for (i = 0; i < 4; i++)
7000 RTMP_IO_WRITE8(pAd, offset + i, pTxtsc[i + 2]);
7003 AsicUpdateWCIDAttribute(pAd, WCID, BssIndex, CipherAlg, bUsePairewiseKeyTable);
7006 if (!bUsePairewiseKeyTable)
7009 // Only update the shared key security mode
7011 RTMP_IO_READ32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), &csr1.word);
7012 if ((BssIndex % 2) == 0)
7014 if (KeyIdx == 0)
7015 csr1.field.Bss0Key0CipherAlg = CipherAlg;
7016 else if (KeyIdx == 1)
7017 csr1.field.Bss0Key1CipherAlg = CipherAlg;
7018 else if (KeyIdx == 2)
7019 csr1.field.Bss0Key2CipherAlg = CipherAlg;
7020 else
7021 csr1.field.Bss0Key3CipherAlg = CipherAlg;
7023 else
7025 if (KeyIdx == 0)
7026 csr1.field.Bss1Key0CipherAlg = CipherAlg;
7027 else if (KeyIdx == 1)
7028 csr1.field.Bss1Key1CipherAlg = CipherAlg;
7029 else if (KeyIdx == 2)
7030 csr1.field.Bss1Key2CipherAlg = CipherAlg;
7031 else
7032 csr1.field.Bss1Key3CipherAlg = CipherAlg;
7034 RTMP_IO_WRITE32(pAd, SHARED_KEY_MODE_BASE + 4 * (BssIndex / 2), csr1.word);
7037 DBGPRINT(RT_DEBUG_TRACE, ("<== AsicAddKeyEntry\n"));
7042 ========================================================================
7043 Description:
7044 Add Pair-wise key material into ASIC.
7045 Update pairwise key, TxMic and RxMic to Asic Pair-wise key table
7047 Return:
7048 ========================================================================
7050 VOID AsicAddPairwiseKeyEntry(
7051 IN PRTMP_ADAPTER pAd,
7052 IN PUCHAR pAddr,
7053 IN UCHAR WCID,
7054 IN CIPHER_KEY *pCipherKey)
7056 INT i;
7057 ULONG offset;
7058 PUCHAR pKey = pCipherKey->Key;
7059 PUCHAR pTxMic = pCipherKey->TxMic;
7060 PUCHAR pRxMic = pCipherKey->RxMic;
7061 #ifdef DBG
7062 UCHAR CipherAlg = pCipherKey->CipherAlg;
7063 #endif // DBG //
7065 // EKEY
7066 offset = PAIRWISE_KEY_TABLE_BASE + (WCID * HW_KEY_ENTRY_SIZE);
7067 for (i=0; i<MAX_LEN_OF_PEER_KEY; i++)
7069 RTMP_IO_WRITE8(pAd, offset + i, pKey[i]);
7071 for (i=0; i<MAX_LEN_OF_PEER_KEY; i+=4)
7073 UINT32 Value;
7074 RTMP_IO_READ32(pAd, offset + i, &Value);
7077 offset += MAX_LEN_OF_PEER_KEY;
7079 // MIC KEY
7080 if (pTxMic)
7082 for (i=0; i<8; i++)
7084 RTMP_IO_WRITE8(pAd, offset+i, pTxMic[i]);
7087 offset += 8;
7088 if (pRxMic)
7090 for (i=0; i<8; i++)
7092 RTMP_IO_WRITE8(pAd, offset+i, pRxMic[i]);
7096 DBGPRINT(RT_DEBUG_TRACE,("AsicAddPairwiseKeyEntry: WCID #%d Alg=%s\n",WCID, CipherName[CipherAlg]));
7097 DBGPRINT(RT_DEBUG_TRACE,(" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7098 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]));
7099 if (pRxMic)
7101 DBGPRINT(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7102 pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7]));
7104 if (pTxMic)
7106 DBGPRINT(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
7107 pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7]));
7111 ========================================================================
7112 Description:
7113 Remove Pair-wise key material from ASIC.
7115 Return:
7116 ========================================================================
7118 VOID AsicRemovePairwiseKeyEntry(
7119 IN PRTMP_ADAPTER pAd,
7120 IN UCHAR BssIdx,
7121 IN UCHAR Wcid)
7123 ULONG WCIDAttri;
7124 USHORT offset;
7126 // re-set the entry's WCID attribute as OPEN-NONE.
7127 offset = MAC_WCID_ATTRIBUTE_BASE + (Wcid * HW_WCID_ATTRI_SIZE);
7128 WCIDAttri = (BssIdx<<4) | PAIRWISEKEYTABLE;
7129 RTMP_IO_WRITE32(pAd, offset, WCIDAttri);
7132 BOOLEAN AsicSendCommandToMcu(
7133 IN PRTMP_ADAPTER pAd,
7134 IN UCHAR Command,
7135 IN UCHAR Token,
7136 IN UCHAR Arg0,
7137 IN UCHAR Arg1)
7139 HOST_CMD_CSR_STRUC H2MCmd;
7140 H2M_MAILBOX_STRUC H2MMailbox;
7141 ULONG i = 0;
7145 RTMP_IO_READ32(pAd, H2M_MAILBOX_CSR, &H2MMailbox.word);
7146 if (H2MMailbox.field.Owner == 0)
7147 break;
7149 RTMPusecDelay(2);
7150 } while(i++ < 100);
7152 if (i >= 100)
7155 UINT32 Data;
7157 // Reset DMA
7158 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7159 Data |= 0x2;
7160 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7162 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
7163 // Reset DMA/CPU ring index
7164 RTMPRingCleanUp(pAd, QID_AC_BK);
7165 RTMPRingCleanUp(pAd, QID_AC_BE);
7166 RTMPRingCleanUp(pAd, QID_AC_VI);
7167 RTMPRingCleanUp(pAd, QID_AC_VO);
7168 RTMPRingCleanUp(pAd, QID_HCCA);
7169 RTMPRingCleanUp(pAd, QID_MGMT);
7170 RTMPRingCleanUp(pAd, QID_RX);
7172 // Clear Reset
7173 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
7174 Data &= 0xfffffffd;
7175 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
7176 DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
7178 //return FALSE;
7181 H2MMailbox.field.Owner = 1; // pass ownership to MCU
7182 H2MMailbox.field.CmdToken = Token;
7183 H2MMailbox.field.HighByte = Arg1;
7184 H2MMailbox.field.LowByte = Arg0;
7185 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CSR, H2MMailbox.word);
7187 H2MCmd.word = 0;
7188 H2MCmd.field.HostCommand = Command;
7189 RTMP_IO_WRITE32(pAd, HOST_CMD_CSR, H2MCmd.word);
7191 if (Command != 0x80)
7195 return TRUE;
7198 BOOLEAN AsicCheckCommanOk(
7199 IN PRTMP_ADAPTER pAd,
7200 IN UCHAR Command)
7202 UINT32 CmdStatus = 0, CID = 0, i;
7203 UINT32 ThisCIDMask = 0;
7205 i = 0;
7208 RTMP_IO_READ32(pAd, H2M_MAILBOX_CID, &CID);
7209 // Find where the command is. Because this is randomly specified by firmware.
7210 if ((CID & CID0MASK) == Command)
7212 ThisCIDMask = CID0MASK;
7213 break;
7215 else if ((((CID & CID1MASK)>>8) & 0xff) == Command)
7217 ThisCIDMask = CID1MASK;
7218 break;
7220 else if ((((CID & CID2MASK)>>16) & 0xff) == Command)
7222 ThisCIDMask = CID2MASK;
7223 break;
7225 else if ((((CID & CID3MASK)>>24) & 0xff) == Command)
7227 ThisCIDMask = CID3MASK;
7228 break;
7231 RTMPusecDelay(100);
7232 i++;
7233 }while (i < 200);
7235 // Get CommandStatus Value
7236 RTMP_IO_READ32(pAd, H2M_MAILBOX_STATUS, &CmdStatus);
7238 // This command's status is at the same position as command. So AND command position's bitmask to read status.
7239 if (i < 200)
7241 // If Status is 1, the comamnd is success.
7242 if (((CmdStatus & ThisCIDMask) == 0x1) || ((CmdStatus & ThisCIDMask) == 0x100)
7243 || ((CmdStatus & ThisCIDMask) == 0x10000) || ((CmdStatus & ThisCIDMask) == 0x1000000))
7245 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanOk CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7246 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7247 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7248 return TRUE;
7250 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail1 CID = 0x%x, CmdStatus= 0x%x \n", CID, CmdStatus));
7252 else
7254 DBGPRINT(RT_DEBUG_TRACE, ("--> AsicCheckCommanFail2 Timeout Command = %d, CmdStatus= 0x%x \n", Command, CmdStatus));
7256 // Clear Command and Status.
7257 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff);
7258 RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff);
7260 return FALSE;
7264 ========================================================================
7266 Routine Description:
7267 Verify the support rate for different PHY type
7269 Arguments:
7270 pAd Pointer to our adapter
7272 Return Value:
7273 None
7275 IRQL = PASSIVE_LEVEL
7277 ========================================================================
7279 VOID RTMPCheckRates(
7280 IN PRTMP_ADAPTER pAd,
7281 IN OUT UCHAR SupRate[],
7282 IN OUT UCHAR *SupRateLen)
7284 UCHAR RateIdx, i, j;
7285 UCHAR NewRate[12], NewRateLen;
7287 NewRateLen = 0;
7289 if (pAd->CommonCfg.PhyMode == PHY_11B)
7290 RateIdx = 4;
7291 else
7292 RateIdx = 12;
7294 // Check for support rates exclude basic rate bit
7295 for (i = 0; i < *SupRateLen; i++)
7296 for (j = 0; j < RateIdx; j++)
7297 if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7298 NewRate[NewRateLen++] = SupRate[i];
7300 *SupRateLen = NewRateLen;
7301 NdisMoveMemory(SupRate, NewRate, NewRateLen);
7304 #ifdef DOT11_N_SUPPORT
7305 BOOLEAN RTMPCheckChannel(
7306 IN PRTMP_ADAPTER pAd,
7307 IN UCHAR CentralChannel,
7308 IN UCHAR Channel)
7310 UCHAR k;
7311 UCHAR UpperChannel = 0, LowerChannel = 0;
7312 UCHAR NoEffectChannelinList = 0;
7314 // Find upper and lower channel according to 40MHz current operation.
7315 if (CentralChannel < Channel)
7317 UpperChannel = Channel;
7318 if (CentralChannel > 2)
7319 LowerChannel = CentralChannel - 2;
7320 else
7321 return FALSE;
7323 else if (CentralChannel > Channel)
7325 UpperChannel = CentralChannel + 2;
7326 LowerChannel = Channel;
7329 for (k = 0;k < pAd->ChannelListNum;k++)
7331 if (pAd->ChannelList[k].Channel == UpperChannel)
7333 NoEffectChannelinList ++;
7335 if (pAd->ChannelList[k].Channel == LowerChannel)
7337 NoEffectChannelinList ++;
7341 DBGPRINT(RT_DEBUG_TRACE,("Total Channel in Channel List = [%d]\n", NoEffectChannelinList));
7342 if (NoEffectChannelinList == 2)
7343 return TRUE;
7344 else
7345 return FALSE;
7349 ========================================================================
7351 Routine Description:
7352 Verify the support rate for HT phy type
7354 Arguments:
7355 pAd Pointer to our adapter
7357 Return Value:
7358 FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode)
7360 IRQL = PASSIVE_LEVEL
7362 ========================================================================
7364 BOOLEAN RTMPCheckHt(
7365 IN PRTMP_ADAPTER pAd,
7366 IN UCHAR Wcid,
7367 IN HT_CAPABILITY_IE *pHtCapability,
7368 IN ADD_HT_INFO_IE *pAddHtInfo)
7370 if (Wcid >= MAX_LEN_OF_MAC_TABLE)
7371 return FALSE;
7373 // If use AMSDU, set flag.
7374 if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable)
7375 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_AMSDU_INUSED);
7376 // Save Peer Capability
7377 if (pHtCapability->HtCapInfo.ShortGIfor20)
7378 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI20_CAPABLE);
7379 if (pHtCapability->HtCapInfo.ShortGIfor40)
7380 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_SGI40_CAPABLE);
7381 if (pHtCapability->HtCapInfo.TxSTBC)
7382 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_TxSTBC_CAPABLE);
7383 if (pHtCapability->HtCapInfo.RxSTBC)
7384 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RxSTBC_CAPABLE);
7385 if (pAd->CommonCfg.bRdg && pHtCapability->ExtHtCapInfo.RDGSupport)
7387 CLIENT_STATUS_SET_FLAG(&pAd->MacTab.Content[Wcid], fCLIENT_STATUS_RDG_CAPABLE);
7390 if (Wcid < MAX_LEN_OF_MAC_TABLE)
7392 pAd->MacTab.Content[Wcid].MpduDensity = pHtCapability->HtCapParm.MpduDensity;
7395 // Will check ChannelWidth for MCSSet[4] below
7396 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x1;
7397 switch (pAd->CommonCfg.RxStream)
7399 case 1:
7400 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7401 pAd->MlmeAux.HtCapability.MCSSet[1] = 0x00;
7402 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7403 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7404 break;
7405 case 2:
7406 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7407 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7408 pAd->MlmeAux.HtCapability.MCSSet[2] = 0x00;
7409 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7410 break;
7411 case 3:
7412 pAd->MlmeAux.HtCapability.MCSSet[0] = 0xff;
7413 pAd->MlmeAux.HtCapability.MCSSet[1] = 0xff;
7414 pAd->MlmeAux.HtCapability.MCSSet[2] = 0xff;
7415 pAd->MlmeAux.HtCapability.MCSSet[3] = 0x00;
7416 break;
7419 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & pAd->CommonCfg.DesiredHtPhy.ChannelWidth;
7421 DBGPRINT(RT_DEBUG_TRACE, ("RTMPCheckHt:: HtCapInfo.ChannelWidth=%d, RecomWidth=%d, DesiredHtPhy.ChannelWidth=%d, BW40MAvailForA/G=%d/%d, PhyMode=%d \n",
7422 pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth, pAddHtInfo->AddHtInfo.RecomWidth, pAd->CommonCfg.DesiredHtPhy.ChannelWidth,
7423 pAd->NicConfig2.field.BW40MAvailForA, pAd->NicConfig2.field.BW40MAvailForG, pAd->CommonCfg.PhyMode));
7425 pAd->MlmeAux.HtCapability.HtCapInfo.GF = pHtCapability->HtCapInfo.GF &pAd->CommonCfg.DesiredHtPhy.GF;
7427 // Send Assoc Req with my HT capability.
7428 pAd->MlmeAux.HtCapability.HtCapInfo.AMsduSize = pAd->CommonCfg.DesiredHtPhy.AmsduSize;
7429 pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs = pAd->CommonCfg.DesiredHtPhy.MimoPs;
7430 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20);
7431 pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40 = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40);
7432 pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC = (pAd->CommonCfg.DesiredHtPhy.TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC);
7433 pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC = (pAd->CommonCfg.DesiredHtPhy.RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC);
7434 pAd->MlmeAux.HtCapability.HtCapParm.MaxRAmpduFactor = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor;
7435 pAd->MlmeAux.HtCapability.HtCapParm.MpduDensity = pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity;
7436 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7437 pAd->MacTab.Content[Wcid].HTCapability.ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC;
7438 if (pAd->CommonCfg.bRdg)
7440 pAd->MlmeAux.HtCapability.ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport;
7441 pAd->MlmeAux.HtCapability.ExtHtCapInfo.PlusHTC = 1;
7444 if (pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth == BW_20)
7445 pAd->MlmeAux.HtCapability.MCSSet[4] = 0x0; // BW20 can't transmit MCS32
7447 COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability);
7448 return TRUE;
7450 #endif // DOT11_N_SUPPORT //
7453 ========================================================================
7455 Routine Description:
7456 Verify the support rate for different PHY type
7458 Arguments:
7459 pAd Pointer to our adapter
7461 Return Value:
7462 None
7464 IRQL = PASSIVE_LEVEL
7466 ========================================================================
7468 VOID RTMPUpdateMlmeRate(
7469 IN PRTMP_ADAPTER pAd)
7471 UCHAR MinimumRate;
7472 UCHAR ProperMlmeRate; //= RATE_54;
7473 UCHAR i, j, RateIdx = 12; //1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54
7474 BOOLEAN bMatch = FALSE;
7476 switch (pAd->CommonCfg.PhyMode)
7478 case PHY_11B:
7479 ProperMlmeRate = RATE_11;
7480 MinimumRate = RATE_1;
7481 break;
7482 case PHY_11BG_MIXED:
7483 #ifdef DOT11_N_SUPPORT
7484 case PHY_11ABGN_MIXED:
7485 case PHY_11BGN_MIXED:
7486 #endif // DOT11_N_SUPPORT //
7487 if ((pAd->MlmeAux.SupRateLen == 4) &&
7488 (pAd->MlmeAux.ExtRateLen == 0))
7489 // B only AP
7490 ProperMlmeRate = RATE_11;
7491 else
7492 ProperMlmeRate = RATE_24;
7494 if (pAd->MlmeAux.Channel <= 14)
7495 MinimumRate = RATE_1;
7496 else
7497 MinimumRate = RATE_6;
7498 break;
7499 case PHY_11A:
7500 #ifdef DOT11_N_SUPPORT
7501 case PHY_11N_2_4G: // rt2860 need to check mlmerate for 802.11n
7502 case PHY_11GN_MIXED:
7503 case PHY_11AGN_MIXED:
7504 case PHY_11AN_MIXED:
7505 case PHY_11N_5G:
7506 #endif // DOT11_N_SUPPORT //
7507 ProperMlmeRate = RATE_24;
7508 MinimumRate = RATE_6;
7509 break;
7510 case PHY_11ABG_MIXED:
7511 ProperMlmeRate = RATE_24;
7512 if (pAd->MlmeAux.Channel <= 14)
7513 MinimumRate = RATE_1;
7514 else
7515 MinimumRate = RATE_6;
7516 break;
7517 default: // error
7518 ProperMlmeRate = RATE_1;
7519 MinimumRate = RATE_1;
7520 break;
7523 for (i = 0; i < pAd->MlmeAux.SupRateLen; i++)
7525 for (j = 0; j < RateIdx; j++)
7527 if ((pAd->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j])
7529 if (j == ProperMlmeRate)
7531 bMatch = TRUE;
7532 break;
7537 if (bMatch)
7538 break;
7541 if (bMatch == FALSE)
7543 for (i = 0; i < pAd->MlmeAux.ExtRateLen; i++)
7545 for (j = 0; j < RateIdx; j++)
7547 if ((pAd->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j])
7549 if (j == ProperMlmeRate)
7551 bMatch = TRUE;
7552 break;
7557 if (bMatch)
7558 break;
7562 if (bMatch == FALSE)
7564 ProperMlmeRate = MinimumRate;
7567 pAd->CommonCfg.MlmeRate = MinimumRate;
7568 pAd->CommonCfg.RtsRate = ProperMlmeRate;
7569 if (pAd->CommonCfg.MlmeRate >= RATE_6)
7571 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM;
7572 pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7573 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM;
7574 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate];
7576 else
7578 pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK;
7579 pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate;
7580 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK;
7581 pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate;
7584 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateMlmeRate ==> MlmeTransmit = 0x%x \n" , pAd->CommonCfg.MlmeTransmit.word));
7587 CHAR RTMPMaxRssi(
7588 IN PRTMP_ADAPTER pAd,
7589 IN CHAR Rssi0,
7590 IN CHAR Rssi1,
7591 IN CHAR Rssi2)
7593 CHAR larger = -127;
7595 if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 != 0))
7597 larger = Rssi0;
7600 if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 != 0))
7602 larger = max(Rssi0, Rssi1);
7605 if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 != 0))
7607 larger = max(larger, Rssi2);
7610 if (larger == -127)
7611 larger = 0;
7613 return larger;
7617 ========================================================================
7618 Routine Description:
7619 Periodic evaluate antenna link status
7621 Arguments:
7622 pAd - Adapter pointer
7624 Return Value:
7625 None
7627 ========================================================================
7629 VOID AsicEvaluateRxAnt(
7630 IN PRTMP_ADAPTER pAd)
7632 UCHAR BBPR3 = 0;
7634 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7636 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS |
7637 fRTMP_ADAPTER_HALT_IN_PROGRESS |
7638 fRTMP_ADAPTER_RADIO_OFF |
7639 fRTMP_ADAPTER_NIC_NOT_EXIST |
7640 fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))
7641 return;
7643 if (pAd->StaCfg.Psm == PWR_SAVE)
7644 return;
7647 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7648 BBPR3 &= (~0x18);
7649 if(pAd->Antenna.field.RxPath == 3)
7651 BBPR3 |= (0x10);
7653 else if(pAd->Antenna.field.RxPath == 2)
7655 BBPR3 |= (0x8);
7657 else if(pAd->Antenna.field.RxPath == 1)
7659 BBPR3 |= (0x0);
7661 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7663 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7664 pAd->StaCfg.BBPR3 = BBPR3;
7666 if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7669 ULONG TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
7670 pAd->RalinkCounters.OneSecTxRetryOkCount +
7671 pAd->RalinkCounters.OneSecTxFailCount;
7673 if (TxTotalCnt > 50)
7675 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
7676 pAd->Mlme.bLowThroughput = FALSE;
7678 else
7680 RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
7681 pAd->Mlme.bLowThroughput = TRUE;
7687 ========================================================================
7688 Routine Description:
7689 After evaluation, check antenna link status
7691 Arguments:
7692 pAd - Adapter pointer
7694 Return Value:
7695 None
7697 ========================================================================
7699 VOID AsicRxAntEvalTimeout(
7700 IN PVOID SystemSpecific1,
7701 IN PVOID FunctionContext,
7702 IN PVOID SystemSpecific2,
7703 IN PVOID SystemSpecific3)
7705 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7706 UCHAR BBPR3 = 0;
7707 CHAR larger = -127, rssi0, rssi1, rssi2;
7709 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7711 if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS) ||
7712 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) ||
7713 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF) ||
7714 RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
7715 return;
7717 if (pAd->StaCfg.Psm == PWR_SAVE)
7718 return;
7721 // if the traffic is low, use average rssi as the criteria
7722 if (pAd->Mlme.bLowThroughput == TRUE)
7724 rssi0 = pAd->StaCfg.RssiSample.LastRssi0;
7725 rssi1 = pAd->StaCfg.RssiSample.LastRssi1;
7726 rssi2 = pAd->StaCfg.RssiSample.LastRssi2;
7728 else
7730 rssi0 = pAd->StaCfg.RssiSample.AvgRssi0;
7731 rssi1 = pAd->StaCfg.RssiSample.AvgRssi1;
7732 rssi2 = pAd->StaCfg.RssiSample.AvgRssi2;
7735 if(pAd->Antenna.field.RxPath == 3)
7737 larger = max(rssi0, rssi1);
7739 if (larger > (rssi2 + 20))
7740 pAd->Mlme.RealRxPath = 2;
7741 else
7742 pAd->Mlme.RealRxPath = 3;
7744 else if(pAd->Antenna.field.RxPath == 2)
7746 if (rssi0 > (rssi1 + 20))
7747 pAd->Mlme.RealRxPath = 1;
7748 else
7749 pAd->Mlme.RealRxPath = 2;
7752 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R3, &BBPR3);
7753 BBPR3 &= (~0x18);
7754 if(pAd->Mlme.RealRxPath == 3)
7756 BBPR3 |= (0x10);
7758 else if(pAd->Mlme.RealRxPath == 2)
7760 BBPR3 |= (0x8);
7762 else if(pAd->Mlme.RealRxPath == 1)
7764 BBPR3 |= (0x0);
7766 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R3, BBPR3);
7767 pAd->StaCfg.BBPR3 = BBPR3;
7773 VOID APSDPeriodicExec(
7774 IN PVOID SystemSpecific1,
7775 IN PVOID FunctionContext,
7776 IN PVOID SystemSpecific2,
7777 IN PVOID SystemSpecific3)
7779 RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
7781 if (!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))
7782 return;
7784 pAd->CommonCfg.TriggerTimerCount++;
7789 ========================================================================
7790 Routine Description:
7791 Set/reset MAC registers according to bPiggyBack parameter
7793 Arguments:
7794 pAd - Adapter pointer
7795 bPiggyBack - Enable / Disable Piggy-Back
7797 Return Value:
7798 None
7800 ========================================================================
7802 VOID RTMPSetPiggyBack(
7803 IN PRTMP_ADAPTER pAd,
7804 IN BOOLEAN bPiggyBack)
7806 TX_LINK_CFG_STRUC TxLinkCfg;
7808 RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word);
7810 TxLinkCfg.field.TxCFAckEn = bPiggyBack;
7811 RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word);
7815 ========================================================================
7816 Routine Description:
7817 check if this entry need to switch rate automatically
7819 Arguments:
7821 pEntry
7823 Return Value:
7824 TURE
7825 FALSE
7827 ========================================================================
7829 BOOLEAN RTMPCheckEntryEnableAutoRateSwitch(
7830 IN PRTMP_ADAPTER pAd,
7831 IN PMAC_TABLE_ENTRY pEntry)
7833 BOOLEAN result = TRUE;
7835 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7837 // only associated STA counts
7838 if (pEntry && (pEntry->ValidAsCLI) && (pEntry->Sst == SST_ASSOC))
7840 result = pAd->StaCfg.bAutoTxRateSwitch;
7842 else
7843 result = FALSE;
7846 return result;
7850 BOOLEAN RTMPAutoRateSwitchCheck(
7851 IN PRTMP_ADAPTER pAd)
7853 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7855 if (pAd->StaCfg.bAutoTxRateSwitch)
7856 return TRUE;
7859 return FALSE;
7864 ========================================================================
7865 Routine Description:
7866 check if this entry need to fix tx legacy rate
7868 Arguments:
7870 pEntry
7872 Return Value:
7873 TURE
7874 FALSE
7876 ========================================================================
7878 UCHAR RTMPStaFixedTxMode(
7879 IN PRTMP_ADAPTER pAd,
7880 IN PMAC_TABLE_ENTRY pEntry)
7882 UCHAR tx_mode = FIXED_TXMODE_HT;
7884 IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
7886 tx_mode = (UCHAR)pAd->StaCfg.DesiredTransmitSetting.field.FixedTxMode;
7889 return tx_mode;
7893 ========================================================================
7894 Routine Description:
7895 Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified.
7897 Arguments:
7899 pEntry
7901 Return Value:
7902 TURE
7903 FALSE
7905 ========================================================================
7907 VOID RTMPUpdateLegacyTxSetting(
7908 UCHAR fixed_tx_mode,
7909 PMAC_TABLE_ENTRY pEntry)
7911 HTTRANSMIT_SETTING TransmitSetting;
7913 if (fixed_tx_mode == FIXED_TXMODE_HT)
7914 return;
7916 TransmitSetting.word = 0;
7918 TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE;
7919 TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS;
7921 if (fixed_tx_mode == FIXED_TXMODE_CCK)
7923 TransmitSetting.field.MODE = MODE_CCK;
7924 // CCK mode allow MCS 0~3
7925 if (TransmitSetting.field.MCS > MCS_3)
7926 TransmitSetting.field.MCS = MCS_3;
7928 else
7930 TransmitSetting.field.MODE = MODE_OFDM;
7931 // OFDM mode allow MCS 0~7
7932 if (TransmitSetting.field.MCS > MCS_7)
7933 TransmitSetting.field.MCS = MCS_7;
7936 if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE)
7938 pEntry->HTPhyMode.word = TransmitSetting.word;
7939 DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n",
7940 pEntry->Aid, GetPhyMode(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS));
7945 ==========================================================================
7946 Description:
7947 dynamic tune BBP R66 to find a balance between sensibility and
7948 noise isolation
7950 IRQL = DISPATCH_LEVEL
7952 ==========================================================================
7954 VOID AsicStaBbpTuning(
7955 IN PRTMP_ADAPTER pAd)
7957 UCHAR OrigR66Value = 0, R66;//, R66UpperBound = 0x30, R66LowerBound = 0x30;
7958 CHAR Rssi;
7960 // 2860C did not support Fase CCA, therefore can't tune
7961 if (pAd->MACVersion == 0x28600100)
7962 return;
7965 // work as a STA
7967 if (pAd->Mlme.CntlMachine.CurrState != CNTL_IDLE) // no R66 tuning when SCANNING
7968 return;
7970 if ((pAd->OpMode == OPMODE_STA)
7971 && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)
7973 && !(OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
7974 && (pAd->bPCIclkOff == FALSE))
7976 RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R66, &OrigR66Value);
7977 R66 = OrigR66Value;
7979 if (pAd->Antenna.field.RxPath > 1)
7980 Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1;
7981 else
7982 Rssi = pAd->StaCfg.RssiSample.AvgRssi0;
7984 if (pAd->LatchRfRegs.Channel <= 14)
7985 { //BG band
7987 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
7989 R66 = (0x2E + GET_LNA_GAIN(pAd)) + 0x10;
7990 if (OrigR66Value != R66)
7992 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
7995 else
7997 R66 = 0x2E + GET_LNA_GAIN(pAd);
7998 if (OrigR66Value != R66)
8000 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8005 else
8006 { //A band
8007 if (pAd->CommonCfg.BBPCurrentBW == BW_20)
8009 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8011 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8012 if (OrigR66Value != R66)
8014 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8017 else
8019 R66 = 0x32 + (GET_LNA_GAIN(pAd)*5)/3;
8020 if (OrigR66Value != R66)
8022 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8026 else
8028 if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
8030 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3 + 0x10;
8031 if (OrigR66Value != R66)
8033 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8036 else
8038 R66 = 0x3A + (GET_LNA_GAIN(pAd)*5)/3;
8039 if (OrigR66Value != R66)
8041 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8051 VOID AsicResetFromDMABusy(
8052 IN PRTMP_ADAPTER pAd)
8054 UINT32 Data;
8055 BOOLEAN bCtrl = FALSE;
8057 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8059 // Be sure restore link control value so we can write register.
8060 RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8061 if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_SET_PCI_CLK_OFF_COMMAND))
8063 DBGPRINT(RT_DEBUG_TRACE,("AsicResetFromDMABusy==>\n"));
8064 RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_HALT);
8065 RTMPusecDelay(6000);
8066 pAd->bPCIclkOff = FALSE;
8067 bCtrl = TRUE;
8069 // Reset DMA
8070 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8071 Data |= 0x2;
8072 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8074 // After Reset DMA, DMA index will become Zero. So Driver need to reset all ring indexs too.
8075 // Reset DMA/CPU ring index
8076 RTMPRingCleanUp(pAd, QID_AC_BK);
8077 RTMPRingCleanUp(pAd, QID_AC_BE);
8078 RTMPRingCleanUp(pAd, QID_AC_VI);
8079 RTMPRingCleanUp(pAd, QID_AC_VO);
8080 RTMPRingCleanUp(pAd, QID_HCCA);
8081 RTMPRingCleanUp(pAd, QID_MGMT);
8082 RTMPRingCleanUp(pAd, QID_RX);
8084 // Clear Reset
8085 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8086 Data &= 0xfffffffd;
8087 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8089 // If in Radio off, should call RTMPPCIePowerLinkCtrl again.
8090 if ((bCtrl == TRUE) && (pAd->StaCfg.bRadio == FALSE))
8091 RTMPPCIeLinkCtrlSetting(pAd, 3);
8093 RTMP_SET_PSFLAG(pAd, fRTMP_PS_CAN_GO_SLEEP);
8094 RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS);
8095 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetFromDMABusy !!!!!!!!!!!!!!!!!!!!!!! \n"));
8098 VOID AsicResetBBP(
8099 IN PRTMP_ADAPTER pAd)
8101 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8103 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0);
8104 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x2);
8105 RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0xc);
8107 // After hard-reset BBP, initialize all BBP values.
8108 NICRestoreBBPValue(pAd);
8109 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset BBP !!!!!!!!!!!!!!!!!!!!!!! \n"));
8112 VOID AsicResetMAC(
8113 IN PRTMP_ADAPTER pAd)
8115 ULONG Data;
8117 DBGPRINT(RT_DEBUG_TRACE, ("---> AsicResetMAC !!!! \n"));
8118 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8119 Data |= 0x4;
8120 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8121 Data &= 0xfffffffb;
8122 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8124 DBGPRINT(RT_DEBUG_TRACE, ("<--- AsicResetMAC !!!! \n"));
8127 VOID AsicResetPBF(
8128 IN PRTMP_ADAPTER pAd)
8130 ULONG Value1, Value2;
8131 ULONG Data;
8133 RTMP_IO_READ32(pAd, TXRXQ_PCNT, &Value1);
8134 RTMP_IO_READ32(pAd, PBF_DBG, &Value2);
8136 Value2 &= 0xff;
8137 // sum should be equals to 0xff, which is the total buffer size.
8138 if ((Value1 + Value2) < 0xff)
8140 DBGPRINT(RT_DEBUG_TRACE, ("---> Asic HardReset PBF !!!! \n"));
8141 RTMP_IO_READ32(pAd, PBF_SYS_CTRL, &Data);
8142 Data |= 0x8;
8143 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8144 Data &= 0xfffffff7;
8145 RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, Data);
8147 DBGPRINT(RT_DEBUG_TRACE, ("<--- Asic HardReset PBF !!!! \n"));
8151 VOID RTMPSetAGCInitValue(
8152 IN PRTMP_ADAPTER pAd,
8153 IN UCHAR BandWidth)
8155 UCHAR R66 = 0x30;
8157 if (pAd->LatchRfRegs.Channel <= 14)
8158 { // BG band
8159 R66 = 0x2E + GET_LNA_GAIN(pAd);
8160 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8162 else
8163 { //A band
8164 if (BandWidth == BW_20)
8166 R66 = (UCHAR)(0x32 + (GET_LNA_GAIN(pAd)*5)/3);
8167 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8169 #ifdef DOT11_N_SUPPORT
8170 else
8172 R66 = (UCHAR)(0x3A + (GET_LNA_GAIN(pAd)*5)/3);
8173 RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
8175 #endif // DOT11_N_SUPPORT //
8180 VOID AsicTurnOffRFClk(
8181 IN PRTMP_ADAPTER pAd,
8182 IN UCHAR Channel)
8185 // RF R2 bit 18 = 0
8186 UINT32 R1 = 0, R2 = 0, R3 = 0;
8187 UCHAR index;
8188 RTMP_RF_REGS *RFRegTable;
8190 RFRegTable = RF2850RegTable;
8192 switch (pAd->RfIcType)
8194 case RFIC_2820:
8195 case RFIC_2850:
8196 case RFIC_2720:
8197 case RFIC_2750:
8199 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8201 if (Channel == RFRegTable[index].Channel)
8203 R1 = RFRegTable[index].R1 & 0xffffdfff;
8204 R2 = RFRegTable[index].R2 & 0xfffbffff;
8205 R3 = RFRegTable[index].R3 & 0xfff3ffff;
8207 RTMP_RF_IO_WRITE32(pAd, R1);
8208 RTMP_RF_IO_WRITE32(pAd, R2);
8210 // Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0.
8211 // Set RF R2 bit18=0, R3 bit[18:19]=0
8212 //if (pAd->StaCfg.bRadio == FALSE)
8213 if (1)
8215 RTMP_RF_IO_WRITE32(pAd, R3);
8217 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n",
8218 Channel, pAd->RfIcType, R2, R3));
8220 else
8221 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n",
8222 Channel, pAd->RfIcType, R2));
8223 break;
8226 break;
8228 default:
8229 break;
8234 VOID AsicTurnOnRFClk(
8235 IN PRTMP_ADAPTER pAd,
8236 IN UCHAR Channel)
8239 // RF R2 bit 18 = 0
8240 UINT32 R1 = 0, R2 = 0, R3 = 0;
8241 UCHAR index;
8242 RTMP_RF_REGS *RFRegTable;
8244 RFRegTable = RF2850RegTable;
8246 switch (pAd->RfIcType)
8248 case RFIC_2820:
8249 case RFIC_2850:
8250 case RFIC_2720:
8251 case RFIC_2750:
8253 for (index = 0; index < NUM_OF_2850_CHNL; index++)
8255 if (Channel == RFRegTable[index].Channel)
8257 R3 = pAd->LatchRfRegs.R3;
8258 R3 &= 0xfff3ffff;
8259 R3 |= 0x00080000;
8260 RTMP_RF_IO_WRITE32(pAd, R3);
8262 R1 = RFRegTable[index].R1;
8263 RTMP_RF_IO_WRITE32(pAd, R1);
8265 R2 = RFRegTable[index].R2;
8266 if (pAd->Antenna.field.TxPath == 1)
8268 R2 |= 0x4000; // If TXpath is 1, bit 14 = 1;
8271 if (pAd->Antenna.field.RxPath == 2)
8273 R2 |= 0x40; // write 1 to off Rxpath.
8275 else if (pAd->Antenna.field.RxPath == 1)
8277 R2 |= 0x20040; // write 1 to off RxPath
8279 RTMP_RF_IO_WRITE32(pAd, R2);
8281 break;
8284 break;
8286 default:
8287 break;
8290 DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOnRFClk#%d(RF=%d, ) , R2=0x%08x\n",
8291 Channel,
8292 pAd->RfIcType,
8293 R2));